opengl - GLSL 统一仅由不相关的调用更新

标签 opengl glsl

我有一个非常基本的 GLSL 程序,它在第一次绘图调用后无法正确更新统一值。没有收到来自 glGetError 的错误,编译和链接着色器时info log中没有报错,所有统一位置都有效。

顶点着色器:

#version 120

uniform mat4 mvp;
uniform mat3 nmv;

attribute vec3 position;
attribute vec3 normal;

varying vec3 v_normal;

void main()
{
    v_normal = normalize(nmv * normal);
    gl_Position = mvp * vec4(position, 1.0);
}

片段着色器:
#version 120

uniform vec3 lightDir;
uniform vec3 lightColor;
uniform vec3 materialColor;

varying vec3 v_normal;

void main()
{
    vec3 n = normalize(v_normal);
    float nDotL = max(0.0, dot(n, lightDir));

    gl_FragColor = vec4(materialColor * lightColor * nDotL, 1.0);
}

渲染代码:
glUseProgram(program);
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, mvp);
glUniformMatrix3fv(nmvLoc, 1, GL_FALSE, nmv);
glUniform3fv(lightDirLoc, 1, lightDir);
glUniform3fv(lightColorLoc, 1, lightColor);

for (auto mesh: meshes)
{
    glUniform3fv(materialColorLoc, 1, mesh.color);
    mesh.draw();
}

渲染出来的网格都是用第一个网格的颜色绘制的,说明在初始设置materialColor之后制服,随后更改制服的调用将被忽略。但是,这里有一个特殊条件列表,它们独立地允许正确更新制服:
  • 调用glUseProgram(program)循环内。
  • 设置mvpnmv循环内的制服。
  • 设置lightDir循环内均匀。
  • 删除 uniform vec3 之一s 来自着色器程序。

  • 请注意设置 lightColor循环内的统一将不是 更新materialColor制服。我也查了GL_CURRENT_PROGRAM在循环中,并且着色器始终保持绑定(bind)。

    我一直试图解决这个问题几个小时,绝对找不到问题。这个着色器设置非常简单,我不相信这是一个驱动程序错误。我在带有 NVIDIA GeForce 9400M 的 Mac OS X 10.8.3 上使用 OpenGL 2.1。

    这是单个帧的调用跟踪:
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glUseProgram(1);
    glUniformMatrix4fv(1, 1, 0, 0x7fff55512550); // mvp
    glUniformMatrix3fv(5, 1, 0, 0x7fff55512528); // nmv
    glUniform3fv(0, 1, 0x7fff55512670);          // lightDir
    glUniform3fv(9, 1, 0x7fff555124e8);          // lightColor
    
    // Mesh 0
    glUniform3fv(8, 1, 0x7fab820cd7ec);          // materialColor
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 1);
    glEnableVertexAttribArray(0);
    glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
    glEnableVertexAttribArray(2);
    glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDrawArrays(GL_TRIANGLES, 0, 21);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    // Mesh 1
    glUniform3fv(8, 1, 0x7fab823000bc);          // materialColor
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 2);
    glEnableVertexAttribArray(0);
    glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
    glEnableVertexAttribArray(2);
    glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDrawArrays(GL_TRIANGLES, 0, 24);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    // Mesh 2
    glUniform3fv(8, 1, 0x7fab8231f8fc);          // materialColor
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 3);
    glEnableVertexAttribArray(0);
    glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
    glEnableVertexAttribArray(2);
    glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDrawArrays(GL_TRIANGLES, 0, 21);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    // Mesh 3
    glUniform3fv(8, 1, 0x7fab820cf41c);          // materialColor
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 4);
    glEnableVertexAttribArray(0);
    glVertexAttribPointerARB(0, 3, GL_FLOAT, 0, 24, 0x00000000);
    glEnableVertexAttribArray(2);
    glVertexAttribPointerARB(2, 3, GL_FLOAT, 0, 24, 0x0000000c);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glDrawArrays(GL_TRIANGLES, 0, 18);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    CGLFlushDrawable();
    

    编辑:这是用于获取统一位置的代码。它在着色器编译和链接后执行,并且所有制服都被验证为有效。
    GLint mvpLoc = glGetUniformLocation(program, "mvp");
    GLint nmvLoc = glGetUniformLocation(program, "nmv");
    GLint lightDirLoc = glGetUniformLocation(program, "lightDir");
    GLint lightColorLoc = glGetUniformLocation(program, "lightColor");
    GLint materialColorLoc = glGetUniformLocation(program, "materialColor");
    

    最佳答案

    还是没有解决?

    什么是mesh.color的类型

    查看传递到调用跟踪中的地址,它们似乎相当高,也许您应该将地址传递给数据而不是实际数据,0x7fab823000bc

    glUniform3fv(materialColorLoc, 1, &mesh.color);
    也许尝试硬编码和使用 glUniform3f()

    关于opengl - GLSL 统一仅由不相关的调用更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16608998/

    相关文章:

    c++ - 如何在 OpenGL 中从一个 VBO 绑定(bind)多个 IBO

    c - 为什么旋转矩阵不在文本中心旋转?

    macos - 为什么我无法将此纹理统一附加到我的 GLSL 片段着色器?

    c++ - opengl 中的着色器应该做多少工作?

    javascript - 如何在 WebGL 中使用纹理和颜色?

    opengl - 优化最小/最大深度 GLSL 着色器

    python - Python/Pyglet 中的分离轴定理

    java - 如何使用 gl.glTranslatef() 定期更改坐标?

    c++ - 立方体在 OpenGL 中的边缘

    android - 形状的渲染顺序