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

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

问题描述

过去几周我一直在学习 OpenGL,但在实现 Phong 着色器时遇到了一些麻烦.尽管我使用了 smooth 限定符,但它似乎没有在顶点之间进行插值.我在这里错过了什么吗?为了在信用到期时给予信用,顶点和片段着色器的代码大量来自 OpenGL SuperBible 第五版.我强烈推荐这本书!

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

}

来自维基百科的这张(公共领域)图像准确地显示了我得到的图像类型以及我的目标——我得到的是平面"图像,但我想要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.

事实证明问题出在我的几何图形上;科斯是对的.对于其他在 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."

推荐答案

嗯...您将法线插入为 variing 变量,因此片段着色器应该接收正确的每像素正常.

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天全站免登陆