有点类似于之前和之前发布过的问题,我正试图在我的GLSL应用程序中正常显示法线。 出于解释的目的,我使用RenderMonkey提供的ninjaHead.obj模型进行测试(you can grab it here)。现在在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;
}
然而我的渲染产生了这个......
有谁知道可能导致这种情况的原因和/或如何使其发挥作用?
修改 响应kvark的评论,这里是没有任何正常/光照计算的模型,以显示正在渲染的所有三角形。
这是模型着色,其中使用了用于颜色的法线。我相信问题已经找到了!现在的原因是为什么它被渲染成这样以及如何解决它?欢迎提出建议!
解 那么每个人的问题都解决了!感谢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代码来节省星期五下午的时间和...当你确定你所看到的代码部分是正确的时,问题可能就在其他地方!
答案 0 :(得分:1)
您的P
矩阵是什么? (我想这是一个世界 - >相机视图转换)。
vNormal = normal4*modelRotationMatrix;
为什么要更改参数的顺序?这样你就可以将正常乘以反转的旋转,这是你真正不想要的。请改用标准订单(modelRotationMatrix * normal4)
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;
这肯定是你的代码中的一件事 - 我希望它能解决你的问题。