2013-08-20 138 views
1

我想在GLSL中實現phong着色,但是在高光組件上存在一些問題。來自GLSL phong着色器的奇怪鏡面反射結果

Strange specular result

綠光是鏡面反射分量。光線(點光源)在飛機上方以圓形行進。鏡面高光始終指向光軸旋轉的Y軸,並朝圖像中看到的漫反射散開。它看起來沒有受到相機定位的影響,我不確定哪裏出錯。

頂點着色器代碼:

#version 330 core 

/* 
* Phong Shading with with Point Light (Quadratic Attenutation) 
*/ 

//Input vertex data 
layout(location = 0) in vec3 vertexPosition_modelSpace; 
layout(location = 1) in vec2 vertexUVs; 
layout(location = 2) in vec3 vertexNormal_modelSpace; 

//Output Data; will be interpolated for each fragment 
out vec2 uvCoords; 

out vec3 vertexPosition_cameraSpace; 
out vec3 vertexNormal_cameraSpace; 

//Uniforms 
uniform mat4 mvMatrix; 
uniform mat4 mvpMatrix; 
uniform mat3 normalTransformMatrix; 


void main() 
{ 
    vec3 normal = normalize(vertexNormal_modelSpace); 

    //Set vertices in clip space 
    gl_Position = mvpMatrix * vec4(vertexPosition_modelSpace, 1); 

    //Set output for UVs 
    uvCoords = vertexUVs; 

    //Convert vertex and normal into eye space 
    vertexPosition_cameraSpace = mat3(mvMatrix) * vertexPosition_modelSpace;  
    vertexNormal_cameraSpace = normalize(normalTransformMatrix * normal); 

} 

片段着色器代碼:

#version 330 core 

in vec2 uvCoords; 

in vec3 vertexPosition_cameraSpace; 
in vec3 vertexNormal_cameraSpace; 

//out 
out vec4 fragColor; 

//uniforms 
uniform sampler2D diffuseTex; 
uniform vec3 lightPosition_cameraSpace; 

void main() 
{ 
    const float materialAmbient = 0.025; //a touch of ambient 

    const float materialDiffuse = 0.65; 
    const float materialSpec = 0.35; 

    const float lightPower = 2.0; 
    const float specExponent = 2; 

    //--------------Set Colors and determine vectors needed for shading-----------------   

    //reflection colors- NOTE- diffuse and ambient reflections will use the texture color 
    const vec3 colorSpec = vec3(0,1,0); //Green spec color 
    vec3 diffuseColor = texture2D(diffuseTex, uvCoords).rgb; //Get color from the texture at fragment 

    const vec3 lightColor = vec3(1,1,1);  //White light 

    //Re-normalize normal vectors : after interpolation they make not be unit length any longer 
    vec3 normVertexNormal_cameraSpace = normalize(vertexNormal_cameraSpace); 

    //Set camera vec 
    vec3 viewVec_cameraSpace = normalize(-vertexPosition_cameraSpace); //Since its view space, camera at origin 

    //Set light vec 
    vec3 lightVec_cameraSpace = normalize(lightPosition_cameraSpace - vertexPosition_cameraSpace); 

    //Set reflect vect 
    vec3 reflectVec_cameraSpace = normalize(reflect(-lightVec_cameraSpace, normVertexNormal_cameraSpace));  //reflect function requires incident vec; from light to vertex 

    //----------------Find intensity of each component--------------------- 

    //Determine Light Intensity 
    float distance = abs(length(lightPosition_cameraSpace - vertexPosition_cameraSpace)); 
    float lightAttenuation = 1.0/((distance > 0) ? (distance * distance) : 1); //Quadratic 

    vec3 lightIntensity = lightPower * lightAttenuation * lightColor; 

    //Determine Ambient Component 
    vec3 ambientComp = materialAmbient * diffuseColor * lightIntensity; 

    //Determine Diffuse Component 
    float lightDotNormal = max(dot(lightVec_cameraSpace, normVertexNormal_cameraSpace), 0.0); 
    vec3 diffuseComp = materialDiffuse * diffuseColor * lightDotNormal * lightIntensity; 

    vec3 specComp = vec3(0,0,0); 
    //Determine Spec Component 
    if(lightDotNormal > 0.0) 
    { 
     float reflectDotView = max(dot(reflectVec_cameraSpace, viewVec_cameraSpace), 0.0); 
     specComp = materialSpec * colorSpec * pow(reflectDotView, specExponent) * lightIntensity; 
    } 

    //Add Ambient + Diffuse + Spec 
    vec3 phongFragRGB = ambientComp + 
      diffuseComp + 
      specComp; 

    //----------------------Putting it together----------------------- 

    //Out Frag color 
    fragColor = vec4( phongFragRGB, 1); 
} 

只需指出的是,在頂點着色器看到的normalTransformMatrix是模型視圖矩陣的逆轉置。

我正在設置一個矢量,從頂點位置到光線,相機和反射矢量,都在相機空間。對於漫反射計算,我使用光矢量和法向矢量的點積,對於鏡面反射分量,我使用反射矢量和視圖矢量的點積。也許我對算法有一些基本的誤解?

我原本以爲這個問題可能是因爲我沒有對插值後進入片段着色器的法線進行標準化,但是添加一行來標準化並不會影響圖像。我不確定在哪裏看。

我知道網站上有很多phong底紋問題,但每個人似乎都有一個有點不同的問題。如果有人能看到我要出錯的地方,請告訴我。任何幫助表示讚賞。

編輯:好吧現在它的工作!就像下面的jozxyqk建議的那樣,我需要爲我的頂點位置做一個mat4 * vec4操作或丟失翻譯信息。當我第一次做出改變時,我得到了奇怪的結果,直到我意識到在我將它傳遞給着色器之前,我在lightPosition_cameraSpace的OpenGL代碼中犯了同樣的錯誤(錯誤是我將視圖矩陣轉換爲mat3用於計算而不是將光位置矢量設置爲vec4)。一旦我編輯了這些線,着色器看起來工作正常!感謝您的幫助,jozxqk!

回答

2

我可以看到兩部分看起來不正確。

  1. 「vertexPosition_cameraSpace = MAT3(mvMatrix)* vertexPosition_modelSpace」 應該是一個MAT4/vec4(X,Y,Z,1)相乘,否則忽略該模型視圖矩陣的平移部分。

2.距離使用相對於相機而不是頂點的光位置。改爲使用lightVec_cameraSpace。 (編輯:錯過了重複的計算)

+0

嗯,當我試圖讓我有一個場景,其中對象的照明取決於從物體到相機的距離。當我將相機拉開時,物體變黑。 – StackAttack

+0

確定它的工作!看到我上面的編輯。 – StackAttack