2015-04-23 9 views
8

Ich versuche, normales Mapping mit LibGDX zu implementieren. Also habe ich ein paar positive Ergebnisse bekommen, wenn ich diffuse und spiegelnde Farben im Vertex Shader berechne (zumindest denke ich das).Normales Mapping GLSL mit 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);    
} 

Ergebnis: Correct result

Wie Sie das Ergebnis wiedergegeben wird corre sehen ganz sicher. Spiegelfleck verhält sich wie von vielen Beispielen. Aber ich muss Specular Color im Fragment-Shader implementieren, um ein beeindruckenderes Bild zu erhalten. So fand ich ein Beispiel von here und jetzt versuche ich es zu machen.

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); 
}  

Ergebnis:

Wrong result

Spiegelfleck ist falsch. Ich dachte es passiert wegen falscher Matrixberechnung. Wenn es wahr ist, warum funktionieren die ersten paar Shader richtig? Wie bekomme ich model-view Matrix, normal Matrix und andere 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); 

Also, meine Frage ist was ist falsch in den letzten paar Shadern?

+0

Warum nicht einen Blick [hier] (http://www.microbasic.net/2015/01/tutorial-shadow-mapping-with-libgdx-3d-shadow-mapping-lighting/). Es ist ein bisschen lang, aber es könnte helfen – Fish

+0

Sie haben auf Shadow-Mapping hingewiesen, aber ich frage nach normalen Mapping! Aufmerksam sein! – Nolesh

+0

Bump und normal berechnen denselben Wert, und ich habe etwas wie specpower 3 anstelle von 8 verwendet, aber ansonsten scheint der Pixelshader korrekt zu sein. Ich bin mir über die "matViewInverseTranspose" nicht sicher, da sie nur die inverse Transponierte der Modellmatrix enthalten soll. Da du es auch als "matModelView" benutzt hast, scheint es auch die View-Transformation zu enthalten. Die Materialmatrix sollte jedoch nur auf der Modellmatrix berechnet werden. – StarShine

Antwort

5

Das Problem war in meinem Modell (Mesh). Nach einiger Zeit des Grabens fand ich heraus, dass mein Netz tangents und binormals nicht hat. Es ist passiert, weil ich Blender 2.58 verwendet habe, das Modell mit FBX mit Tangentialraum nicht exportieren kann. Glücklicherweise haben sie diesen Fehler in Blender 2.71 und später behoben. Wenn Sie also Ihr Modell exportieren, sollten Sie den Parameter Tangent Space aktivieren und die Version FBX 7.4 binary auswählen. Um sicherzustellen, dass Ihre Masche enthält Tangenten und Binormalen, können Sie fbx-converter Tool verwenden, um Ihr fbx Datei zu g3dj-Format zu konvertieren, anstatt Standard-g3db durch zusätzliche Option wie unten:

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

Dann öffnen Sie es in einem gewissen Programm wie Notepad und überprüfen, ob Attribute enthalten TANGENT und 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, 

nur eine Sache, die ich nicht verstehen, warum tut lamberFactor Arbeit mit falschem Tangens Attribute (eigentlich w ohne es)? Höchstwahrscheinlich wird diffuse Farbe falsch berechnet, aber in meinem Beispiel (auf der Kugel) sieht es ziemlich zufriedenstellend aus. Ich hoffe, dass es jemand anderem hilft.

EDIT

By the way, eine normalen & eine Model-View-Matrizen zu erhalten, verwende ich den folgenden Code:

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

Ich bin froh, dass wir lösen werden, nichts mit Ihrer Frage zu tun, aber geben Sie Kopfgeld, denn es ist selten zu sehen in libGDX, aber ich gebe die Aufwertung für Ihre Hingabe, aber ich gebe die Aufwertung für Ihre Hingabe zu finden Fehler, und veröffentlichen Sie die Lösung, danke –

+0

Auf der anderen Seite überrascht mich, Ihre v 0.9.9 zu verwenden, fragte ich mich, wenn meine ändern, das ist die 1.4.x haha, wenn Verbesserungen fehlten, haha ​​ –

+0

sieht aus wie eines von diese Fehler, dass Sie etwas Glück haben müssen, um zu beheben "zu denken, dass Ihr Modell diese Eigenschaften nicht hat" –