使用LibGDX的法线贴图GLSL [英] Normal mapping GLSL using LibGDX

查看:243
本文介绍了使用LibGDX的法线贴图GLSL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用LibGDX实现法线映射.因此,当我在顶点着色器中计算漫反射和镜面反射颜色时,我得到了一些积极的结果(至少我是这么认为的).

I try to implement normal mapping using LibGDX. So I got some positive results when I calculate diffuse and specular color in vertex shader (at least I think so).

顶点着色器:

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

片段着色器:

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

结果:

如您所见,结果呈现正确.高光点的行为类似于许多示例.但是我需要在片段着色器中实现镜面反射颜色以获得更令人印象深刻的图像.因此,我从此处中找到了示例,现在我试图使其工作.

As you can see the result is rendered correctly. Specular spot behaves like from many examples. But I need to implement specular color in fragment shader to get more impressive picture. So I found example from here and now I'm trying to make it works.

顶点着色器:

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

片段着色器:

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

结果:

镜面斑点是错误的.我以为发生这种情况是因为矩阵计算错误.如果是事实,为什么前几个着色器可以正常工作? 如何在LibGDX中获得model-view矩阵,normal矩阵和其他矩阵?

Specular spot is wrong. I thought it happens because of wrong matrix calculation. If it's true why do first couple of shaders work correctly? How do I get model-view matrix, normal matrix and others 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);

所以,我的问题是在最近的两个着色器中出了什么问题?

So, my question is what is wrong in the last couple of shaders?

推荐答案

问题出在我的模型(网格)中.经过一段时间的挖掘,我发现我的网格物体没有tangentsbinormals.之所以发生这种情况,是因为我使用了Blender 2.58,该Blender 2.58无法将切线空间的模型导出到FBX.幸运的是,他们修复了Blender 2.71及更高版本中的此错误.因此,在导出模型时,应勾选Tangent Space参数并选择版本FBX 7.4 binary.为确保您的网格包含切线和法线,可以使用 fbx-converter 工具通过使用如下所示的其他选项将您的fbx文件转换为g3dj格式,而不是默认的g3db格式:

The problem was in my model(mesh). After some time of digging I found out that my mesh doesn't have tangents and binormals. It happend because I used Blender 2.58 which cannot export model to FBX with tangent space. Fortunately, they fixed this bug in Blender 2.71 and later. So, when you export your model, you should tick Tangent Space parameter and choose version FBX 7.4 binary. To ensure that your mesh contains tangents and binormals, you can use fbx-converter tool to convert your fbx file to g3dj format instead of default g3db by using additional option like below:

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

然后在诸如Notepad之类的程序中将其打开,并检查属性是否包含TANGENTBINORMAL

Then open it in some program like Notepad and check that attributes contain TANGENT and 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,

我唯一不了解的一件事,为什么lamberFactor使用错误的切线属性(实际上没有切线属性)?最有可能的是,漫反射颜色的计算错误,但是在我的示例中(球状),它看起来令人满意.我希望它会对其他人有所帮助.

Only one thing I don't understand, why does lamberFactor work with wrong tangent attribute(actually, without it)? Most likely, diffuse color is wrong calculated, but in my example(on sphere) it looks pretty satisfactorily. I hope it will help somebody else.

编辑

顺便说一句,以获取正常的&模型视图矩阵,我使用以下代码:

By the way, to get a normal & a model-view matrices, I use the following 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

这篇关于使用LibGDX的法线贴图GLSL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆