为什么我的OpenGL Phong着色器表现得像平面着色器? [英] Why does my OpenGL Phong shader behave like a flat shader?

查看:107
本文介绍了为什么我的OpenGL Phong着色器表现得像平面着色器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

过去两周来我一直在学习OpenGL,但在实现Phong着色器时遇到了一些麻烦.尽管我使用了smooth限定词,但似乎在顶点之间没有插值.我在这里想念什么吗?要在应归功的地方提供功劳,顶点着色器和片段着色器的代码会从

I've been learning OpenGL for the past couple of weeks and I've run into some trouble implementing a Phong shader. It appears to do no interpolation between vertexes despite my use of the smooth qualifier. Am I missing something here? To give credit where credit is due, the code for the vertex and fragment shaders cribs heavily from the OpenGL SuperBible Fifth Edition. I would highly recommend this book!

顶点着色器:

#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);
 }

}

这张来自Wikipedia的(公共领域)图像准确显示了我正在获得的图像类型以及目标是什么-我正在获得扁平"图像,但我想要"Phong"图像.

This (public domain) image from Wikipedia shows exactly what sort of image I'm getting and what I'm aiming for -- I'm getting the "flat" image but I want the "Phong" image.

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

Any help would be greatly appreciated. Thank you!

如果有所作为,我正在使用PyOpenGL 3.0.1和Python 2.6.

edit: If it makes a difference, I'm using PyOpenGL 3.0.1 and Python 2.6.

edit2:

事实证明问题出在我的几何图形上;科斯是正确的.对于其他在Blender模型中遇到此问题的人,Kos指出,执行Edit->Faces->Set Smooth可以解决问题.我发现Wings 3D可以开箱即用".

It turns out the problem was with my geometry; Kos was correct. For anyone else that's having this problem with Blender models, Kos pointed out that doing Edit->Faces->Set Smooth does the trick. I found that Wings 3D worked "out of the box."

推荐答案

Hmm ...您要将法线作为varying变量进行插值,因此片段着色器应接收正确的每像素法线.

Hmm... You're interpolating the normal as a varying variable, so the fragment shader should receive the correct per-pixel normal.

(您能想到的)事实唯一的解释(我能想到的)是,给定面部上的每个片段最终都会获得相同的法线.您可以使用片段着色器进行确认,例如:

The only explanation (I can think of) of the fact that you're having the result as on your left image is that every fragment on a given face ultimately receives the same normal. You can confirm it with a fragment shader like:

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

如果是这样,问题仍然存在:为什么?顶点着色器看起来不错.

If it's the case, the question remains: Why? The vertex shader looks OK.

所以您的几何形状可能有问题吗?您发送给着色器的数据是什么?您确定已正确计算了每个顶点法线,而不仅仅是每个面法线?

So maybe there's something wrong in your geometry? What is the data which you send to the shader? Are you sure you have correctly calculated per-vertex normals, not just per-face normals?

橙色线是对角线的法线,红色线是水平面的法线.

The orange lines are normals of the diagonal face, the red lines are normals of the horizontal face.

如果您的数据看起来像上面的图像,那么即使使用正确的着色器,您也会得到平坦的阴影.确保您具有正确的每个顶点法线,如下面的图像所示. (对于一个球体,它们真的很简单.)

If your data looks like the above image, then even with a correct shader you'll get flat shading. Make sure that you have correct per-vertex normals like on the lower image. (They are really simple to calculate for a sphere.)

这篇关于为什么我的OpenGL Phong着色器表现得像平面着色器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆