用textureCube访问环境贴图在片段着色器中失败

3
我正在编写一个折射着色器,其中考虑了两个表面。因此,我使用FBO将深度和法线渲染到纹理中,并使用立方体贴图表示环境。我需要使用存储在纹理中的法线值来从立方体贴图中获取值,以获取后表面的折射法线。
只要我不尝试从从纹理中检索出来的向量访问立方体贴图,它就能够完美地工作。
以下是一个最小化的片段着色器示例,无法正常工作。颜色保持黑色。我确信调用texture2D返回非零值:如果我尝试显示包含在direction中的纹理颜色(表示法线),我会得到完美的彩色模型。无论我使用“direction”向量进行什么操作,它都无法正常工作。
uniform samplerCube cubemap;
uniform sampler2D normalTexture;
uniform vec2 viewportSize;

void main()
{
   vec3 direction = texture2D(normalTexture, gl_FragCoord.xy/viewportSize).xyz;
   // direction = vec3(1., 0., 0) + direction; // fails as well!!
   vec4 color = textureCube(cubemap, direction);
   gl_FragColor = color;
}

这里展示了向量“direction”的值以颜色的方式呈现,仅为证明它们不是空的! Values of "direction" 下面是上述着色器的结果(只显示茶壶)。 enter image description here

虽然这段代码完美运行:

uniform samplerCube cubemap;
uniform vec2 viewportSize;
varying vec3 T1;

void main()
{
   vec4 color = textureCube(cubemap, T1);
   gl_FragColor = color;
}

enter image description here

每当我访问采样立方体值时,我都无法想到为什么我的颜色会保持黑色!

为了完整起见,即使我的立方图正常工作,这里是用于设置它的参数: glGenTextures(1, &mTextureId);

glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, mTextureId);
// Set parameters
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

除非我错过了重要的东西,否则我认为可能是驱动程序出现了问题。 我没有任何显卡,我使用的是英特尔Core i5处理器芯片组。

00:02.0 VGA compatible controller: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller (rev 09)

有什么想法是为什么会出现这种情况,或者你有什么解决方法吗?
编辑:这里是我的着色器类如何绑定纹理的。
4 textures to bind
Bind texture 3 on texture unit unit 0
Bind to shader uniform: 327680
Bind texture 4 on texture unit unit 1
Bind to shader uniform: 262144
Bind texture 5 on texture unit unit 2
Bind to shader uniform: 393216
Bind texture 9 on texture unit unit 3
Bind to shader uniform: 196608

第3和4个纹理是深度图,第5个是法线贴图,第9个是立方体贴图。

绑定这些纹理的代码如下:

void Shader::bindTextures() {
    dinf << m_textures.size() << " textures to bind" << endl;
    int texture_slot_index = 0;
    for (auto it = m_textures.begin(); it != m_textures.end(); it++) {
        dinf << "Bind texture " << it->first<< " on texture unit unit "
                << texture_slot_index << std::endl;
        glActiveTexture(GL_TEXTURE0 + texture_slot_index);
        glBindTexture(GL_TEXTURE_2D, it->first);
        // Binds to the shader
        dinf << "Bind to shader uniform: " << it->second << endl;
        glUniform1i(it->second, texture_slot_index);
        texture_slot_index++;
    }
    // Make sure that the texture unit which is left active is the number 0
    glActiveTexture(GL_TEXTURE0);

}

m_textures是纹理ID到统一变量ID的映射表。

2个回答

4

您似乎并没有使用不同的纹理单元来处理法线贴图和立方体贴图,所有纹理都是默认使用纹理单元0。您需要像下面这样做:

uniform sampler2D norm_tex;

uniform samplerCube cube_tex;

在着色器中,纹理查找应该只使用“重载”的texture函数,在使用(3.2+)核心配置文件时。在(3.3+)中,您还可以使用采样器对象
生成并将纹理绑定到单独的纹理单元:
... generate 'norm_tex' and 'cube_tex' ...

glActiveTexture(GL_TEXTURE0);
... bind 'norm_tex' and set parameters ...

glActiveTexture(GL_TEXTURE1);
... bind 'cube_tex' and set parameters ...

... glUseProgram(prog); ...

glUniform1i(glGetUniformLocation(prog, "norm_map"), 0);
glUniform1i(glGetUniformLocation(prog, "cube_map"), 1);

谢谢你的回答! 我也考虑过这个问题,但我非常确定纹理已经正确绑定了。我的着色器类正在绑定所有纹理,然后将它们分配给着色器的统一值。 如果您想查看绑定内容的跟踪,请参阅我的问题。 - geenux
@geenux - 片段着色器仅列出一个取样器。 - Brett Hale
是的,我忘记把它添加到最小着色器中了,但那不是问题 ;) 现在一切都已经解决了! - geenux

0

我明白了,其实是个很愚蠢的错误。 我忘记将着色器函数更改为绑定立方体贴图作为GL_TEXTURE_CUBE_MAP,而一切都被绑定为GL_TEXTURE_2D!

无论如何,还是谢谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接