原文地址:WebGL学习之法线贴图

实际效果请看demo:纹理贴图

为了增加额外细节,提升真实感,我们使用了漫反射贴图和高光贴图,它们都是向三角形进行附加纹理。但是从光的视角来看是表面法线向量使表面被视为平坦光滑的表面。以光照算法的视角考虑的话,只有一件事决定物体的形状,那就是垂直于它的法线向量。砖块表面只有一个法向量,表面完全根据这个法向量被以一致的方式照亮。如果每个片元都用不同的法线会怎样?这样我们就可以根据表面细微的细节对法线向量进行改变;这样就会获得一种表面看起来要复杂得多的幻觉:

每个片元使用了自己的法线,我们就可以让光照相信一个表面由很多微小的(垂直于法线向量的)平面所组成,物体表面的细节将会得到极大提升。这种每个片元使用各自的法线,替代一个面上所有片元使用同一个法线的技术叫做法线贴图(normal mapping)或凹凸贴图(bump mapping)。

以上都是从 LearnOpenGL CN 相关的文章摘抄 法线贴图。没办法,WebGL相关比较深入的知识你只能去看openGL,好在原理基本相同,WebGL1就是基于openGL es 2.0,WebGL2就是基于openGL es 3.0。

法线贴图

法线贴图就是用纹理中的颜色向量r、g、b存储法线向量的x、y、z。不过它们有另外的称呼:t (切线)、b (副切线)、n (法线),它们组成了一个切线空间,被称为TBN坐标系。由于颜色与方向的表示范围有区别,颜色范围是[0,1],而作为表示位置方向的TBN坐标系则是[-1,1],那么从法线贴图取出来的值要使用的话,得进行转换。

  1. // 将法线向量转换为范围[-1,1]
  2. vec3 normal = normalize(normal * 2.0 - 1.0);

法线贴图偏蓝是因为所有法线的指向都偏向z轴(0, 0, 1), 对应于rgb 中的 blue分量,也就是蓝色。法线向量从z轴方向向其他方向轻微偏移,于是颜色也就发生轻微变化,这样看起来便有了一种深度。例如,你可以看到顶部颜色倾向于偏绿,这是因为顶部的法线偏向于指向正y轴方向(0, 1, 0)对应于rgb总的 green分量,也就是绿色。

法线贴图的优点是可以用一个低精度模型表现出非常高的细节,看起来像高精度模型那样。

只需要500个三角形的简单网格加上法线贴图就能达到媲美4M个三角形的精细网格模型的效果,可以说法线贴图优势巨大,处理4M个三角形的复杂度简直不可想象。

但法线贴图也不是万能的,它也有缺点。因为它只是改变了物体表面的光照计算方式,所以不适合用在凹凸起伏较大的物体上,这些物体会有遮挡的效果,法线贴图是无法实现的。

而文章 法线贴图 里面有很详细的原理讲解和切线推导过程,最后求出如下的公式,我这里也不再叙述了。

着色器

我这里使用了另外一种更加方便的算法,能达到同样的效果,原理就是使用导数(dFdx/dFdy)求出每个像素在插值化传值过来的点的变化率当成一个法线,请看函数 dHdxy_fwd。然后再通过与当前平面的法向量进行叉积 (cross),即可求得同时垂直于这两个方向的法向量,请看函数 perturbNormalArb,而最终的这个法向量就是我们所要求的值,非常地高明。下面是glsl 内置的几个关键函数。

  1. dFdx(p) //在x方向的偏导数
  2. dFdy(p) //在y方向的偏导数
  3. cross(p0,p1) //向量p0,p1的叉乘

我们用到的求导函数 dFdx / dFdy,在WebGL1是需要开启扩展的,顶点着色器无需变动,主要变动的是片元着色器。具体的计算过程,请看如下片元着色器代码:

  1. #extension GL_OES_standard_derivatives : enable// 注意要开启该扩展
  2. //...
  3. uniform sampler2D u_diffMap;
  4. uniform sampler2D u_specMap;
  5. uniform sampler2D u_normMap;
  6. //...
  7. vec2 dHdxy_fwd() {
  8. vec2 dSTdx = dFdx( v_texcoord );
  9. vec2 dSTdy = dFdy( v_texcoord );
  10. float Hll = bumpScale * texture2D( u_normMap, v_texcoord ).x;
  11. float dBx = bumpScale * texture2D( u_normMap, v_texcoord + dSTdx ).x - Hll;
  12. float dBy = bumpScale * texture2D( u_normMap, v_texcoord + dSTdy ).x - Hll;
  13. return vec2( dBx, dBy );
  14. }
  15. vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {
  16. vec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );
  17. vec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );
  18. vec3 vN = surf_norm;
  19. vec3 R1 = cross( vSigmaY, vN );
  20. vec3 R2 = cross( vN, vSigmaX );
  21. float fDet = dot( vSigmaX, R1 );
  22. fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
  23. vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
  24. return normalize( abs( fDet ) * surf_norm - vGrad );
  25. }
  26. //...
  27. // 从法线贴图计算出逐像素法线向量
  28. vec3 normal = perturbNormalArb( -v_position, normal, dHdxy_fwd());
  29. //...
  30. // 总的光照
  31. gl_FragColor = vec4(ambient + diffuse + specular, diffuseColor.a);

最后效果请看demo:纹理贴图

后记

相关资料 LearnOpenGL CN

WebGL学习之法线贴图的更多相关文章

  1. WebGL学习之纹理贴图

    为了使图形能获得接近于真实物体的材质效果,一般会使用贴图,贴图类型主要包括两种:漫反射贴图和镜面高光贴图.其中漫反射贴图可以同时实现漫反射光和环境光的效果. 实际效果请看demo:纹理贴图 2D纹理 ...

  2. 【Unity Shaders】学习笔记——SurfaceShader(七)法线贴图

    [Unity Shaders]学习笔记——SurfaceShader(七)法线贴图 转载请注明出处:http://www.cnblogs.com/-867259206/p/5627565.html 写 ...

  3. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十九章:法线贴图

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十九章:法线贴图 学习目标 理解为什么需要法线贴图: 学习法线贴图如 ...

  4. 【Unity Shader学习笔记】Unity基础纹理-法线贴图

    1 高度纹理 使用一张纹理改变物体表面法线,为模型提供更多细节. 有两种主要方法: 1.高度映射:使用一张高度纹理(height map)来模拟表面位移(displacement).得到一个修改后的法 ...

  5. WebGL学习之纹理盒

    原文地址:WebGL学习之纹理盒 我们之前已经学习过二维纹理 gl.TEXTURE_2D,而且还使用它实现了各种效果.但还有一种立方体纹理 gl.TEXTURE_CUBE_MAP,它包含了6个纹理代表 ...

  6. 翻译:非常详细易懂的法线贴图(Normal Mapping)

    翻译:非常详细易懂的法线贴图(Normal Mapping) 本文翻译自: Shaders » Lesson 6: Normal Mapping 作者: Matt DesLauriers 译者: Fr ...

  7. shader复杂与深入:Normal Map(法线贴图)1

    转自:http://www.zwqxin.com/archives/shaderglsl/review-normal-map-bump-map.htmlNormal Map法线贴图,想必每个学习计算机 ...

  8. 一个有趣的模拟光照的shader(类似法线贴图)

    最近使用unity,碰到到一个很有趣的例子.场景无光线,却模拟出了光照,效果挺好.其思路与法线贴图原理异曲同工. 原作者提供的效果印象深刻. 模型除了使用原来的diffuse贴图外,还用到了一张模拟记 ...

  9. WebGL学习(2) - 3D场景

    原文地址:WebGL学习(2) - 3D场景 经过前面WebGL学习(1) - 三角形的学习,我们已经掌握了webGL的基础知识,也已经能够画出最基本的图形,比如点,线,三角形,矩形等.有了2D绘图的 ...

随机推荐

  1. 2017年排名前15的数据科学python库

    2017年排名前15的数据科学python库 2017-05-22 Python程序员 Python程序员 Python程序员 微信号 pythonbuluo 功能介绍 最专业的Python社区,有每 ...

  2. 查看自己U盘格式

    转自:https://zhidao.baidu.com/question/220844418.html 选中U盘后,鼠标右键单击,选项菜单中点击属性,出的的属性窗口中的“常规”项里边就有U盘的基本信息 ...

  3. Bootstrap 概览

    目录1.移动设备2.响应式图片3.Normalize4.Containers 1.移动设备在Bootstrap 3中,我们重写了整个框架,使其一开始就是对移动设备友好的.这次不是简单的增加一些可选的针 ...

  4. Python基本数据类型之字符串、数字、布尔

     一.数据类型种类 Python中基本数据类型主要有以下几类: Number(数字) String(字符串) Bool (布尔) List(列表) Tuple(元组) Sets(集合) Diction ...

  5. 【光速使用开源框架系列】数据库框架OrmLite

    [关于本系列] 最近看了不少开源框架,网上的资料也非常多,但是我认为了解一个框架最好的方法就是实际使用.本系列博文就是带领大家快速的上手一些常用的开源框架,体会到其作用. 由于作者水平有限,本系列只会 ...

  6. spring 3.1.13中新增的util @value注解,给类或方法注入值

    在spring 3.0以上版本中,可以通过使用@value,对一些如xxx.properties文件 ,进行键值对的注入,例子如下: 一.类变量注入 1 首先在applicationContext.x ...

  7. 有关Lucene的问题(4):影响Lucene对文档打分的四种方式

    原文出自:http://forfuture1978.iteye.com/blog/591804点击打开链接 在索引阶段设置Document Boost和Field Boost,存储在(.nrm)文件中 ...

  8. 27-拓扑排序-poj1094

    http://poj.org/problem?id=1094 Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Su ...

  9. 虚拟机Ubuntu16.04安装lrzsz

    [系统环境] 宿主机:Win7 64位 虚拟机软件:Vmware workstation 12 虚拟机:Ubuntu 16.0.4 [目的] 配合Secure CRT使用rz,sz,方便在Ubuntu ...

  10. Web网站的几个QPS

    评价一个网站的"大小",处于视角的不同,有很多种衡量的方法,类似文章数,页面数之类的数据非常明显,也没有什么可以争议的.但对于并发来说,争议非常之多,这里就从一个技术的角度开始,谈 ...