读写整数1通道纹理opengl
read and write integer 1-channel texture opengl
我想:
- 创建一个包含整数的可读写单通道纹理。
- 使用着色器,将整数 "I" 写入纹理。
- 使用纹理作为源,对其进行采样并比较样本是否等于整数 I。
- 所有这些都包含核心配置文件 3.3。
这是我目前得到的:
我是这样创建纹理的:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 宽度, 高度, 0, GL_RED, GL_INT, (java.nio.ByteBuffer) null);
我也试过 GL_R8I 和 GL_RED_INTEGER,但那行不通。
我将这个纹理绑定为我的 FBO,将 blendfunc 设置为 (GL_ONE, GL_ONE)(加法)并使用一个简单的着色器渲染 1 个四边形:
layout(location = 2) 输出浮点值;
主要{ 值 = 1.0;}
同样,整数在这里不起作用!
接下来,我绑定另一个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 都只是 returns 规范化浮点数,对吧?这是对颜色附件进行采样的唯一方法吗?
更新:
我发现如果我写 0.5,那么这个工作:
if (texture2D(Tshadow, v_sampler_coo).r == 0.4980392307){discard;}
内部格式 GL_R8I
实际上是适用于您的用例的正确格式,规范明确将该格式列为可渲染的格式。
layout(location = 2) out float value;
如果您打算存储整数,为什么要使用 float
输出类型? OpenGL 3.3 core profile specification 明确指出以下内容:
Color values written by a fragment shader may be floating-point,
signed integer, or unsigned integer. If the color buffer has an signed
or unsigned normalized fixed-point format, color values are assumed to
be floating-point and are converted to fixed-point as described in
equations 2.6 or 2.4, respectively; otherwise no type conversion is
applied.
然而,正如你所说:
Now what I'd ideally like is to be able to write an integer and sample that integer.
你可以做到这一点,假设你在着色器中使用了正确的整数采样器类型。您不能做的是将 blending 与整数一起使用。引用规范:
Blending applies only if the color buffer has a fixed-point or
floating-point format. If the color buffer has an integer format,
proceed to the next operation.
因此,如果您需要混合,最好的选择是使用 GL_R8
规范化整数格式,并在着色器中使用浮点输出。
使用更现代的 GL,您可以通过直接采样正在更新纹理的着色器中的先前值来简单地模拟加法混合。着色器 精确读取 稍后要写入的纹素位置的这种反馈循环是明确定义的,并且在最近的 GL 版本中允许,但不幸的是在 GL3.x 中没有。 =23=]
更新
I found that if I write 0.5, then this work:
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 spec中,规定乘法后的值
is then cast to an unsigned binary integer value with exactly b bits
完全没有四舍五入,所以结果应该总是 127。但是,在最新版本 GL 4.5 中,它表示为
returns one of the two unsigned binary integer values with exactly b
bits which are closest to the floating-point value r (where rounding
to nearest is preferred).
所以实际上,任何舍入行为都是允许的...
最后一点:你应该永远不要比较浮点数是否相等。
我想:
- 创建一个包含整数的可读写单通道纹理。
- 使用着色器,将整数 "I" 写入纹理。
- 使用纹理作为源,对其进行采样并比较样本是否等于整数 I。
- 所有这些都包含核心配置文件 3.3。
这是我目前得到的:
我是这样创建纹理的:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 宽度, 高度, 0, GL_RED, GL_INT, (java.nio.ByteBuffer) null);
我也试过 GL_R8I 和 GL_RED_INTEGER,但那行不通。
我将这个纹理绑定为我的 FBO,将 blendfunc 设置为 (GL_ONE, GL_ONE)(加法)并使用一个简单的着色器渲染 1 个四边形:
layout(location = 2) 输出浮点值; 主要{ 值 = 1.0;}
同样,整数在这里不起作用!
接下来,我绑定另一个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 都只是 returns 规范化浮点数,对吧?这是对颜色附件进行采样的唯一方法吗?
更新:
我发现如果我写 0.5,那么这个工作:
if (texture2D(Tshadow, v_sampler_coo).r == 0.4980392307){discard;}
内部格式 GL_R8I
实际上是适用于您的用例的正确格式,规范明确将该格式列为可渲染的格式。
layout(location = 2) out float value;
如果您打算存储整数,为什么要使用 float
输出类型? OpenGL 3.3 core profile specification 明确指出以下内容:
Color values written by a fragment shader may be floating-point, signed integer, or unsigned integer. If the color buffer has an signed or unsigned normalized fixed-point format, color values are assumed to be floating-point and are converted to fixed-point as described in equations 2.6 or 2.4, respectively; otherwise no type conversion is applied.
然而,正如你所说:
Now what I'd ideally like is to be able to write an integer and sample that integer.
你可以做到这一点,假设你在着色器中使用了正确的整数采样器类型。您不能做的是将 blending 与整数一起使用。引用规范:
Blending applies only if the color buffer has a fixed-point or floating-point format. If the color buffer has an integer format, proceed to the next operation.
因此,如果您需要混合,最好的选择是使用 GL_R8
规范化整数格式,并在着色器中使用浮点输出。
使用更现代的 GL,您可以通过直接采样正在更新纹理的着色器中的先前值来简单地模拟加法混合。着色器 精确读取 稍后要写入的纹素位置的这种反馈循环是明确定义的,并且在最近的 GL 版本中允许,但不幸的是在 GL3.x 中没有。 =23=]
更新
I found that if I write 0.5, then this work:
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 spec中,规定乘法后的值
is then cast to an unsigned binary integer value with exactly b bits
完全没有四舍五入,所以结果应该总是 127。但是,在最新版本 GL 4.5 中,它表示为
returns one of the two unsigned binary integer values with exactly b bits which are closest to the floating-point value r (where rounding to nearest is preferred).
所以实际上,任何舍入行为都是允许的...
最后一点:你应该永远不要比较浮点数是否相等。