GLSL点光着色器用相机移动

时间:2014-08-31 18:05:01

标签: opengl glsl shader lwjgl

我一直试图使用着色器为LWJGL游戏制作一个基本的静态点光源,但看起来好像光线正在移动,因为相机的位置正在平移和旋转。这些着色器稍微修改了OpenGL 4.3指南,所以我不确定它们为什么没有按预期工作。任何人都可以解释为什么这些着色器没有按预期工作以及我可以做些什么来让它们工作?

顶点着色器:

varying vec3 color, normal;
varying vec4 vertexPos;

void main() {
    color = vec3(0.4);
    normal = normalize(gl_NormalMatrix * gl_Normal);
    vertexPos = gl_ModelViewMatrix * gl_Vertex;
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Fragment Shader:

varying vec3 color, normal;
varying vec4 vertexPos;

void main() {
    vec3 lightPos = vec3(4.0);
    vec3 lightColor = vec3(0.75);
    vec3 lightDir = lightPos - vertexPos.xyz;
    float lightDist = length(lightDir);
    float attenuation = 1.0 / (3.0 + 0.007 * lightDist +  0.000008 * lightDist * lightDist);
    float diffuse = max(0.0, dot(normal, lightDir));
    vec3 ambient = vec3(0.4, 0.4, 0.4);
    vec3 finalColor = color * (ambient + lightColor * diffuse * attenuation);
    gl_FragColor = vec4(finalColor, 1.0);
}

2 个答案:

答案 0 :(得分:2)

如果有人感兴趣,我最终找到了解决方案。删除对gl_NormalMatrix和gl_ModelViewMatrix的调用解决了这个问题。

答案 1 :(得分:0)

这里的临界值lightPos被设置为vertexPos的函数,你在屏幕空间中表达了这种情况(这是因为它的原始世界空间形式乘以了modelView)。屏幕空间与相机保持一致,而不是3D世界中的任何内容。因此,对于世界空间中的某个绝对点(如[4.0,4.0,4.0]),要有一个不动的光源,你可以在发现时将对象的点留在那个空间中。

但摆脱模型视图不是一个好主意,因为模型矩阵的整个点是将对象放置在它们所属的位置(因此您可以重新使用顶点数组,只更改模型矩阵,而不是通过从头开始指定每个形状的顶点位置来加重它们。

更好的方法是在vertexPos和lightPos上执行modelView乘法。这样你就可以将lightPos视为世界空间中的原始数量,然后在屏幕空间中进行比较。从法线获得光强度的数学运算在两个空间都可以达到相同的效果,你会得到一个正确的光源。