2016-08-06 84 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