2012-04-05 28 views
9

Ottengo risultati piuttosto bizzarri dal mio ombreggiatore di mappatura normale per lo spazio tangente :). Nella scena che mostro qui, la teiera e le pareti a scacchi sono ombreggiate con il mio ordinario shader Phong-Blinn (ovviamente la teiera sul retro della teiera le conferisce un aspetto leggermente effimero :-)). Ho provato ad aggiungere a normal mapping alla sfera, con risultati psichedeliche:Mappatura normale dello spazio tangente - controllo di integrità dello shader

Incorrect Normal Mapping on Sphere

La luce proviene da destra (quasi visibile come una macchia nera). La mappa normale che sto usando sulla sfera si presenta così:

Normal Map

sto usando ASSIMP per elaborare modelli di input, quindi è il calcolo della tangente e bi-normali per ogni vertice automaticamente per me.

I pixel e i vertex shader sono riportati di seguito. Non sono troppo sicuro di cosa possa andare storto, ma non mi sorprenderebbe se la matrice della base tangente fosse in qualche modo sbagliata. Presumo di dover calcolare le cose nello spazio degli occhi e quindi trasformare l'occhio e i vettori di luce in uno spazio tangente e che questo è il modo corretto per farlo. Si noti che la posizione della luce entra nello shader già nello spazio di visualizzazione.

// Vertex Shader 
#version 420 

// Uniform Buffer Structures 

// Camera. 
layout (std140) uniform Camera 
{ 
    mat4 Camera_Projection; 
    mat4 Camera_View; 
}; 

// Matrices per model. 
layout (std140) uniform Model 
{ 
    mat4 Model_ViewModelSpace; 
    mat4 Model_ViewModelSpaceInverseTranspose; 
}; 

// Spotlight. 
layout (std140) uniform OmniLight 
{ 
    float Light_Intensity; 

    vec3 Light_Position;   // Already in view space. 
    vec4 Light_Ambient_Colour; 
    vec4 Light_Diffuse_Colour; 
    vec4 Light_Specular_Colour; 
}; 

// Streams (per vertex) 
layout(location = 0) in vec3 attrib_Position; 
layout(location = 1) in vec3 attrib_Normal; 
layout(location = 2) in vec3 attrib_Tangent; 
layout(location = 3) in vec3 attrib_BiNormal; 
layout(location = 4) in vec2 attrib_Texture; 

// Output streams (per vertex) 
out vec3 attrib_Fragment_Normal; 
out vec4 attrib_Fragment_Position; 
out vec3 attrib_Fragment_Light; 
out vec3 attrib_Fragment_Eye; 

// Shared. 
out vec2 varying_TextureCoord; 

// Main 
void main() 
{ 
    // Compute normal. 
    attrib_Fragment_Normal = (Model_ViewModelSpaceInverseTranspose * vec4(attrib_Normal, 0.0)).xyz; 

    // Compute position. 
    vec4 position = Model_ViewModelSpace * vec4(attrib_Position, 1.0); 

    // Generate matrix for tangent basis. 
    mat3 tangentBasis = mat3( attrib_Tangent, 
           attrib_BiNormal, 
           attrib_Normal); 

    // Light vector. 
    attrib_Fragment_Light = tangentBasis * normalize(Light_Position - position.xyz); 

    // Eye vector. 
    attrib_Fragment_Eye = tangentBasis * normalize(-position.xyz); 

    // Return position. 
    gl_Position = Camera_Projection * position; 
} 

... e il pixel shader assomiglia a questo:

// Pixel Shader 
#version 420 

// Samplers 
uniform sampler2D Map_Normal; 

// Global Uniforms 

// Material. 
layout (std140) uniform Material 
{ 
    vec4 Material_Ambient_Colour; 
    vec4 Material_Diffuse_Colour; 
    vec4 Material_Specular_Colour; 
    vec4 Material_Emissive_Colour; 

    float Material_Shininess; 
    float Material_Strength; 
}; 

// Spotlight. 
layout (std140) uniform OmniLight 
{ 
    float Light_Intensity; 

    vec3 Light_Position;  
    vec4 Light_Ambient_Colour; 
    vec4 Light_Diffuse_Colour; 
    vec4 Light_Specular_Colour; 
}; 

// Input streams (per vertex) 
in vec3 attrib_Fragment_Normal; 
in vec3 attrib_Fragment_Position; 
in vec3 attrib_Fragment_Light; 
in vec3 attrib_Fragment_Eye; 

// Shared. 
in vec2 varying_TextureCoord; 

// Result 
out vec4 Out_Colour; 

// Main 
void main(void) 
{ 
    // Compute normals. 
    vec3 N = normalize(texture(Map_Normal, varying_TextureCoord).xyz * 2.0 - 1.0); 
    vec3 L = normalize(attrib_Fragment_Light); 
    vec3 V = normalize(attrib_Fragment_Eye); 
    vec3 R = normalize(-reflect(L, N)); 

    // Compute products. 
    float NdotL = max(0.0, dot(N, L)); 
    float RdotV = max(0.0, dot(R, V)); 

    // Compute final colours. 
    vec4 ambient = Light_Ambient_Colour * Material_Ambient_Colour; 
    vec4 diffuse = Light_Diffuse_Colour * Material_Diffuse_Colour * NdotL; 
    vec4 specular = Light_Specular_Colour * Material_Specular_Colour * (pow(RdotV, Material_Shininess) * Material_Strength); 

    // Final colour. 
    Out_Colour = ambient + diffuse + specular;  
} 

Edit: 3D Studio rendering della scena (per mostrare il UV sono OK sulla sfera):

enter image description here

risposta

3

Penso che i tuoi ombreggiatori siano a posto, ma le coordinate della trama sulla sfera sono completamente disattivate. È come se fossero distorti verso i poli lungo la longitudine.

+0

Grazie. Ho aggiunto un rendering 3D della scena per mostrare gli UV sulla sfera sono tutti OK. Sta usando la stessa mappa anche per il dosso. – Robinson

+1

Come al solito, mi dai una buona idea della risposta datenwolf. Il rendering della sfera con color = (u, v, 0, 1) non sta sicuramente elaborando correttamente i raggi UV durante l'importazione per questa mesh, o il mio shader non viene associato correttamente. – Robinson

+1

Quindi era così. Vertex shader necessario: \t varying_TextureCoord = attrib_Texture ;. Un tale stupido errore e il tempo dedicato a preparare la domanda :-). – Robinson

Problemi correlati