GLSL法线的奇数效应

时间:2011-04-20 14:51:41

标签: opengl glsl normals

有点类似于之前和之前发布过的问题,我正试图在我的GLSL应用程序中正常显示法线。 出于解释的目的,我使用RenderMonkey提供的ninjaHead.obj模型进行测试(you can grab it here)。现在在RenderMonkey的预览窗口中,一切看起来都很棒: RenderMonkey 并且分别生成的顶点和片段代码是:

顶点:

uniform vec4 view_position;

varying vec3 vNormal;
varying vec3 vViewVec;

void main(void)
{
  gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

  // World-space lighting
  vNormal = gl_Normal;
  vViewVec = view_position.xyz - gl_Vertex.xyz;
}

片段:

uniform vec4 color;

varying vec3 vNormal;
varying vec3 vViewVec;

void main(void)
{
   float v = 0.5 * (1.0 + dot(normalize(vViewVec), vNormal));
   gl_FragColor =  v* color;
}

我的GLSL代码基于此,但我没有得到预期的结果......

我的顶点着色器代码:

uniform mat4 P;
uniform mat4 modelRotationMatrix;
uniform mat4 modelScaleMatrix;
uniform mat4 modelTranslationMatrix;
uniform vec3 cameraPosition;

varying vec4 vNormal;
varying vec4 vViewVec;

void main()
{
vec4 pos = gl_ProjectionMatrix * P * modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix * gl_Vertex;

gl_Position = pos;

gl_TexCoord[0] = gl_MultiTexCoord0;

gl_FrontColor = gl_Color;   

vec4 normal4 = vec4(gl_Normal.x,gl_Normal.y,gl_Normal.z,0);     

// World-space lighting
   vNormal = normal4*modelRotationMatrix;
   vec4 tempCameraPos = vec4(cameraPosition.x,cameraPosition.y,cameraPosition.z,0);     
   //vViewVec = cameraPosition.xyz - pos.xyz;
   vViewVec = tempCameraPos - pos;
}

我的片段着色器代码:

varying vec4 vNormal;
varying vec4 vViewVec;

void main()
{
  //gl_FragColor = gl_Color;
  float v = 0.5 * (1.0 + dot(normalize(vViewVec), vNormal));
gl_FragColor =  v * gl_Color;
}

然而我的渲染产生了这个...... openGL render

有谁知道可能导致这种情况的原因和/或如何使其发挥作用?

修改 响应kvark的评论,这里是没有任何正常/光照计算的模型,以显示正在渲染的所有三角形。 Render flat shading

这是模型着色,其中使用了用于颜色的法线。我相信问题已经找到了!现在的原因是为什么它被渲染成这样以及如何解决它?欢迎提出建议! Normal shading

那么每个人的问题都解决了!感谢kvark他所有有用的洞察力,这肯定有助于我的编程练习,但我担心答案来自于我是一个大规模的山雀......我的代码的display()函数中有一个错误,设置了glNormalPointer偏移量到随机值。它曾经是这样的:

gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getNormalsBufferObject());
gl.glNormalPointer(GL.GL_FLOAT, 0, getNormalsBufferObject());

但应该是这样的:

gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, getNormalsBufferObject());
gl.glNormalPointer(GL.GL_FLOAT, 0, 0);

所以我想这是一个教训。从来没有盲目地按Ctrl + C和Ctrl + V代码来节省星期五下午的时间和...当你确定你所看到的代码部分是正确的时,问题可能就在其他地方!

2 个答案:

答案 0 :(得分:1)

  1. 您的P矩阵是什么? (我想这是一个世界 - >相机视图转换)。

  2. vNormal = normal4*modelRotationMatrix;为什么要更改参数的顺序?这样你就可以将正常乘以反转的旋转,这是你真正不想要的。请改用标准订单(modelRotationMatrix * normal4)

  3. vViewVec = tempCameraPos - pos。这完全是错误的。 pos是齐次剪辑空间中的顶点,而tempCameraPos位于世界空间(我猜)。您需要将结果放在与法线相同的空间(世界空间)中,因此请使用世界空间顶点位置(modelTranslationMatrix * modelRotationMatrix * modelScaleMatrix * gl_Vertex)来表示此等式。

答案 1 :(得分:0)

你似乎在混合GL版本了吗?您通过制服手动传递矩阵,但使用固定函数传递顶点属性。嗯。总之...


我真诚地不喜欢你正常做的事情。看看:

vec4 normal4 = vec4(gl_Normal.x,gl_Normal.y,gl_Normal.z,0);     

vNormal = normal4*modelRotationMatrix;

法线只存储方向数据,为什么要使用vec4?我相信只使用vec3会更优雅。此外,看看接下来会发生什么 - 你将法线乘以4x4模型旋转矩阵...另外你的法线的第四个坐标等于0,所以它不是同质坐标中的正确向量。我不确定这是主要的问题,但如果这种乘法会给你垃圾,我不会感到惊讶。

变换法线的标准方法是将vec3乘以模型 - 视图矩阵的3x3子矩阵(因为您只对方向感兴趣,而不是对平移感兴趣)。嗯,确切地说,“correctest”方法是使用该3x3子矩阵的逆转置(当你进行缩放时这很重要)。在旧的OpenGL版本中,您将其预先计算为gl_NormalMatrix

因此,除了上述内容之外,您应该使用类似

的内容
// (...)
varying vec3 vNormal;
// (...)

mat3 normalMatrix = transpose(inverse(mat3(modelRotationMatrix)));
// or if you don't need scaling, this one should work too-
mat3 normalMatrix = mat3(modelRotationMatrix);

vNormal = gl_Normal*normalMatrix;

这肯定是你的代码中的一件事 - 我希望它能解决你的问题。