OpenGL Normal transformation in shaders
我正在尝试在LWJGL中创建一些基本的照明着色器。一切似乎都正常,只是当我改变相机的旋转角度时,灯光也会改变。我认为这是因为旋转相机时法线的旋转也被弄乱了。
这是我原来的顶点着色器:
1 2 3 4 5 6 7 8 | uniform vec3 lightDir; varying vec3 normal; void main() { normal = gl_NormalMatrix*gl_Normal; gl_Position = ftransform(); } |
我的片段着色器:
1 2 3 4 5 6 7 8 9 10 | varying vec3 normal; void main(){ vec3 color = vec3(1,1,1); vec3 lightDir = vec3(1,1,0); float inten = 1; color = color*dot(normal, lightDir)*inten; gl_FragColor = vec4(color,1); } |
要转换我使用的相机:
1 2 3 4 5 6 7 8 9 | public static void applyTranslations() { glPushAttrib(GL_TRANSFORM_BIT); glMatrixMode(GL_MODELVIEW); glRotatef(pitch, 1, 0, 0); glRotatef(yaw, 0, 1, 0); glRotatef(roll, 0, 0, 1); glTranslatef(-x, -y, -z); glPopAttrib(); } |
我意识到,这种变换相机的方法实际上可能是在相机保持静态的同时更改模型,这会弄乱法线,因此我尝试输入一个包含模型旋转的统一矩阵来变换法线,但这并没有。似乎也不起作用。现在整个模型都是黑色的。 (除旋转外,它之前一直在工作。)
我用它来将更改传递给着色器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Vector3f scale, rot, trans; Matrix3f modelMatrix = new Matrix3f(); modelMatrix.setIdentity(); scale = new Vector3f(1,1,1); rot = new Vector3f(xRot,yRot,zRot); trans = new Vector3f(x,y,z); Matrix4f.scale(scale, modelMatrix, modelMatrix); Matrix4f.translate(trans, modelMatrix, modelMatrix); Matrix4f.rotate((float) Math.toRadians(rot.z), new Vector3f(0,0,1), modelMatrix, modelMatrix); Matrix4f.rotate((float) Math.toRadians(rot.y), new Vector3f(0,1,0), modelMatrix, modelMatrix); Matrix4f.rotate((float) Math.toRadians(rot.x), new Vector3f(1,0,0), modelMatrix, modelMatrix); FloatBuffer modelBuff = BufferUtils.createFloatBuffer(9); modelMatrix.store(modelBuff); int loc = ARBShaderObjects.glGetUniformLocationARB(e.m.shader.programID,"modelMatrix"); ARBShaderObjects.glUniformMatrix4ARB(loc, false, modelBuff); |
然后将顶点着色器更改为:
1 2 3 4 5 6 7 8 9 | uniform vec3 lightDir; uniform modelMatrix; varying vec3 normal; void main() { normal = modelMatrix*gl_Normal; gl_Position = ftransform(); } |
这是我应该做的创建并传递转换矩阵的事情吗?还有没有使用glRotatef()旋转照相机的另一种方法吗?
每次更换相机时,
为避免这种情况,请确保
除了要实现的效果外,片段着色器中还有一个问题:
您应该做的是这样的:
1 | color*dot(normalize(normal), transform_to_same_space(lightDir))*inten; |
第二部分中的一些小问题:
您在声明
您不能使用4x4矩阵变换
您将
但是,通常情况下,应使用