我正在實施目標聚光燈。我有光錐,脫落,所有這一切,工作正常。問題是,當我在相機周圍的某個點上旋轉相機時,照明似乎跟隨着它,即無論相機在哪裏,相對於相機的光線總是處於相同的角度。OpenGL,目標聚光燈「跟着我在房間周圍」!
這是我在我的頂點着色器正在做:
void main()
{
// Compute vertex normal in eye space.
attrib_Fragment_Normal = (Model_ViewModelSpaceInverseTranspose * vec4(attrib_Normal, 0.0)).xyz;
// Compute position in eye space.
vec4 position = Model_ViewModelSpace * vec4(attrib_Position, 1.0);
// Compute vector between light and vertex.
attrib_Fragment_Light = Light_Position - position.xyz;
// Compute spot-light cone direction vector.
attrib_Fragment_Light_Direction = normalize(Light_LookAt - Light_Position);
// Compute vector from eye to vertex.
attrib_Fragment_Eye = -position.xyz;
// Output texture coord.
attrib_Fragment_Texture = attrib_Texture;
// Return position.
gl_Position = Camera_Projection * position;
}
我有Light_Position和Light_LookAt定義的目標聚光燈(查找的是空間中的點聚光燈看當然)。位置和外觀已經在眼睛空間。我通過從它們中減去相機位置來計算眼睛空間CPU端。
在頂點着色器中,我繼續創建一個光錐矢量,從光的位置到光的lookAt點,它通知像素着色器光錐的主軸在哪裏。
在這一點上,我想知道如果我也必須轉換矢量,如果是這樣的話?我試過了視圖矩陣的逆轉置,沒有運氣。
任何人都可以帶我通過這個嗎?
下面是完整的像素着色器:
void main(void)
{
// Compute N dot L.
vec3 N = normalize(attrib_Fragment_Normal);
vec3 L = normalize(attrib_Fragment_Light);
vec3 E = normalize(attrib_Fragment_Eye);
vec3 H = normalize(L + E);
float NdotL = clamp(dot(L,N), 0.0, 1.0);
float NdotH = clamp(dot(N,H), 0.0, 1.0);
// Compute ambient term.
vec4 ambient = Material_Ambient_Colour * Light_Ambient_Colour;
// Diffuse.
vec4 diffuse = texture2D(Map_Diffuse, attrib_Fragment_Texture) * Light_Diffuse_Colour * Material_Diffuse_Colour * NdotL;
// Specular.
float specularIntensity = pow(NdotH, Material_Shininess) * Material_Strength;
vec4 specular = Light_Specular_Colour * Material_Specular_Colour * specularIntensity;
// Light attenuation (so we don't have to use 1 - x, we step between Max and Min).
float d = length(-attrib_Fragment_Light);
float attenuation = smoothstep(Light_Attenuation_Max,
Light_Attenuation_Min,
d);
// Adjust attenuation based on light cone.
vec3 S = normalize(attrib_Fragment_Light_Direction);
float LdotS = dot(-L, S);
float CosI = Light_Cone_Min - Light_Cone_Max;
attenuation *= clamp((LdotS - Light_Cone_Max)/CosI, 0.0, 1.0);
// Final colour.
Out_Colour = (ambient + diffuse + specular) * Light_Intensity * attenuation;
}
感謝下面的反應。我仍然無法解決這個問題。我現在正在將光轉換到眼睛空間的CPU端。所以沒有必要轉換燈光,但它仍然不起作用。
// Compute eye-space light position.
Math::Vector3d eyeSpacePosition = MyCamera->ViewMatrix() * MyLightPosition;
MyShaderVariables->Set(MyLightPositionIndex, eyeSpacePosition);
// Compute eye-space light direction vector.
Math::Vector3d eyeSpaceDirection = Math::Unit(MyLightLookAt - MyLightPosition);
MyCamera->ViewMatrixInverseTranspose().TransformNormal(eyeSpaceDirection);
MyShaderVariables->Set(MyLightDirectionIndex, eyeSpaceDirection);
......而在頂點着色器中,我正在做這個(下面)。據我所知,光在眼睛空間,頂點被轉換成眼睛空間,照明矢量(attrib_Fragment_Light)在眼睛空間。然而,矢量永遠不會改變。原諒我有點厚!
// Transform normal from model space, through world space and into eye space (world * view * normal = eye).
attrib_Fragment_Normal = (Model_WorldViewInverseTranspose * vec4(attrib_Normal, 0.0)).xyz;
// Transform vertex into eye space (world * view * vertex = eye)
vec4 position = Model_WorldView * vec4(attrib_Position, 1.0);
// Compute vector from eye space vertex to light (which has already been put into eye space).
attrib_Fragment_Light = Light_Position - position.xyz;
// Compute vector from the vertex to the eye (which is now at the origin).
attrib_Fragment_Eye = -position.xyz;
// Output texture coord.
attrib_Fragment_Texture = attrib_Texture;
這是非常古老的,但我會指出一些東西,因爲有人會發現它有幫助。我曾經遇到類似的問題,並花了我一段時間來整理。問題在於我已經改變了着色器中光源位置的名稱,但卻忘記了在CPU代碼中這樣做。結果是在着色器中的光線保持不變,這導致了您在問題中描述的效果。 – broncoAbierto