2016-08-06 58 views
0

我为照明实现了一个简单的着色器;它有点作用,但当相机旋转时(并且只有当它旋转时),光似乎会移动。opengl - 当使用着色器时相机旋转时聚光灯移动

我与聚光灯试验,这是它的样子(这是在中心现场): enter image description here

如果现在我旋转的摄像头,现场到处移动;例如,在这里我向下看(我根本没有动,只是朝下看),它似乎在我的脚下: enter image description here

我已经看过了,我已经看到,这是一个常见的错误在着色器中混合参考系统和/或在移动相机之前设置光的位置。

事情是,我很确定我没有做这两件事,但显然我错了;这只是我找不到错误。

这里的着色器:

的Vertex Shader

varying vec3 vertexNormal; 
varying vec3 lightDirection; 

void main() 
{ 
    vertexNormal = gl_NormalMatrix * gl_Normal; 

    lightDirection = vec3(gl_LightSource[0].position.xyz - (gl_ModelViewMatrix * gl_Vertex).xyz); 

    gl_Position = ftransform(); 
} 

片段着色器

uniform vec3 ambient; 
uniform vec3 diffuse; 
uniform vec3 specular; 
uniform float shininess; 

varying vec3 vertexNormal; 
varying vec3 lightDirection; 

void main() 
{ 
    vec3 color = vec3(0.0, 0.0, 0.0); 

    vec3 lightDirNorm; 
    vec3 eyeVector; 
    vec3 half_vector; 
    float diffuseFactor; 
    float specularFactor; 
    float attenuation; 
    float lightDistance; 

    vec3 normalDirection = normalize(vertexNormal); 

    lightDirNorm = normalize(lightDirection); 

    eyeVector = vec3(0.0, 0.0, 1.0); 
    half_vector = normalize(lightDirNorm + eyeVector); 

    diffuseFactor = max(0.0, dot(normalDirection, lightDirNorm)); 

    specularFactor = max(0.0, dot(normalDirection, half_vector)); 
    specularFactor = pow(specularFactor, shininess); 

    color += ambient * gl_LightSource[0].ambient; 
    color += diffuseFactor * diffuse * gl_LightSource[0].diffuse; 
    color += specularFactor * specular * gl_LightSource[0].specular; 

    lightDistance = length(lightDirection[i]); 

    float constantAttenuation = 1.0; 
    float linearAttenuation = (0.02/SCALE_FACTOR) * lightDistance; 
    float quadraticAttenuation = (0.0/SCALE_FACTOR) * lightDistance * lightDistance; 

    attenuation = 1.0/(constantAttenuation + linearAttenuation + quadraticAttenuation); 

    // If it's a spotlight 
    if(gl_LightSource[i].spotCutoff <= 90.0) 
    { 
     float spotEffect = dot(normalize(gl_LightSource[0].spotDirection), normalize(-lightDirection)); 
     if (spotEffect > gl_LightSource[0].spotCosCutoff) 
     { 
      spotEffect = pow(spotEffect, gl_LightSource[0].spotExponent); 

      attenuation = spotEffect/(constantAttenuation + linearAttenuation + quadraticAttenuation); 
     } 
     else 
      attenuation = 0.0; 
    } 

    color = color * attenuation; 

    // Moltiplico il colore per il fattore di attenuazione 
    gl_FragColor = vec4(color, 1.0); 
} 

现在,我不能告诉你,我渲染的东西的代码,因为它是一种集成了opengl和用于创建3D应用程序的自定义语言(这无助于向你展示);但我做的是这样的:

SetupLights(); 
UpdateCamera(); 
RenderStuff(); 

其中:

  • SetupLights包含实际的OpenGL调用设置灯光和它们的位置;
  • UpdateCamera使用语言的内置类更新相机的位置;我在这里没有太多的权力;
  • RenderStuff调用语言的内置函数来绘制场景;我也没有太多的权力。

因此,无论我在着色器中做错了什么,或者在“幕后”语言中有什么东西会破坏事情。

您能否指点我正确的方向?

回答

2

你写

光的位置已经在世界坐标,而这正是我在做的计算

然而,因为你申请gl_ModelViewMatrix到你的顶点和gl_NormalMatrix到你的正常值,这些值可能是在视图空间,这可能会导致移动光。作为一边,你的眼睛向量看起来应该是在视图坐标中,但是,视图空间是一个右手坐标系,所以沿着负z轴“向前”指向。此外,由于您对所有片段使用相同的眼图向量,因此您的高光计算可能会关闭,但它应该指向该片段在近/远平面上的位置。

+0

我的错误,光线的位置是在着色器中的视角空间。 我认为你对其他事情是正确的,但仍然无法找到真正的问题。 – Beriol

+0

如果您的照明位置在视野范围内,则每当照相机发生变化时您都必须更新。在UpdateCamera()之前,你的'SetupLights()'序列在概念上似乎是错误的。 – derhass