读写整数1通道纹理opengl

时间:2015-08-24 14:06:42

标签: opengl textures glsl

我想:

  1. 创建一个包含整数的可读写1通道纹理。
  2. 使用着色器,写整数" I"纹理。
  3. 使用纹理作为源,对其进行采样并比较样本是否等于整数I.
  4. 所有这些都是核心配置文件3.3。
  5. 这是我到目前为止所得到的:

    1. 我像这样创建纹理:

      glTexImage2D(GL_TEXTURE_2D,0,GL_R8,width,height,0,GL_RED,GL_INT,(java.nio.ByteBuffer)null);

    2. 我还尝试了GL_R8I和GL_RED_INTEGER,但这不起作用。

      1. 我将此纹理绑定为我的FBO,将blendfunc设置为(GL_ONE,GL_ONE)(添加)并使用仅执行以下操作的着色器渲染1个四边形:

        layout(location = 2)out float value; main {value = 1.0;}

      2. 再一次,整数队在这里工作不了!

        接下来,我绑定另一个FBO并使用上面的源代码。我使用着色器对上面的样本进行采样:

        "if (texture2D(Tshadow, v_sampler_coo).r == 1.0){discard;}" + "\n"
        

        问题在于,只有通过输出才能让我以某种方式工作:

        out_diffuse = 1.0;
        

        比较:

        if (texture2D(Tshadow, v_sampler_coo).r == 1.0){discard;}
        

        任何其他值,即使是2的幂(2 ^ -2,2 ^ -3等)也不会生成真正的语句,除了1.0之外什么都没有。

        现在我理想的是能够写一个整数并对该整数进行采样。但我无法管理。无论我是否成功写入和整数,sampler2D事物只返回规范化的浮点数,对吗?这是采样颜色附件的唯一方法吗?

        更新:

        我发现如果我写0.5,那么这项工作:

        if (texture2D(Tshadow, v_sampler_coo).r == 0.4980392307){discard;}
        

1 个答案:

答案 0 :(得分:2)

内部格式GL_R8I实际上是您的用例的正确格式,并且规范明确地将该格式列为颜色可渲染。

  

layout(location = 2) out float value;

如果您打算存储整数,为什么使用float输出类型? OpenGL 3.3 core profile specification明确指出以下内容:

  

片段着色器写入的颜色值可能是浮点数,   有符号整数或无符号整数。如果颜色缓冲区有签名   或无符号标准化定点格式,假定颜色值   是浮点数并转换为定点,如中所述   方程式2.6或2.4;否则没有类型转换   应用

然而,正如你所说:

  

现在我理想的是能够写一个整数并对该整数进行采样。

您可以这样做,假设您在着色器中使用了正确的整数采样器类型。你不能做的是使用混合和整数。引用规范:

  

仅当颜色缓冲区具有定点或时,才会应用混合   浮点格式。如果颜色缓冲区具有整数格式,   继续下一步操作。

因此,如果您需要混合,最好的选择是使用GL_R8规范化整数格式,并使用着色器中的浮点输出。

使用更现代的GL,您可以通过直接采样更新纹理的着色器中的先前值来模拟添加剂混合。这样的反馈循环,其中着色器读取完全以后要写入的纹素位置是明确定义的并且在最近的GL版本中允许,但遗憾的是不在GL3.x中。

<强>更新

  

我发现如果我写0.5,那么这项工作:

if (texture2D(Tshadow, v_sampler_coo).r == 0.4980392307){discard;}

嗯,0.5是无法表示的归一化整数格式(实际上,位深度甚至不重要,它永远不会起作用)。在8位的情况下,GL将转换 0.5至0.5 * 255 = 127.5。现在它将是特定于实现的,如果它将舍入到127或128,那么你将得到127.0 / 255.0(你得到)或128.0 / 255.0。

关于舍入规则的注意事项:在GL 3.3规范中,表示乘法后的值

  然后将

转换为无符号二进制整数值,恰好是b位

根本没有舍入,所以127应该始终是结果。但是,在最新版本GL 4.5中,它被声明为

  

返回两个无符号二进制整数值中的一个,其中b完全为b   最接近浮点值r的位(舍入为圆形)   到最近是最好的。)

实际上,允许任何舍入行为......

作为最后一点:你应该从不比较浮点数是否相等。