【问题标题】:GLSL Lighting Acting As Flat - Normals Issue?GLSL 照明作为平面 - 法线问题?
【发布时间】:2012-08-16 09:12:24
【问题描述】:

我目前正在开发一个 OpenGL 框架,最近创建了一个 .ply(多边形文件格式)网格导入器。随着导入器的工作,我想在导入的网格上尝试一个简单的光照着色器,但遇到了问题。

网格是著名的斯坦福兔子的低分辨率版本,取自 Stanford 3D Scanning Repository,最初被导入 Blender 以验证正确性,然后再次导出以获得 nX, nY, nZ 值而不是 confidenceintensity。这个文件可以在http://pastebin.com/raw.php?i=xRmLYN0s找到

发生的情况是光照着色器就像一个平面着色器,它会根据相机方向改变颜色。图片包含在本文末尾。

着色器来自OpenGL超级圣经,描述为Simple diffuse, directional, and vertex based light

顶点

#version 140

uniform mat4 mvMatrix;
uniform mat4 pMatrix;
uniform vec4 vColor;

in vec4 vVertex;
in vec3 vNormal;

out vec4 vFragColor;

void main( void )
{
    mat3 mNormalMatrix;

    mNormalMatrix[0] = mvMatrix[0].xyz;
    mNormalMatrix[1] = mvMatrix[1].xyz;
    mNormalMatrix[2] = mvMatrix[2].xyz;

    vec3 vNorm = normalize(mNormalMatrix * vNormal);
    vec3 vLightDir = vec3(0.0, 0.0, 1.0);

    float fDot = max(0.0, dot(vNorm, vLightDir)); 
    vFragColor.rgb = vColor.rgb * fDot;
    vFragColor.a = vColor.a;

    gl_Position = ( pMatrix * mvMatrix ) * vVertex;
}

片段

#version 140

in vec4 vFragColor;

void main( void )
{
    gl_FragColor = vFragColor;
}

这可能是法线的问题吗?我已经验证它们是从模型文件中正确提取的,然后它们被输入到 VAO:

    glBindVertexArray( m_VAO );
    glEnableVertexAttribArray( ToolBox::Math::GLSL_ATTR::NORMAL );
    glBindBuffer( GL_ARRAY_BUFFER, m_NormalBuffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * num_elements, normals, GL_STATIC_DRAW );
    glVertexAttribPointer( ToolBox::Math::GLSL_ATTR::NORMAL, 3, GL_FLOAT, GL_FALSE, 0, ( const GLvoid* )0 );
    glBindVertexArray( 0 );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );

这与用于空间 (x,y,z) 信息的 VAO 相同,过去曾用于颜色和纹理值。此外,着色器由自定义 ShaderManager 类解析,并且已确认 vNormal 属性通过 glBindAttribLocation 绑定到相同的索引(ToolBox::Math::GLSL_ATTR::NORMAL aka 2)作为上述 sn-p 中的普通缓冲区.

据我所知,法线应该正确地从文件传递到着色器。但是如果我在顶点着色器中设置vFragColor.rgb = vNormal.xyz,兔子就会变成纯红色。这样不好,是吗?

所以有什么想法为什么着色器不工作?不好吗?正常不通过吗?还有什么?

感谢您提供的任何帮助。如果您需要更多信息,请告诉我。


图片

围绕兔子旋转:

设置vFragColor.rgb = vNormal.xyz;

Blender 中的模型(确认其正确性)

【问题讨论】:

  • 看起来你的法线肯定没有通过。我猜该错误不是您发布的 sn-ps 中的内容。你可以检查 glGetError 并确保它为零,并发布更多上下文(任何着色器初始化、链接、属性绑定等)。
  • 我检查了各个地方的错误,但没有发现任何错误。相关代码 sn-ps 如下:pastebin.com/eetAmKTu(着色器构建)、pastebin.com/Cz3ZYdEt(属性绑定)、pastebin.com/jTafh7ia(完整的正常 VAO 构建)。完整源代码也可以在github.com/ssell/glToolBox 找到,相关文件为ToolBox_Batch.cppToolBox_Batch_Module_StanfordPLY.cppToolBox_Shaders.cpp;虽然代码很长,而且到目前为止几乎没有内部文档。
  • “那不是普通的兔子!!!”
  • 请注意,完整的 VAO sn-p 中有一个错误,我从未生成正常缓冲区。这不是问题所在,在试图解决这个问题时一定是意外切断了线路。

标签: c++ opengl glsl shader


【解决方案1】:

问题在于属性绑定。不知何故,在我的着色器解析器中,我忘记区分正在读取的真实代码行和设置为全大写以进行不区分大小写比较检查的代码行。

这导致GLSL_ATTR::NORMAL 索引绑定到VNORMAL,而不是vNormal。奇怪的是,这个问题在位置/颜色/纹理工作期间从未出现过。感谢@Tim 试图帮助我解决这个只是一个愚蠢的错字的问题。

最后,兔子照原样亮了起来:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 2012-01-12
    • 2012-01-09
    相关资源
    最近更新 更多