为什么我的OpenGL Phong着色器performance得像一个平坦的着色器?

过去几周我一直在学习OpenGL,而且在实现Phong着色器时遇到了一些麻烦。 尽pipe我使用了smooth限定符,但似乎在顶点之间没有插值。 我在这里错过了什么? 为了在信用到期时提供信用,顶点和片段着色器的代码严重依赖于OpenGL SuperBible第五版。 我会强烈推荐这本书!

顶点着色器:

 #version 330 in vec4 vVertex; in vec3 vNormal; uniform mat4 mvpMatrix; // mvp = ModelViewProjection uniform mat4 mvMatrix; // mv = ModelView uniform mat3 normalMatrix; uniform vec3 vLightPosition; smooth out vec3 vVaryingNormal; smooth out vec3 vVaryingLightDir; void main(void) { vVaryingNormal = normalMatrix * vNormal; vec4 vPosition4 = mvMatrix * vVertex; vec3 vPosition3 = vPosition4.xyz / vPosition4.w; vVaryingLightDir = normalize(vLightPosition - vPosition3); gl_Position = mvpMatrix * vVertex; } 

片段着色器:

 #version 330 out vec4 vFragColor; uniform vec4 ambientColor; uniform vec4 diffuseColor; uniform vec4 specularColor; smooth in vec3 vVaryingNormal; smooth in vec3 vVaryingLightDir; void main(void) { float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir))); vFragColor = diff * diffuseColor; vFragColor += ambientColor; vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir),normalize(vVaryingNormal))); float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection)); if(diff != 0) { float fSpec = pow(spec, 32.0); vFragColor.rgb += vec3(fSpec, fSpec, fSpec); } } 

来自维基百科的这个(公共领域)图像显示了我得到的图像和我正在瞄准的图像 – 我得到了“平坦”的图像,但是我想要“Phong”图像。

任何帮助将不胜感激。 谢谢!

编辑:如果它有所作为,我使用PyOpenGL 3.0.1和Python 2.6。

EDIT2:

原来问题出在我的几何体上, 科斯是正确的。 对于其他任何与Blender模型有关的问题,Kos指出做Edit->Faces->Set Smooth就是一个好办法。 我发现Wings 3D“开箱即用”。

嗯…你正在插入正常的variables,所以片段着色器应该接收正确的每像素法线。

唯一的解释(我能想到的),就是你在左边的图像上得到的结果是, 给定脸上的每个片段最终都会得到相同的法线 。 您可以使用片段着色器来确认它,如下所示:

 void main() { vFragColor = normalize(vVaryingNormal); } 

如果是这样,问题依然存在:为什么? 顶点着色器看起来OK。

所以也许你的几何体有什么问题? 你发送给着色器的数据是什么? 你确定你已经正确地计算了每个顶点的法线,而不仅仅是每个面的法线吗?

法线

橙色线是对angular线的法线,红线是水平线的法线。

如果你的数据看起来像上面的图像,那么即使使用正确的着色器,你也会得到平坦的阴影。 确保你有正确的每个顶点法线,就像在下面的图像。 (它们对于一个球体来说非常简单。)

除了这个答案,这里是一个简单的几何着色器,它可以让你看到你的法线。 根据您的属性位置以及如何发送matrix,根据需要修改随附的顶点着色器。

但首先,我们的朋友斯坦福兔子的一个巨大的兔子头的图片作为结果的一个例子!

斯坦福兔子的法线

主要警告:请注意,我用模型视图matrix而不是一个适当的常规matrix来转换法线。 如果您的模型视图包含非均匀缩放,这将无法正常工作。 而且,你的法线的长度不正确,但是如果你只是想检查他们的方向,这个问题就没什么问题。

顶点着色器:

 #version 330 layout(location = 0) in vec4 position; layout(location = 1) in vec4 normal; layout(location = 2) in mat4 mv; out Data { vec4 position; vec4 normal; vec4 color; mat4 mvp; } vdata; uniform mat4 projection; void main() { vdata.mvp = projection * mv; vdata.position = position; vdata.normal = normal; } 

几何着色器:

 #version 330 layout(triangles) in; layout(line_strip, max_vertices = 6) out; in Data { vec4 position; vec4 normal; vec4 color; mat4 mvp; } vdata[3]; out Data { vec4 color; } gdata; void main() { const vec4 green = vec4(0.0f, 1.0f, 0.0f, 1.0f); const vec4 blue = vec4(0.0f, 0.0f, 1.0f, 1.0f); for (int i = 0; i < 3; i++) { gl_Position = vdata[i].mvp * vdata[i].position; gdata.color = green; EmitVertex(); gl_Position = vdata[i].mvp * (vdata[i].position + vdata[i].normal); gdata.color = blue; EmitVertex(); EndPrimitive(); } } 

片段着色器:

 #version 330 in Data { vec4 color; } gdata; out vec4 outputColor; void main() { outputColor = gdata.color; }