2016-09-14 25 views
2

首先,我必須道歉在這個問題上發佈另一個問題(已經有很多了!)。我確實在尋找其他相關的問題和答案,但不幸的是他們中沒有人向我展示解決方案。現在我絕望了! :DGLSL3切線空間座標和法線貼圖

值得一提的是,下面的代碼給出了令人滿意的'顛簸'效果。這似乎是錯誤的場景啓發。

現場:死了簡單!中心的立方體,圍繞它旋轉的光源(與地面平行)及以上。

我的做法是從我的基本光着色器開始,它給了我足夠的輸出(或者我認爲!)。第一步是修改它在切線空間中進行計算,然後使用從紋理中提取的法線。

我想很好地評論的代碼,但在短期我有兩個問題

1)只做基本的照明(沒有法線貼圖),我希望來現場看完全一樣,有或而無需用TBN矩陣將我的向量轉換爲切線空間。我錯了嗎?

2)爲什麼我得到不正確的啓示?

一些截圖給你一個想法(編輯) - 遵循LJ的評論,我不再總結法線和每個頂點/面的切線。有趣的是,它突出了這個問題(請參閱捕獲,我已經標記了光線如何移動)。

基本上它是因爲如果立方體旋轉90度到左側,或者,如如果光被圖靈垂直代替正常映射水平

結果的:

Result with normal mapping

版本以簡單的光:

Version with simple light

頂點着色器:

// Information about the light. 
// Here we care essentially about light.Position, which 
// is set to be something like vec3(cos(x)*9, 5, sin(x)*9) 
uniform Light_t Light; 

uniform mat4 W; // The model transformation matrix 
uniform mat4 V; // The camera transformation matrix 
uniform mat4 P; // The projection matrix 

in vec3 VS_Position; 
in vec4 VS_Color; 
in vec2 VS_TexCoord; 
in vec3 VS_Normal; 
in vec3 VS_Tangent; 

out vec3 FS_Vertex; 
out vec4 FS_Color; 
out vec2 FS_TexCoord; 
out vec3 FS_LightPos; 
out vec3 FS_ViewPos; 
out vec3 FS_Normal; 

// This method calculates the TBN matrix: 
// I'm sure it is not optimized vertex shader code, 
// to have this seperate method, but nevermind for now :) 
mat3 getTangentMatrix() 
{ 
    // Note: here I must say am a bit confused, do I need to transform 
    // with 'normalMatrix'? In practice, it seems to make no difference... 
    mat3 normalMatrix = transpose(inverse(mat3(W))); 
    vec3 norm = normalize(normalMatrix * VS_Normal); 
    vec3 tang = normalize(normalMatrix * VS_Tangent); 
    vec3 btan = normalize(normalMatrix * cross(VS_Normal, VS_Tangent)); 
    tang = normalize(tang - dot(tang, norm) * norm); 
    return transpose(mat3(tang, btan, norm)); 
} 

void main() 
{ 
    // Set the gl_Position and pass color + texcoords to the fragment shader 
    gl_Position = (P * V * W) * vec4(VS_Position, 1.0); 
    FS_Color = VS_Color; 
    FS_TexCoord = VS_TexCoord; 

    // Now here we start: 
    // This is where supposedly, multiplying with the TBN should not 
    // change anything to the output, as long as I apply the transformation 
    // to all of them, or none. 
    // Typically, removing the 'TBN *' everywhere (and not using the normal 
    // texture later in the fragment shader) is exactly the code I use for 
    // my basic light shader. 
    mat3 TBN = getTangentMatrix(); 
    FS_Vertex = TBN * (W * vec4(VS_Position, 1)).xyz; 
    FS_LightPos = TBN * Light.Position; 
    FS_ViewPos = TBN * inverse(V)[3].xyz; 

    // This line is actually not needed when using the normal map: 
    // I keep the FS_Normal variable for comparison purposes, 
    // when I want to switch to my basic light shader effect. 
    // (see later in fragment shader) 
    FS_Normal = TBN * normalize(transpose(inverse(mat3(W))) * VS_Normal); 
} 

而片段着色器:

struct Textures_t 
{ 
    int SamplersCount; 
    sampler2D Samplers[4]; 
}; 

struct Light_t 
{ 
    int Active; 
    float Ambient; 
    float Power; 
    vec3 Position; 
    vec4 Color; 
}; 

uniform mat4 W; 
uniform mat4 V; 
uniform Textures_t Textures; 
uniform Light_t Light; 

in vec3 FS_Vertex; 
in vec4 FS_Color; 
in vec2 FS_TexCoord; 
in vec3 FS_LightPos; 
in vec3 FS_ViewPos; 
in vec3 FS_Normal; 

out vec4 frag_Output; 

vec4 getPixelColor() 
{ 
    return Textures.SamplersCount >= 1 
     ? texture2D(Textures.Samplers[0], FS_TexCoord) 
     : FS_Color; 
} 

vec3 getTextureNormal() 
{ 
    // FYI: the normal texture is always at index 1 
    vec3 bump = texture(Textures.Samplers[1], FS_TexCoord).xyz; 
    bump = 2.0 * bump - vec3(1.0, 1.0, 1.0); 
    return normalize(bump); 
} 

vec4 getLightColor() 
{ 
    // This is the one line that changes between my basic light shader 
    // and the normal mapping one: 
    // - If I don't do 'TBN *' earlier and use FS_Normal here, 
    // the enlightenment seems fine (see second screenshot) 
    // - If I do multiply by TBN (including on FS_Normal), I would expect 
    // the same result as without multiplying ==> not the case: it looks 
    // very similar to the result with normal mapping 
    // (just has no bumpy effect of course) 
    // - If I use the normal texture (along with TBN of course), then I get 
    // the result you see in the first screenshot. 
    vec3 N = getTextureNormal(); // Instead of 'normalize(FS_Normal);' 

    // Everything from here on is the same as my basic light shader 
    vec3 L = normalize(FS_LightPos - FS_Vertex); 
    vec3 E = normalize(FS_ViewPos - FS_Vertex); 
    vec3 R = normalize(reflect(-L, N)); 

    // Ambient color: light color times ambient factor 
    vec4 ambient = Light.Color * Light.Ambient; 

    // Diffuse factor: product of Normal to Light vectors 
    // Diffuse color: light color times the diffuse factor 
    float dfactor = max(dot(N, L), 0); 
    vec4 diffuse = clamp(Light.Color * dfactor, 0, 1); 

    // Specular factor: product of reflected to camera vectors 
    // Note: applies only if the diffuse factor is greater than zero 
    float sfactor = 0.0; 
    if(dfactor > 0) 
    { 
     sfactor = pow(max(dot(R, E), 0.0), 8.0); 
    } 

    // Specular color: light color times specular factor 
    vec4 specular = clamp(Light.Color * sfactor, 0, 1); 

    // Light attenuation: square of the distance moderated by light's power factor 
    float atten = 1 + pow(length(FS_LightPos - FS_Vertex), 2)/Light.Power; 

    // The fragment color is a factor of the pixel and light colors: 
    // Note: attenuation only applies to diffuse and specular components 
    return getPixelColor() * (ambient + (diffuse + specular)/atten); 
} 

void main() 
{ 
    frag_Output = Light.Active == 1 
     ? getLightColor() 
     : getPixelColor(); 
} 

這就是它!我希望你有足夠的信息,當然,你的幫助將不勝感激! :) 保重。

+0

沒有看你的代碼,從圖像看,你的立方體看起來像8個共享頂點和gouraud法線?所以你的法線和你的切線是錯誤的,高斯陰影用於近似光滑的表面,立方體當然不是光滑的表面。在你做任何事情之前,修復你的表面法線(提示它們應該垂直於表面,額外的提示:是的,這意味着沒有共享頂點)。 –

+0

非常感謝LJ - gouraud法線不是問題的根源,但是您的評論使問題更加明顯我發現:現在左邊的臉總是處於光明中,就好像它在上面 - 右邊的那個(截圖中不可見)總是在黑暗中! – Smoove

回答

0

我experiancing一個非常類似的問題,我無法解釋爲什麼照明不工作的權利,但我可以回答你的第一個問題,起碼說明如何我不知怎麼照明可接受工作(儘管你的問題可能並不一定與我的相同)。

首先在理論上如果切線和bitangents計算正確,那麼你在tangentspace與tangentspace正常[0,0,1]做計算的時候應該得到完全一樣的照明效果。其次,雖然你應該通過乘以逆轉矩模型 - 視圖矩陣as explained by this tutorial將你的法線從模型轉換到相機空間是常識,我發現如果你轉換正常相切模型視圖矩陣而不是逆轉置模型視圖。即使用normalMatrix = mat3(W);而不是normalMatrix = transpose(inverse(mat3(W)));

在我的情況下,這確實「修復」與光的問題,,但我不知道爲什麼這固定它,但我不能保證它不(它實際上我認爲它)介紹其他陰影問題