Opengl 为什么我会得到;纹理单元0作为sampler2D和samplerCube访问;两个不同的采样器?

Opengl 为什么我会得到;纹理单元0作为sampler2D和samplerCube访问;两个不同的采样器?,opengl,textures,glsl,pyopengl,Opengl,Textures,Glsl,Pyopengl,我有一些OpenGL/Python代码: import sys from OpenGL.GL import * from OpenGL.GL import shaders from OpenGL.GLU import * from OpenGL.GLUT import * glutInit(sys.argv) glutInitDisplayMode(GLUT_RGBA) glutInitWindowSize(640, 480) window = glutCreateWindow("Test"

我有一些OpenGL/Python代码:

import sys

from OpenGL.GL import *
from OpenGL.GL import shaders
from OpenGL.GLU import *
from OpenGL.GLUT import *

glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(640, 480)
window = glutCreateWindow("Test")

print glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS)
print glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)
print glGetIntegerv(0x8872)
print glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)

fs = (
"""
#version 130

uniform sampler2D foo;
uniform samplerCube bar;

void main()
{
    vec4 c1 = texture2D(foo, vec2(0, 0));
    vec4 c2 = textureCube(bar, vec3(0, 0, 0));
    gl_FragColor = c1 + c2;
}
"""
)

shader = shaders.compileShader(fs, GL_FRAGMENT_SHADER)
program = shaders.compileProgram(shader)
print program
运行时,片段着色器无法编译:

$ python tex.py 
16
16
16
48
Traceback (most recent call last):
  File "tex.py", line 35, in <module>
    program = shaders.compileProgram(shader)
  File "/usr/local/lib/python2.7/dist-packages/OpenGL/GL/shaders.py", line 196, in compileProgram
    program.check_validate()
  File "/usr/local/lib/python2.7/dist-packages/OpenGL/GL/shaders.py", line 108, in check_validate
    glGetProgramInfoLog( self ),
RuntimeError: Validation failure (0): Texture unit 0 is accessed both as sampler2D and samplerCube
$python tex.py
16
16
16
48
回溯(最近一次呼叫最后一次):
文件“tex.py”,第35行,在
程序=着色器。编译程序(着色器)
compileProgram中的文件“/usr/local/lib/python2.7/dist packages/OpenGL/GL/shaders.py”,第196行
program.check_validate()
文件“/usr/local/lib/python2.7/dist packages/OpenGL/GL/shaders.py”,第108行,在check\u validate中
glGetProgramInfoLog(自我),
运行时错误:验证失败(0):纹理单元0作为sampler2D和samplerCube访问
我不明白为什么两个采样器对象会绑定到相同的纹理单元?使用GLSL 1.30,我甚至不知道如何在编译程序之前指定纹理单位。而且应该可以使用多个采样器和纹理单元


我做错了什么?

您可能将采样器统一值保留为默认值,或者将其中一个设置为0。这显然是错误的

图形纹理绑定代码应如下所示:

glActiveTexture(GL_TEXTURE0 + x)
glBindTexture(GL_TEXTURE_2D, …)
glUniform1i(uniform_location_of_foo, x)


glActiveTexture(GL_TEXTURE0 + y)
glBindTexture(GL_TEXTURE_CUBE_MAP, …)
glUniform1i(uniform_location_of_bar, y)

也就是说,采样器统一整数值必须与匹配纹理目标绑定到的纹理单元相对应。

我最近刚开始学习OpenGL,所以我不熟悉它的所有细节。然而,我也遇到了同样的问题,这是因为在我将制服分配给各自的单位之前,我试图验证着色器。在我按照以下顺序完成所有操作后,问题得到了解决:

        glLinkProgram(m_Program);

        m_Uniforms[DIFFUSE_U]   = glGetUniformLocation(m_Program, "diffuse");
        m_Uniforms[NORMALMAP_U] = glGetUniformLocation(m_Program, "normalMap");
        m_Uniforms[SHADOWMAP_U] = glGetUniformLocation(m_Program, "shadowMap");

        glUseProgram(m_Program);

        glUniform1i(m_Uniforms[DIFFUSE_U], 0);//sets the diffuse sampler to the texture bound as unit 0
        glUniform1i(m_Uniforms[NORMALMAP_U], 1);
        glUniform1i(m_Uniforms[SHADOWMAP_U], 2);

        glValidateProgram(m_Program);

请注意,这发生在着色器编译之前。因此,程序和统一(位置)都还不存在……我感觉调用
glValidateProgram()
是PyOpenGL的错,这取决于OpenGL的状态。我将尝试跳过该步骤,并查看它在绑定纹理后是否正确验证。谢谢@维嘉德:那对PyOpenGL来说是糟糕的设计。我希望这种行为是可以失败的,因为程序不一定需要立即处于有效的工作状态。调用
glUseProgram(…)
以及稍后设置纹理图像单元和其他支持状态是常见的场景。验证程序状态的最佳时间是在调用
glDraw*(…)
之前-出于上述原因,在任何其他点进行验证都为时过早。您需要在
glLinkProgram()
glUniform1i()
调用之间进行
glUseProgram()
调用
glUniform1i()
适用于当前程序。谢谢,我编辑了代码以显示glUseProgram()的去向。