opengl libgdx glsl opengl-es-2.0 shader

opengl - Mapeo normal de GLSL usando LibGDX



opengl-es-2.0 shader (1)

Intento implementar mapas normales usando LibGDX. Así que obtuve algunos resultados positivos cuando calculo color difuso y especular en vertex shader (al menos eso creo).

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

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

Resultado:

Como puede ver, el resultado se representa correctamente. El punto especular se comporta como en muchos ejemplos. Pero necesito implementar el color especular en el sombreador de fragmentos para obtener una imagen más impresionante. Así que encontré ejemplos de aquí y ahora estoy tratando de hacer que funcione.

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

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

Resultado:

El punto especular está mal. Pensé que sucede debido a un cálculo de matrices incorrecto. Si es verdad, ¿por qué los primeros sombreadores funcionan correctamente? ¿Cómo obtengo matriz de model-view matriz normal y otras en 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);

Entonces, mi pregunta es ¿qué está mal en los últimos sombreadores?


El problema estaba en mi modelo (malla). Después de un tiempo de excavar descubrí que mi malla no tiene tangents ni binormals . Pasó porque utilicé Blender 2.58 que no puede exportar el modelo a FBX con espacio tangente. Afortunadamente, arreglaron este error en Blender 2.71 y posteriores. Entonces, cuando exporta su modelo, debe marcar Tangent Space parámetro Tangent Space y elegir la versión FBX 7.4 binary . Para asegurarse de que su malla contiene tangentes y binormals, puede usar la herramienta fbx-converter para convertir su archivo g3dj formato g3dj lugar de g3db por defecto mediante el uso de una opción adicional como la siguiente:

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

Luego BINORMAL en algún programa como el Notepad y comprueba que los atributos contengan BINORMAL y 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 que no entiendo, ¿por qué funciona lamberFactor con el atributo de tangente equivocado (en realidad, sin él)? Lo más probable es que el color difuso sea calculado incorrectamente, pero en mi ejemplo (en la esfera) se ve bastante satisfactoriamente. Espero que ayude a alguien más.

EDITAR

Por cierto, para obtener una normal y una matriz de vista de modelo, uso el siguiente código:

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