2014-08-31 30 views
1

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

顶点着色器:

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

片段着色器:

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

如果有人有兴趣,我最终找到解决方案。删除对gl_NormalMatrix和gl_ModelViewMatrix的调用解决了这个问题。 – user29112 2014-09-02 00:07:13

+0

你应该发布这个答案并接受它。 – Dawnkeeper 2014-09-05 13:15:26

回答

2

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

0

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

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

更好的方法是在vertexPos和lightPos上执行modelView乘法。这样你就可以将lightPos当作世界空间中的一个量来处理,然后在屏幕空间中进行比较。从法线获得光强度的数学运算在任何空间都可以达到相同的程度,您将获得正确的光源。