2015-04-23 25 views
8

Cerco di implementare la normale mappatura utilizzando LibGDX. Quindi ho ottenuto dei risultati positivi quando ho calcolato il colore diffuso e speculare nel vertex shader (almeno lo penso).Mappatura normale GLSL con LibGDX

Vertex Shader:

attribute vec4 a_position; 
attribute vec2 a_texCoord0; 
attribute vec3 a_normal;  

varying vec2 v_texCoord; 
varying float v_diffuse; 
varying vec3 v_specular; 
varying vec3 v_lightVec; 

uniform mat4 u_worldTrans; 
uniform mat4 u_projTrans; 
uniform mat4 u_matViewInverseTranspose; 
uniform mat4 u_matModelView; 

const vec3 lightVector = vec3(0.0,0.0,-1.0); 

void main() 
{ 
    // Output the unmodified vertex position. 
    gl_Position = u_projTrans * u_worldTrans * a_position; 

    mat3 normalMatrix = mat3(u_matViewInverseTranspose); 
    // compute the transformed normal 
    vec3 n = normalize(normalMatrix * a_normal); 

    // compute the light vector pointing toward the sun, in model coordinates 
    // x,y compose the longitude and z the (seasonal) lattitude of the nadir point. 
    //vec3 lightVec = normalize(vec3(u_matViewInverseTranspose * vec4(u_lightVec, 1.0))); 
    vec3 lightVec = normalize(normalMatrix * lightVector); 

    // Calculate a diffuse light intensity 
    //v_diffuse = dot(lightVec, n); 
    v_diffuse = clamp(dot(n, lightVec), 0.0, 1.0); 

    vec4 ecPosition = u_matModelView * a_position; 
    // compute the reflection vector 
    vec3 reflectVec = reflect(-lightVec, n); 
    // compute a unit vector in direction of viewing position 
    vec3 viewVec = normalize(vec3(-ecPosition)); 

    // Calculate specular light intensity, scale down and apply a tint. 
    float specIntensity = pow(max(dot(reflectVec, viewVec), 0.0), 8.0);  
    v_specular   = specIntensity * 
         //gloss color 
         vec3(1.,.7,.3) * 
         //gloss intensity 
         .7;  

    v_texCoord.y = 1.-a_texCoord0.y; 
    v_texCoord.x = a_texCoord0.x; 

    vec3 lightDir = normalize(lightVector - u_matModelView * a_position); 

    vec3 tangent=a_tangent; 
    vec3 t = normalize(normalMatrix * tangent); 
    vec3 b = cross (n, t);  

    vec3 v; 
    v.x = dot (lightDir, t); 
    v.y = dot (lightDir, b); 
    v.z = dot (lightDir, n); 

    v_lightVec = normalize (v);   
} 

Fragment Shader:

precision mediump float; 

varying vec2 v_texCoord; 
varying float v_diffuse; 
varying vec3 v_specular; 
varying vec3 v_lightVec; 

uniform sampler2D u_texture; 
uniform sampler2D u_normalMap; 

void main() 
{ 
    vec3 ground = texture2D(u_texture, v_texCoord).rgb; 

    vec3 normal = normalize(2.0 * texture2D (u_normalMap, v_texCoord).rgb - 1.0); 
    float lamberFactor = max (dot (normal, v_lightVec), 0.0); 

    vec3 color = (ground.rgb * v_diffuse * lamberFactor + v_specular); 

    gl_FragColor = vec4 (color, 1.0);    
} 

Risultato: Correct result

Come si può vedere il risultato è reso corre ctly. Lo spot speculare si comporta come da molti esempi. Ma ho bisogno di implementare il colore speculare nello shader dei frammenti per ottenere un'immagine più impressionante. Quindi ho trovato un esempio da here e ora sto cercando di farlo funzionare.

Vertex Shader:

attribute vec4 a_position; 
attribute vec2 a_texCoord0; 
attribute vec3 a_normal; 
attribute vec3 a_tangent; 

varying vec2 v_texCoord; 
varying vec3 v_lightVec; 
varying vec3 v_eyeVec; //Added 

uniform mat4 u_worldTrans; 
uniform mat4 u_projTrans; 
uniform mat4 u_matViewInverseTranspose; 
uniform mat4 u_matModelView; 

const vec3 lightVector = vec3(0.0,0.0,-1.0); 

void main() 
{ 
    // Output the unmodified vertex position. 
    gl_Position = u_projTrans * u_worldTrans * a_position; 

    mat3 normalMatrix = mat3(u_matViewInverseTranspose); 
    // compute the transformed normal 
    vec3 n = normalize(normalMatrix * a_normal); 

    v_texCoord.y = 1.-a_texCoord0.y; 
    v_texCoord.x = a_texCoord0.x; 

    vec3 lightDir = normalize(lightVector - u_matModelView * a_position); 

    vec3 tangent=a_tangent; 
    vec3 t = normalize(normalMatrix * tangent); 
    vec3 b = cross (n, t);  

    vec3 v; 
    v.x = dot (lightDir, t); 
    v.y = dot (lightDir, b); 
    v.z = dot (lightDir, n); 

    v_lightVec = normalize (v); 

    //Added 
    vec3 ecPosition = u_matModelView * a_position; 

    vec3 tmp = vec3(-ecPosition); 
    v_eyeVec.x = dot(tmp, t); 
    v_eyeVec.y = dot(tmp, b); 
    v_eyeVec.z = dot(tmp, n); 
    v_eyeVec = normalize (v_eyeVec); 
} 

Fragment Shader:

precision mediump float; 

varying vec2 v_texCoord; 
varying vec3 v_lightVec; 
varying vec3 v_eyeVec; 

uniform sampler2D u_texture; 
uniform sampler2D u_normalMap; 

void main() 
{ 
    vec3 ground = texture2D(u_texture, v_texCoord).rgb;  
    vec3 normal = normalize(2.0 * texture2D (u_normalMap, v_texCoord).rgb - 1.0); 

    //Added 
    float distSqr = dot(v_lightVec, v_lightVec); 
    float att = clamp(1.0 - .25 * sqrt(distSqr), 0.0, 1.0); 
    vec3 lVec = v_lightVec * inversesqrt(distSqr); 

    vec3 vVec = normalize(v_eyeVec); 
    vec3 bump = normalize(texture2D(u_normalMap, v_texCoord).xyz * 2.0 - 1.0); 

    float diffuse = max(dot(lVec, bump), 0.0); 

    vec3 specular = pow(clamp(dot(reflect(-lVec, bump), v_eyeVec), 0.0, 1.0), 8.0) * 
         //gloss color 
         vec3(1.,.7,.3) * 
         //gloss intensity 
         .7; 

    vec3 color = (ground.rgb * diffuse + specular) * att;   
    gl_FragColor = vec4 (color, 1.0); 
}  

Risultato:

Wrong result

Il punto speculare è sbagliato. Ho pensato che succedesse a causa di un calcolo errato della matrice. Se è vero perché i primi due shader funzionano correttamente? Come ottengo la matrice model-view, la matrice normal e altre in LibGDX?

viewInvTraMatrix.set(camera.view);  
viewInvTraMatrix.mul(renderable.worldTransform); 
//model-view matrix 
program.setUniformMatrix("u_matModelView", viewInvTraMatrix); 
viewInvTraMatrix.inv(); //inverse 
viewInvTraMatrix.tra(); //transpose 
//normal matrix 
program.setUniformMatrix("u_matViewInverseTranspose", viewInvTraMatrix); 

//other matrix 
program.setUniformMatrix("u_worldTrans", renderable.worldTransform); 
program.setUniformMatrix("u_projTrans", camera.combined); 

Quindi, la mia domanda è cosa c'è di sbagliato nell'ultima coppia di shader?

+0

Perché non dare un'occhiata [qui] (http://www.microbasic.net/2015/01/tutorial-shadow-mapping-with-libgdx-3d-shadow-mapping-lighting/). È un po 'lungo, ma potrebbe aiutare – Fish

+0

Hai indicato la mappatura delle ombre, ma ti sto chiedendo una mappatura normale! Sii attento! – Nolesh

+0

Bump e normale stanno calcolando lo stesso valore, e ho usato qualcosa come specpower 3 invece di 8, ma per il resto pixelhader sembra corretto. Non sono sicuro del "matViewInverseTranspose", poiché si suppone che mantenga la trasposizione inversa della matrice del modello. Dal momento che lo hai usato anche come "matModelView", sembra che mantenga anche la trasformazione della vista. Ma la matrice materiale dovrebbe essere calcolata solo sulla matrice del modello. – StarShine

risposta

5

Il problema era nel mio modello (mesh). Dopo un po 'di tempo di ricerca ho scoperto che la mia mesh non ha tangents e binormals. È successo perché ho usato Blender 2.58 che non può esportare il modello in FBX con spazio tangente. Fortunatamente, hanno corretto questo bug in Blender 2.71 e versioni successive. Quindi, quando esporti il ​​tuo modello, devi selezionare il parametro Tangent Space e scegliere la versione FBX 7.4 binary. Per assicurarsi che il rete contiene tangenti e binormals, è possibile utilizzare fbx-converter strumento per convertire il vostro fbx file in g3dj formato invece che di default g3db utilizzando l'opzione aggiuntiva come di seguito:

fbx-converter.exe -o g3dj yourModel.fbx yourConvertedModel.g3dj 

quindi aprirlo in qualche programma come Notepad e verificare che gli attributi contengono TANGENT e BINORMAL

"version": [ 0, 1], 
"id": "", 
"meshes": [ 
    { 
     "attributes": ["POSITION", "NORMAL", "TANGENT", "BINORMAL", "TEXCOORD0"], 
     "vertices": [ 
      0.257400, 58.707802, -0.257400, 0.000000, 1.000000, -0.000000, 0.941742, 

Solo una cosa che non capisco, perché fa lamberFactor lavoro con l'attributo tangente sbagliato (in realtà, w senza di esso)? Molto probabilmente, il colore diffuso è calcolato male, ma nel mio esempio (sulla sfera) sembra abbastanza soddisfacente. Spero che aiuterà qualcun altro.

EDIT

Tra l'altro, per ottenere un normale & un model-view matrici, io uso il seguente codice:

myMatrix.set(camera.view); 
myMatrix.mul(renderable.worldTransform); 
program.setUniformMatrix(u_matModelView, myMatrix); //pass model-view matrix 
myMatrix.inv(); 
myMatrix.tra(); 
program.setUniformMatrix(u_matNormal, myMatrix); //pass normal matrix 
+0

Sono contento che risolveremo, non cercare nulla relativo alla tua domanda, ma inserire taglie, perché è raro vederne in libGDX, ma ti do l'uptote per la tua dedizione ma ti do l'uptote per la tua dedizione a trovare la errore, e pubblicare la soluzione, grazie –

+0

D'altra parte mi sorprende usare la tua v 0.9.9, mi stavo chiedendo se cambiando il mio che è la 1.4.x haha, se mancassero i miglioramenti, haha ​​ –

+0

sembra uno di quegli errori che devi avere un po 'di fortuna, per sistemare "pensare che il tuo modello non ha queste proprietà" –