OpenGL GLSL 采样器是否始终返回从 0.0 到 1.0 的浮点数?
我创建了几个浮点 RGBA 纹理...
glBindTexture( GL_TEXTURE_2D, texid[k] );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA,
GL_FLOAT, data);
然后我在着色器程序中交替对它们进行双缓冲渲染/采样
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texid[i], 0)
...
state_tex_loc = glGetUniformLocation( program, "state_tex" )
glUniform1i( state_tex_loc, 0 )
glActiveTexture( GL_TEXTURE0 )
glBindTexture( GL_TEXTURE_2D, texid[1-i] )
...
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec2 sample_pos = gl_Vertex.xy / vec2( xscale, yscale );
vec4 sample = texture2D( state_tex, sample_pos.xy );
sample.rgb = sample.rgb + vec3( 0.5, 0.5, 0.5 );
if ( sample.r > 1.1 )
sample.rgb = vec3( 0.0, 0.0, 0.0 );
gl_FrontColor = sample;
}
...
void main( void )
{
gl_FragColor = gl_Color;
}
注意对 sample.r< 的检查/code> 大于 1.1。这永远不会发生。似乎对texture2D的调用或片段着色器的输出将sample.rgb的值限制为[0.0..1.0]。然而,我的理解是纹理本身具有完整的浮点类型。
有什么办法可以避免这种夹紧吗?
更新:
按照下面的说明,我已修复了 glTexImage2D()
调用以使用 GL_RGBA32F_ARB,但我仍然没有从采样器中获得大于 1.0 的值。
更新 2:
我刚刚尝试将纹理初始化为大于 1.0 的值,并且它有效! texture2d()
返回初始值,> 1.0 值。所以也许这意味着问题出在片段着色器中,写入纹理?
更新 3:
我尝试更改着色器,这有效:
varying vec4 out_color;
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec2 sample_pos = gl_Vertex.xy / vec2( xscale, yscale );
vec4 sample = texture2D( state_tex, sample_pos.xy );
sample.rgb = sample.rgb + vec3( 0.5, 0.5, 0.5 );
if ( sample.r > 1.1 )
sample.rgb = vec3( 0.0, 0.0, 0.0 );
out_color = sample;
}
...
varying vec4 out_color;
void main( void )
{
gl_FragColor = out_color;
}
为什么使用自定义变化工作,但使用内置变化 gl_FrontColor/gl_Color 不起作用?
I've created a couple of floating point RGBA texture...
glBindTexture( GL_TEXTURE_2D, texid[k] );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA,
GL_FLOAT, data);
and then I double-buffer render/sample into them alternately in a shader program
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texid[i], 0)
...
state_tex_loc = glGetUniformLocation( program, "state_tex" )
glUniform1i( state_tex_loc, 0 )
glActiveTexture( GL_TEXTURE0 )
glBindTexture( GL_TEXTURE_2D, texid[1-i] )
...
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec2 sample_pos = gl_Vertex.xy / vec2( xscale, yscale );
vec4 sample = texture2D( state_tex, sample_pos.xy );
sample.rgb = sample.rgb + vec3( 0.5, 0.5, 0.5 );
if ( sample.r > 1.1 )
sample.rgb = vec3( 0.0, 0.0, 0.0 );
gl_FrontColor = sample;
}
...
void main( void )
{
gl_FragColor = gl_Color;
}
Notice the check for sample.r
being greater than 1.1. This never happens. It seems that either the call to texture2D
or the output of the fragment shader clamps the value of sample.rgb to [0.0..1.0]. And yet, my understanding is that the textures themselves have complete floating-point types in them.
Is there any way to avoid this clamping?
UPDATE:
As per instructions below, I've fixed my glTexImage2D()
call to use GL_RGBA32F_ARB, but I still don't get a value greater than 1.0 out of the sampler.
UPDATE 2:
I just tried initializing the textures to values larger than 1.0, and it works! texture2d()
returns the initial, > 1.0 values. So perhaps this means that the problem is in the fragment shader, writing to the texture?
UPDATE 3:
I've tried changing the shaders, and this works:
varying vec4 out_color;
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec2 sample_pos = gl_Vertex.xy / vec2( xscale, yscale );
vec4 sample = texture2D( state_tex, sample_pos.xy );
sample.rgb = sample.rgb + vec3( 0.5, 0.5, 0.5 );
if ( sample.r > 1.1 )
sample.rgb = vec3( 0.0, 0.0, 0.0 );
out_color = sample;
}
...
varying vec4 out_color;
void main( void )
{
gl_FragColor = out_color;
}
Why does using a custom varying work, but using the built-in varying gl_FrontColor/gl_Color not work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不,你没有。
该语句不会创建浮点纹理。好吧,如果您使用的是 OpenGL ES,也许可以,但在桌面 GL 中肯定不会。虽然我很确定 OpenGL ES 不允许您使用“4”作为内部格式。
在桌面 GL 中,
glTexImage2D
的第三个参数定义图像格式。 这个参数告诉OpenGL数据是浮点型、整数型还是其他类型。当您使用“4”时(您不应该这样做,因为这是指定内部格式的糟糕方法。始终使用真正的内部格式),您是在告诉 OpenGL 您想要 4 个无符号标准化整数分量。最后三个参数指定要上传到纹理的像素数据的位置、格式和数据类型。在桌面 GL 中,这对数据的存储方式没有影响。您只需告诉 OpenGL 您的输入像素是什么样子的。 OpenGL ES 规范不明智地改变了这一点。最后三个参数确实对数据的内部格式有一些影响。
无论如何,如果您想要 32 位浮点数,您应该要求它们:
因为它是内置的。我已经很多年没有使用过内置的 GLSL 东西了,所以我从来没有注意到这一点。
3.3 兼容性规范有一个函数
glClampColor
,它定义顶点(和片段)颜色夹紧行为。它仅影响内置组件。亲自?我会避免它并且根本不使用内置的东西。No, you did not.
This statement does not create a floating-point texture. Well, maybe it does if you're using OpenGL ES, but it certainly doesn't in desktop GL. Though I'm pretty sure OpenGL ES doesn't let you use "4" as the internal format.
In desktop GL, the third parameter to
glTexImage2D
defines the image format. It is this parameter that tells OpenGL whether the data is floating-point, integer, or whatever. When you use "4" (which you should never do, because it's a terrible way to specify the internal format. Always use a real internal format), you're telling OpenGL that you want 4 unsigned normalized integer components.The last three parameters specify the location, format, and data type of the pixel data that you want to upload to the texture. In desktop GL, this has no effect on how the data is stored. You're just telling OpenGL what your input pixels look like. The OpenGL ES specification unwisely changes this. The last three parameters do have some effect on what the internal format of the data is.
In any case, if you want 32-bit floats, you should ask for them:
Because it's built-in. I haven't used built-in GLSL stuff in years, so I never even noticed that.
The 3.3 compatibility spec has a function
glClampColor
that defines vertex (and fragment) color clamping behavior. It only affects the built-ins. Personally? I'd avoid it and just not use built-in stuff at all.