首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在未使用的着色器中设置制服会影响输出。

在未使用的着色器中设置制服会影响输出。
EN

Stack Overflow用户
提问于 2021-01-18 12:55:08
回答 1查看 229关注 0票数 1

我正在学习OpenGL,我偶然发现了一个我不知道为什么会发生的问题。我有一个着色器(顶点+片段),我为它设置了统一的变量。着色器既负责绘制天框,也负责绘制对象(它通过uIsSkybox统一变量进行区分)。以下是每个人的代码:

代码语言:javascript
复制
#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);
    }
}

代码语言:javascript
复制
#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)。我认为这已经足够了,因为着色器没有被使用过。然而,它确实影响了我的天窗,我不知道为什么。

代码语言:javascript
复制
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);

在这些设置器后面是对glGetUniformLocationglUniform...的调用。我还确认了两个程序ID不是相同的,也不是相同的。如果我取消对skyboxShader的setter调用的注释,它将按需要工作。(真正造成这种影响的正是view矩阵。)我也试着把制服的名字分开,但没什么区别。

我想知道为什么会这样。如果你需要,我会提供更多的信息。

PS:我最近读到片段着色器中对texture()的调用应该发生在分支之外。但在本例中,两种参数类型都不同(samplerCubevec3sampler2Dvec2),因此我不确定这种情况在本例中是否可行。

编辑:这是setMat4的代码

代码语言:javascript
复制
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));
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-18 13:13:46

挑战着色器有它的制服:

uModel

  • Location 1(可能):uView

  • Location 2(可能):uProjection

  • Location 3(可能):uIsSkybox

  • .等等.

天窗遮阳器也是--比如说,它们的排列顺序不同:

uProjection

  • Location 1(例如):uModel

  • Location 2(例如):uView

  • .等等.

当您执行skyboxShader.setMat4("uModel", model);时,它调用glGetUniformLocation(skyboxShader.ID, "uModel"),它告诉您uModel是skyboxShader中的位置1。然后,它调用glUniformMatrix4fv(1, ...etc...),它设置当前着色器中的位置1,即challengeShader,即uView。看到问题了吗?

glUniformWhatever总是更新当前使用的着色器程序中的制服。如果您想在不同的着色程序中设置制服,您必须先使用它,或者使用glProgramUniformWhatever (OpenGL 4.1+)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65774928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档