2011-12-19 69 views
2

我目前正在嘗試使用glsl和使用Phong模型對球體進行高光照明。glsl中的phong-specular照明(lwjgl)

這是我的片段着色器看起來像:

#version 120 
uniform vec4 color; 
uniform vec3 sunPosition; 
uniform mat4 normalMatrix; 
uniform mat4 modelViewMatrix; 
uniform float shininess; 
// uniform vec4 lightSpecular; 
// uniform vec4 materialSpecular; 

varying vec3 viewSpaceNormal; 
varying vec3 viewSpacePosition; 

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) { 
    vec3 r = -l+2*(n*l)*n; 
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess); 
} 

void main(){ 
    vec3 normal = normalize(viewSpaceNormal); 
    vec3 viewSpacePosition = (modelViewMatrix * vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1.0)).xyz; 
    vec4 specular = calculateSpecular(sunPosition, normal, viewSpacePosition, vec4(0.3,0.3,0.3,0.3), vec4(0.3,0.3,0.3,0.3)); 
    gl_FragColor = color+specular; 
} 

的sunPosition不動,並設置爲值(2.0F,3.0F,-1.0F)。

問題是圖像看起來沒有任何作用,因爲如果鏡面反射計算是正確的話,圖像就沒有用了。

這是它的樣子: http://i.imgur.com/Na2C6.png

的原因我沒有任何ambient-/emissiv-/deffuse-在此代碼照明是因爲我想要得到的鏡面光部分第一份工作。

感謝您的幫助!

編輯: @Darcy雷納 這indead幫助了很多辛苦也接縫是東西,還是不對......

當前的代碼看起來是這樣的:

頂點着色器:

viewSpacePosition = (modelViewMatrix*gl_Vertex).xyz; 
viewSpaceSunPosition = (modelViewMatrix*vec4(sunPosition,1)).xyz; 
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
viewSpaceNormal = (normalMatrix * vec4(gl_Position.xyz, 0.0)).xyz; 

片段着色器:

vec4 calculateSpecular(vec3 l, vec3 n, vec3 v, vec4 specularLight, vec4 materialSpecular) { 
    vec3 r = -l+2*(n*l)*n; 
    return specularLight * materialSpecular * pow(max(0,dot(r, v)), shininess); 
} 

void main(){ 
    vec3 normal = normalize(viewSpaceNormal); 
    vec3 viewSpacePosition = normalize(viewSpacePosition); 
    vec3 viewSpaceSunPosition = normalize(viewSpaceSunPosition); 
    vec4 specular = calculateSpecular(viewSpaceSunPosition, normal, viewSpacePosition,  vec4(0.7,0.7,0.7,1.0), vec4(0.6,0.6,0.6,1.0)); 
    gl_FragColor = color+specular; 
} 

而球體看起來是這樣的:

-->Picture-link<--

與太陽的位置:sunPosition =新的向量(12.0f,15.0f,-1.0F);

回答

0

嘗試不使用gl_FragCoord,因爲它存儲在屏幕座標中(我不認爲通過modelViewMatrix轉換它會將其返回到查看座標)。做最簡單的事情,在你的頂點着色器設置viewSpacePosition爲:

// Change gl_Vertex to whatever attribute you are using. 
viewSpacePosition = (modelViewMatrix * gl_Vertex).xyz; 

這應該讓你viewSpacePosition視圖座標,(即應用在投影之前)。然後,您可以繼續並在片段着色器中規格化viewSpacePosition。不知道您是否將太陽矢量存儲在世界座標中,但您可能希望將其轉換爲視圖空間,然後將其正常化。試一試,看看會發生什麼,這些事情往往很容易出錯。

0

gl_FragCoord是一個輸入變量,它包含片段的窗口相對座標(x,y,z,1/w)值。 ...該值是固定功能的結果,該功能在頂點處理後插入基元以生成片段。

gl_FragCoord的前兩個值(x,y)包含正在渲染片段的像素的中心座標。例如,在幀緩衝區分辨率爲800×600時,在左下角渲染的片段將落在像素位置(0.5,0.5)上;呈現在最右上角的片段將具有座標(799.5,599.5)。第三個值(z)是在非線性範圍[0,1]中映射的片段深度。它將片段深度從[znear,zfar]映射到[0,1]。

據此,vec3 viewSpacePosition = (modelViewMatrix * vec4(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, 1.0)).xyz;不符合您的期望。 gl_FragCoord是頂點位置,它由gl_ModelViewProjectionMatrix轉換,由三角形基元上片段的偏心座標插值並由視口大小縮放。模型視圖矩陣(modelView Matrix)的進一步轉換沒有意義。

爲了計算一個鏡面光(Phong reflection model的情況下)3個載體是必需的:

  1. 表面上,這是在這種情況下normalize(viewSpaceNormal)的法線向量。
  2. 從frgments位置到相機的矢量。相機在視圖空間中具有位置(0,0,0)。 因此,視圖向量是normalize(vec3(0.0) - viewSpacePosition)
  3. 光矢量,它是從分段位置到光源的矢量。所以光矢量由normalize(viewSpaceSunPosition - viewSpacePosition)計算。
    請注意,由於計算是在視圖空間中完成的(viewSpaceNormalviewSpacePosition位於視圖空間中),因此光矢量以及光源位置(viewSpaceSunPosition)必須位於視圖空間中。這意味着在將光源的位置設置爲統一變量viewSpaceSunPosition之前,光源的位置應該通過視圖矩陣進行變換。

注意視圖矩陣和模型視圖矩陣不能相等。模型視圖矩陣由模型矩陣和視圖矩陣組成。通常,模型矩陣包含單個對象的附加變換(例如,場景中的對象上的動畫)。

除此之外,有在反射矢量的計算錯誤,計算公式如下:

incidentVector - 2.0 * dot(incidentVector, normalVector) * normalVector; 

注意,在GLSL有功能reflect,這將做的工作。

的頂點和片段着色器應該以某種方式是這樣的:

頂點着色器

varying vec3 viewSpacePosition; 
varying vec3 viewSpaceNormal; 

void main() 
{ 
    viewSpacePosition = (modelViewMatrix*gl_Vertex).xyz; 
    viewSpaceNormal = (normalMatrix * vec4(gl_Position.xyz, 0.0)).xyz; 
    gl_Position  = gl_ModelViewProjectionMatrix * gl_Vertex; 
} 

片段着色器

varying vec3 viewSpacePosition; 
varying vec3 viewSpaceNormal; 

uniform vec3 viewSpaceSunPosition; 
uniform float shininess; 

vec4 calculateSpecular(vec3 L, vec3 N, vec3 V, vec4 specularLight, vec4 materialSpecular) 
{ 
    vec3 R = -L - 2.0 * dot(N, -L) * N; 
    // vec3 R = reflect(-L, N); 
    return specularLight * materialSpecular * pow(max(0,dot(R, V)), shininess); 
} 

void main() 
{ 
    vec3 N = normalize(viewSpaceNormal); 
    vec3 V = normalize(-viewSpacePosition); 
    vec3 L = normalize(viewSpaceSunPosition - viewSpacePosition); 
    vec4 specular = calculateSpecular(L, N, V, vec4(0.7,0.7,0.7,1.0), vec4(0.6,0.6,0.6,1.0)); 
    gl_FragColor = color+specular; 
} 

又見回答這個問題: