在 glTexImage2D() 中指定 GL_RGBA32F 时输出奇怪
Posted
技术标签:
【中文标题】在 glTexImage2D() 中指定 GL_RGBA32F 时输出奇怪【英文标题】:Weird output when specifying GL_RGBA32F in glTexImage2D() 【发布时间】:2020-02-24 09:05:54 【问题描述】:我正在开发一个 Java (JOGL) 程序来使用着色器程序进行一些计算,并且我遇到了来自片段着色器的奇怪输出值。 更具体地说,glGetTexImage() 似乎返回了缩放值。
现在,这是一个简单的片段着色器。
#version 330
layout(location=0) out vec4 fs_out_color;
void main()
fs_out_color=vec4(-1.0,0.5,0.4,2.0);
我创建了一个浮点纹理来获取着色器的输出。 TEXTURE_WIDTH 和 TEXTURE_HEIGHT 都是 2。
glBindTexture(GL4.GL_TEXTURE_2D, texture_id);
glTexImage2D(
GL4.GL_TEXTURE_2D, 0, GL4.GL_RGBA32F,
TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL4.GL_RGBA, GL4.GL_FLOAT, null);
glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_NEAREST);
glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_NEAREST);
glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_WRAP_S, GL4.GL_CLAMP_TO_EDGE);
glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_WRAP_T, GL4.GL_CLAMP_TO_EDGE);
glBindTexture(GL4.GL_TEXTURE_2D, 0);
GL_RGBA32F 被传递给 glTexImage2D() 的第三个参数以获取未被钳位的值。
然后,使用以下代码获取结果:
int size=TEXTURE_WIDTH*TEXTURE_HEIGHT*4;
FloatBuffer buf=Buffers.newDirectFloatBuffer(size);
glBindTexture(GL4.GL_TEXTURE_2D, texture_id);
glGetTexImage(GL4.GL_TEXTURE_2D, 0, GL4.GL_RGBA, GL4.GL_FLOAT, buf);
glBindTexture(GL4.GL_TEXTURE_2D, 0);
最后,它们被输出到控制台。
for(int i=0;i<size;i+=4)
float r=buf.get();
float g=buf.get();
float b=buf.get();
float a=buf.get();
String str="("+r+","+g+","+b+","+a+")";
System.out.println(str);
我在这里期望的是(-1.0,0.5,0.4,2.0)
。
但是,实际输出是
(-2.0,1.0,0.8,4.0)
(-2.0,1.0,0.8,4.0)
(-2.0,1.0,0.8,4.0)
(-2.0,1.0,0.8,4.0)
我在着色器中尝试了另一个 vec4 变量 vec4(-10.0,0.5,0.4,20.0)
,我得到了
(-200.0,10.0,8.0,400.0)
(-200.0,10.0,8.0,400.0)
(-200.0,10.0,8.0,400.0)
(-200.0,10.0,8.0,400.0)
我做错了什么吗?如何获得片段着色器的原始输出? 任何建议将不胜感激。
注意: 片段着色器
fs_out_color=vec4(-1.0,0.5,0.4,2.0);
Java 代码
glTexImage2D(
GL4.GL_TEXTURE_2D, 0, GL4.GL_RGBA,
TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL4.GL_RGBA, GL4.GL_FLOAT, null);
输出是
(0.0,0.5019608,0.4,1.0)
(0.0,0.5019608,0.4,1.0)
(0.0,0.5019608,0.4,1.0)
(0.0,0.5019608,0.4,1.0)
似乎与 GL_RGBA 配合得很好。
【问题讨论】:
是的,纹理附加到帧缓冲区,我使用 glDrawElements() 对其进行渲染。 我碰巧在 5 个月后回来并审查了这个问题,一无所获。在发布之前,我对代码进行了不必要的更改。对 OpenGL 函数的实际调用如下所示:GL4 gl = GLContext.getCurrentGL().getGL4(); gl.glBindTexture(GL4.GL_TEXTURE_2D, textureID);
澄清一下。
【参考方案1】:
好的,让我们做一些或多或少有根据的猜测:
Input: -1.0,0.5,0.4,2.0 -> Output: -2.0,1.0,0.8,4.0
Input: -10.0,0.5,0.4,20.0 -> Output: -200.0,10.0,8.0,400.0
Input: -1.0,0.5,0.4,2.0 -> Output: 0.0,0.5019608,0.4,1.0 (using UNORM target)
假设:您启用了Blending,并且您特别设置了glBlendFunc(GL_SRC_ALPHA, ...)
,以便片段着色器的输出(将是混合阶段的源操作数)乘以您提供的alpha值。请注意,当使用像 GL_RGBA
这样的 UNORM 渲染目标时,片段着色器的输出将在混合发生之前被限制为 [0,1]
,因此您会在其中得到 alpha = 1.0,并且乘法无效。
如果我的假设是正确的,那么在 UNORM GL_RGBA
格式的情况下,如果您尝试输入 alpha 为 0.5,您也会得到“错误”的缩放结果。
【讨论】:
这对我来说是一个完美的答案。我启用了混合并设置了 glBlendFunc(GL4.GL_SRC_ALPHA, GL4.GL_ONE_MINUS_SRC_ALPHA)。感谢您回答我的问题。 请注意,这也是未定义值的情况。由于您使用NULL
作为数据指针创建纹理,因此纹理内容未初始化,并且您添加(嗯,在您的场景中,1-alpha 是负数,因此您减去)它们作为混合过程中的目标因素。但是,在现实世界中,您的纹理很有可能全为零,但规范无法保证这一点。以上是关于在 glTexImage2D() 中指定 GL_RGBA32F 时输出奇怪的主要内容,如果未能解决你的问题,请参考以下文章