Bump mapping的GLSL实现

原文 http://www.cnblogs.com/CGDeveloper/archive/2008/07/03/1234206.html

 

如果物体表面细节很多,我们可以不断的精细化物体的几何数据,但是这样会产生大量的Lighting & Transformation等计算,
为了实现丰富真实的物体表面,除了贴上一般纹理之外,往往还使用Bump mapping(凹凸纹理)技术。
Bump mapping并没有增加物体的几何复杂度,它只是在计算物体的光照效果时作了“弊”,不使用物体本身的法向量,而是
使用了经过处理的法向量。如果这样的法向量使用normal map,我们可以使用GLSL实现凹凸效果。
首先,因为没有改变对象的几何形状,所以bump mapping的实现是在FS之中进行的,因此光照计算就必须在FS之中进行。
由于normal map之中的法向量是在SURFACE_LOCAL COORDINATE SPACE,所以用于光照计算的光源的方向和视向都
必须变换到同一空间进行光照计算。也就是说,必须使用所谓TBN矩阵的逆矩阵对光源的方向和视向进行变换,转换之后的值
作为varying传入到FS之中。
对于三角形mesh而言,TBN的一种计算方法如下:

Bump mapping的GLSL实现 void FindInvTBN(Vertor3f Vertices[3], Vector2f TexCoords[3], Vector3f & InvNormal,
Bump mapping的GLSL实现                   Vector3f & InvBinormal, Vector3f & InvTangent) 
Bump mapping的GLSL实现   {
Bump mapping的GLSL实现                 /* Calculate the vectors from the current vertex
Bump mapping的GLSL实现                    to the two other vertices in the triangle */
Bump mapping的GLSL实现   
Bump mapping的GLSL实现                 Vector3f v2v1 = Vertices[0- Vertices[2];
Bump mapping的GLSL实现                 Vector3f v3v1 = Vertices[1- Vertices[2];
Bump mapping的GLSL实现   
Bump mapping的GLSL实现                 //Calculate the “direction” of the triangle based on texture coordinates.
Bump mapping的GLSL实现   
Bump mapping的GLSL实现                 // Calculate c2c1_T and c2c1_B
Bump mapping的GLSL实现                 float c2c1_T = TexCoords[0].x() - TexCoords[2].x();
Bump mapping的GLSL实现                 float c2c1_B = TexCoords[0].y() - TexCoords[2].y();
Bump mapping的GLSL实现   
Bump mapping的GLSL实现                 // Calculate c3c1_T and c3c1_B
Bump mapping的GLSL实现                 float c3c1_T = TexCoords[1].x() - TexCoords[2].x();
Bump mapping的GLSL实现                 float c3c1_B = TexCoords[1].y() - TexCoords[2].y();
Bump mapping的GLSL实现   
Bump mapping的GLSL实现                 //Look at the references for more explanation for this one.
Bump mapping的GLSL实现                 float fDenominator = c2c1_T * c3c1_B - c3c1_T * c2c1_B;  
Bump mapping的GLSL实现                 /*ROUNDOFF here is a macro that sets a value to 0.0f if the value is a very small
Bump mapping的GLSL实现                   value, such as > -0.001f and < 0.001. */
Bump mapping的GLSL实现  
Bump mapping的GLSL实现                 /* EDIT by c programmer: you should NEVER perform an equality test against a floating point value, even if
Bump mapping的GLSL实现                    your macro has set fDenominator to 0.0f.  The comparison can still fail.  The code needs fixed.
Bump mapping的GLSL实现                    Instead you should check if fDenominator is within an epsilon value of 0.0f. */
Bump mapping的GLSL实现  
Bump mapping的GLSL实现                 if (ROUNDOFF(fDenominator) == 0.0f
Bump mapping的GLSL实现                 {
Bump mapping的GLSL实现                        /* We won't risk a divide by zero, so set the tangent matrix to the
Bump mapping的GLSL实现                           identity matrix */
Bump mapping的GLSL实现                         InvTangent = Vector3f(1.0f0.0f0.0f);
Bump mapping的GLSL实现                         InvBinormal = Vector3f(0.0f1.0f0.0f);
Bump mapping的GLSL实现                         InvNormal = Vector3f(0.0f0.0f1.0f);
Bump mapping的GLSL实现                 }
Bump mapping的GLSL实现                 else
Bump mapping的GLSL实现                 {            
Bump mapping的GLSL实现                         // Calculate the reciprocal value once and for all (to achieve speed)
Bump mapping的GLSL实现                         float fScale1 = 1.0f / fDenominator;
Bump mapping的GLSL实现   
Bump mapping的GLSL实现                         /* Time to calculate the tangent, binormal, and normal.
Bump mapping的GLSL实现                            Look at Søren’s article for more information. */
Bump mapping的GLSL实现                         Vector3f T, B, N;
Bump mapping的GLSL实现                         T = Vector3f((c3c1_B * v2v1.x() - c2c1_B * v3v1.x()) * fscale1,
Bump mapping的GLSL实现                                      (c3c1_B * v2v1.y() - c2c1_B * v3v1.y()) * fScale1,
Bump mapping的GLSL实现                                      (c3c1_B * v2v1.z() - c2c1_B * v3v1.z()) * fScale1);
Bump mapping的GLSL实现   
Bump mapping的GLSL实现                         B = Vector3f((-c3c1_T * v2v1.x() + c2c1_T * v3v1.x()) * fScale1,                                     (-c3c1_T * v2v1.y() + c2c1_T * v3v1.y()) * fScale1,                                     (-c3c1_T * v2v1.z() + c2c1_T * v3v1.z()) * fScale1);                          N = T%B; //Cross product!  /*This is where programmers should break up the function to smooth the tangent, binormal and    normal values. */    //Look at “Derivation of the Tangent Space Matrix” for more information.                          float fScale2 = 1.0f / ((T.x() * B.y() * N.z() - T.z() * B.y() * N.x()) +                                                 (B.x() * N.y() * T.z() - B.z() * N.y() * T.x()) +                                                 (N.x() * T.y() * B.z() - N.z() * T.y() * B.x()));                        InvTangent.set((B%N).x() * fScale2,                                       ((-1.0f * N)%T).x() * fScale2,                                       (T%B).x() * fScale2);                        InvTangent.normalize();                          InvBinormal.set(((-1.0f *B)%N).y() * fScale2,                                        (N%T).y() * fScale2,                                        ((-1.0f * T)%B).y() * fScale2);                        InvBinormal.normalize();                          InvNormal.set((B%N).z() * fScale2,                                      ((-1.0f * N)%T).z() * fScale2,                                      (T%B).z() * fScale2);                        InvNormal.normalize();              }

上述计算中可以只计算T。
相应的VS如下:

Bump mapping的GLSL实现 varying vec3 LightDir;
Bump mapping的GLSL实现 varying vec3 EyeDir;
Bump mapping的GLSL实现
Bump mapping的GLSL实现 attribute vec3 Tangent;
Bump mapping的GLSL实现
Bump mapping的GLSL实现 void main()
Bump mapping的GLSL实现 {
Bump mapping的GLSL实现     gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
Bump mapping的GLSL实现     gl_TexCoord[0= gl_MultiTexCoord0;
Bump mapping的GLSL实现
Bump mapping的GLSL实现     // 眼坐标系下的TBN
Bump mapping的GLSL实现     vec3 n = normalize(gl_NormalMatrix * gl_Normal);
Bump mapping的GLSL实现     vec3 t = normalize(gl_NormalMatrix * Tangent);
Bump mapping的GLSL实现     vec3 b = cross(n, t);
Bump mapping的GLSL实现     mat3 TBN = mat3(t, b, n);
Bump mapping的GLSL实现     
Bump mapping的GLSL实现     vec4 pos = gl_ModelViewMatrix * gl_Vertex;
Bump mapping的GLSL实现     vec3 epos = vec3(pos)/pos.w;
Bump mapping的GLSL实现     
Bump mapping的GLSL实现     vec3 v = gl_LightSource[0].position.xyz - epos;
Bump mapping的GLSL实现     v = v * TBN;
Bump mapping的GLSL实现     LightDir = normalize(v);
Bump mapping的GLSL实现
Bump mapping的GLSL实现     v = -epos * TBN;
Bump mapping的GLSL实现     EyeDir = normalize(v);
Bump mapping的GLSL实现 }


相应的FS如下:

Bump mapping的GLSL实现 uniform sampler2D BumpTex;
Bump mapping的GLSL实现 uniform sampler2D DecalTex;
Bump mapping的GLSL实现
Bump mapping的GLSL实现 varying vec3 LightDir;
Bump mapping的GLSL实现 varying vec3 EyeDir;
Bump mapping的GLSL实现
Bump mapping的GLSL实现 void main() 
Bump mapping的GLSL实现 {
Bump mapping的GLSL实现     vec3 BumpNorm = vec3(texture2D(BumpTex, gl_TexCoord[0].xy));
Bump mapping的GLSL实现     BumpNorm = (BumpNorm -0.5* 2.0;
Bump mapping的GLSL实现     
Bump mapping的GLSL实现     vec4 DecalCol = texture2D(DecalTex, gl_TexCoord[0].xy);
Bump mapping的GLSL实现     
Bump mapping的GLSL实现     float NdotL = max(dot(BumpNorm, LightDir), 0.0);
Bump mapping的GLSL实现     
Bump mapping的GLSL实现     vec3 h = normalize(LightDir+EyeDir);
Bump mapping的GLSL实现     float NdotH = max(dot(BumpNorm, h), 0.0);
Bump mapping的GLSL实现     
Bump mapping的GLSL实现     vec3 diffuse = vec3(NdotL * gl_LightSource[0].diffuse * DecalCol);
Bump mapping的GLSL实现     vec3 specular = vec3(pow(NdotH, 6* gl_LightSource[0].specular);
Bump mapping的GLSL实现     
Bump mapping的GLSL实现     gl_FragColor = vec4(diffuse + specular, 1.0);
Bump mapping的GLSL实现 }
Bump mapping的GLSL实现

你可能感兴趣的:(mapping)