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的一种计算方法如下:

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

varying vec3 LightDir;
varying vec3 EyeDir;

attribute vec3 Tangent;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;

    // 眼坐标系下的TBN
    vec3 n = normalize(gl_NormalMatrix * gl_Normal);
    vec3 t = normalize(gl_NormalMatrix * Tangent);
    vec3 b = cross(n, t);
    mat3 TBN = mat3(t, b, n);
    
    vec4 pos = gl_ModelViewMatrix * gl_Vertex;
    vec3 epos = vec3(pos)/pos.w;
    
    vec3 v = gl_LightSource[0].position.xyz - epos;
    v = v * TBN;
    LightDir = normalize(v);

    v = -epos * TBN;
    EyeDir = normalize(v);
}

相应的FS如下:

uniform sampler2D BumpTex;
uniform sampler2D DecalTex;

varying vec3 LightDir;
varying vec3 EyeDir;

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

Bump mapping的GLSL实现 [转]

时间: 2024-10-08 17:58:47

Bump mapping的GLSL实现 [转]的相关文章

ZFXEngine开发笔记之Bump Mapping(2)

作者:i_dovelemon 日期: 2014 / 9 / 13 来源 : CSDN 主题 :Bump Mapping, Tangent Space, Normal Map, Height Map 引言 在上篇文章中,我讲述了如何根据高度图来创建法线图.并且承诺在后面会讲述3D几何学中的重要工具Tangent Space的相关知识.今天,就在这里,向大家讲述如何接下来的工作部分. Tangent Space 我们知道,在前篇文章中,讲述的法线图中的法线是在纹理图的空间中也就是Tangent Sp

ZFXEngine开发笔记之Bump Mapping(1)

作者:i_dovelemon 日期:2014 / 9 / 7 来源:CSDN博客 主题:Bump Mapping, Tangent Space, Normal Map, Height Map 引言 我们知道,在真实世界中,任何物体的表面都不是非常光滑的,这种粗糙的表面效果,在光源的照射下会有明暗的感觉.那么,如何在3D图形中模拟这种效果了?是通过建模的方法,为模型的表面建造出粗糙的表面?这种方法很难做出真实的粗糙感出来,毕竟表面的粗糙程度是很细微的效果,很难用建模的方式建模出来.所以,只能用其他

凹凸映射(Bump mapping)

Bump mapping is very much like Texture Mapping. However, where Texture Mapping added colour to a polygon, Bump Mapping adds, what appears to be surface roughness. This can have a dramatic effect on the look of a polygonal object. Bump Mapping can add

《Normal Mapping》

原文地址:https://learnopengl-cn.github.io/05%20Advanced%20Lighting/04%20Normal%20Mapping/ 原文 Normal Mapping 作者 JoeyDeVries 翻译 Django 校对 KenLee 我们的场景中已经充满了多边形物体,其中每个都可能由成百上千平坦的三角形组成.我们以向三角形上附加纹理的方式来增加额外细节,提升真实感,隐藏多边形几何体是由无数三角形组成的事实.纹理确有助益,然而当你近看它们时,这个事实便隐

Mapping

Reflection mapping cube mapping sphere mapping HEALPix mapping Displacement mapping Bump mapping Normal mapping Parallax mapping Texture mapping

【转】使用 WebGL 进行 3D 开发,第 2 部分: 使用 WebGL 库以更少的编码做更多的事情

转自HTML5开发社区 使用 WebGL 进行 3D 开发,第 1 部分: WebGL 简介使用 WebGL 进行 3D 开发,第 2 部分: 使用 WebGL 库以更少的编码做更多的事情使用 WebGL 进行 3D 开发,第 3 部分: 添加用户交互 WebGL API 让 JavaScript 开发人员能够直接利用如今的 PC 及移动设备硬件中强大的内置 3D 图形加速功能.现代浏览器透明地支持 WebGL,它使人们可以为主流 Web 用户创建高性能的 3D 游戏.应用程序以及 3D 增强的

NormalMap 贴图 【转】

转载: http://www.zwqxin.com/archives/shaderglsl/review-normal-map-bump-map.html 说起Normal Map(法线贴图),就会想起Bump Map(凹凸贴图).Bump Mapping是Blin大师在1978年提出的图形学算法,目的是以低代价给予计算机几何体以更丰富的表面信息(高模盖低模).30年来,这项技术不断延展,尤其是计算机图形学成熟以后,相继出现了不少算法变体,90年代末的Normal Map解放了必须自行计算纹理像

BumpMapping [转]

http://fabiensanglard.net/bumpMapping/index.php Fabien Sanglard's Website Home About FAQ Email Rss Twitter March 19th, 2009 BumpMapping with GLSL When I got started learning bump mapping and parallax mapping, I found a lot of tutorial involving a sim

什么是source引擎?

关于什么是Engine(引擎)? 在Half-Life 完成之后不久,Valve开始筹备他们的下一个主打游戏--Half-Life 2.在商讨游戏引擎的采用问题上,开发小组明白到原版游戏所采用的改良Quake 1引擎对于Half-Life 2来说显得过于破旧,而且在很多的方面都不符合这一代游戏发展的要求.于是,vlave的开发小组决定从美工设计以及游戏代码开始,设计出一个全新的游戏框架,并在其中加入了一套来自havok的定制物理引擎. 对于一个游戏来说,“引擎”就是一个系统,就像是一辆汽车的发动