我正在学习OpenGL,我偶然发现了一个我不知道为什么会发生的问题。我有一个着色器(顶点+片段),我为它设置了统一的变量。着色器既负责绘制天框,也负责绘制对象(它通过uIsSkybox统一变量进行区分)。以下是每个人的代码:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec2 oObjTexCoords;
out vec3 oSkyboxTexCoords;
uniform mat4 uModel;
uniform mat4 uView;
uniform mat4 uProjection;
uniform bool uIsSkybox;
void main()
{
if(uIsSkybox)
{
mat4 mvp = uProjection * mat4(mat3(uView)) * uModel;
oSkyboxTexCoords = aPos;
vec4 pos = mvp * vec4(aPos, 1.0);
gl_Position = pos.xyww;
}
else
{
mat4 mvp = uProjection * uView * uModel;
oObjTexCoords = aTexCoords;
gl_Position = mvp * vec4(aPos, 1.0);
}
}#version 330 core
struct Material {
sampler2D texture_diffuse;
sampler2D texture_specular;
float shininess;
};
in vec2 oObjTexCoords;
in vec3 oSkyboxTexCoords;
out vec4 fragColor;
uniform Material material;
uniform sampler2D texture_diffuse1;
uniform samplerCube uSkyboxSampler;
uniform bool uIsSkybox;
void main()
{
if(uIsSkybox)
{
fragColor = texture(uSkyboxSampler, oSkyboxTexCoords);
}
else
{
// fragColor = texture(texture_diffuse1, oObjTexCoords);
fragColor = texture(material.texture_diffuse, oObjTexCoords);
}
}以下是(所需的)输出:

在此之前,我有一个单独的天窗着色器。在代码中,我留下了这个着色器的"setUniforms“代码,只删除了它的用法(glUseProgram)。我认为这已经足够了,因为着色器没有被使用过。然而,它确实影响了我的天窗,我不知道为什么。
model = glm::mat4(1.0f);
challengeShader.use();
challengeShader.setBool("uIsSkybox", true);
challengeShader.setMat4("uModel", model);
challengeShader.setMat4("uView", view);
challengeShader.setMat4("uProjection", projection);
//skyboxShader.use();
skyboxShader.setMat4("uModel", model);
skyboxShader.setMat4("uView", view);
skyboxShader.setMat4("uProjection", projection);

在这些设置器后面是对glGetUniformLocation和glUniform...的调用。我还确认了两个程序ID不是相同的,也不是相同的。如果我取消对skyboxShader的setter调用的注释,它将按需要工作。(真正造成这种影响的正是view矩阵。)我也试着把制服的名字分开,但没什么区别。
我想知道为什么会这样。如果你需要,我会提供更多的信息。
PS:我最近读到片段着色器中对texture()的调用应该发生在分支之外。但在本例中,两种参数类型都不同(samplerCube和vec3与sampler2D和vec2),因此我不确定这种情况在本例中是否可行。
编辑:这是setMat4的代码
void Shader::setMat4(const std::string& name, glm::mat4 value) const {
int location = glGetUniformLocation(ID, name.c_str());
glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(value));
}发布于 2021-01-18 13:13:46
挑战着色器有它的制服:
uModel
天窗遮阳器也是--比如说,它们的排列顺序不同:
uProjection
当您执行skyboxShader.setMat4("uModel", model);时,它调用glGetUniformLocation(skyboxShader.ID, "uModel"),它告诉您uModel是skyboxShader中的位置1。然后,它调用glUniformMatrix4fv(1, ...etc...),它设置当前着色器中的位置1,即challengeShader,即uView。看到问题了吗?
glUniformWhatever总是更新当前使用的着色器程序中的制服。如果您想在不同的着色程序中设置制服,您必须先使用它,或者使用glProgramUniformWhatever (OpenGL 4.1+)。
https://stackoverflow.com/questions/65774928
复制相似问题