zoukankan      html  css  js  c++  java
  • [Unity Shader] 切线空间的法线贴图

      切线空间的法线贴图,可以这样理解:

      #纹理坐标是从0到1,它的坐标是x向右,y向下

      #顶点坐标是从-1到-1,坐标是x向右,y向上

      1 由表面上某点的切线Tangent、副切线Bitangent、法线Normal形成一个新的坐标系,即切线空间。

      2 其中与法线垂直的切线有很多,在Unity中或者是Cg中,规定纹理坐标的方向u和v作为切线和副切线的方向

      3 修改法线的方向,会让表面看起来有凹凸感。这时在切线空间中,调整后的法线看起来是对原法线的扰动。

      4 其扰动后的在切线空间中的坐标(x, y, z),其中x是u方向上的偏移,y是v方向上的偏移,z则是法线方向上的偏移。

      5 将其作为颜色存储在法线贴图中。由于归一化之后的法线坐标,各分量范围在[-1, 1]之间,而颜色范围在[0, 1]之间。对其做(x+1)/2的映射计算,使其值满足颜色范围。

      6 由于是偏移量,因此当表面凹凸没有变化时,法线为原法线方向(x y z) = (0, 0, 1)。映射到颜色之后为(0.5, 0.5, 1.0)。这也是为什么法线贴图大部分是偏浅蓝色的原因。

      

      7 由于偏移后的法线是归一化的,因此满足x2 + y2 + z2 = 1。知道x和y就可以求出z。因此如果texture的类型被设置为Normal Map,Unity使用DXT5nm压缩算法,对法线贴图进行了压缩。只存储x和y的值,存储在贴图中的a和g通道(即w和y),这样另外两个通道可对其他数据进行存储。见UnityCG.cginc的UnpackNormal函数

      

     1 inline fixed3 UnpackNormalDXT5nm (fixed4 packednormal)
     2 {
     3     fixed3 normal;
     4     normal.xy = packednormal.wy * 2 - 1;
     5     normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));
     6     return normal;
     7 }
     8 
     9 inline fixed3 UnpackNormal(fixed4 packednormal)
    10 {
    11 #if defined(UNITY_NO_DXT5nm)
    12     return packednormal.xyz * 2 - 1;
    13 #else
    14     return UnpackNormalDXT5nm(packednormal);
    15 #endif
    16 }

      

    书中(《Unity Shader 入门精要》)P153页,求得了世界空间下的切线、副切线、法线后,归一化得到这三个正交分量。按列摆放可得到从切线空间到世界空间的变换矩阵。没有完全理解为什么按列摆放就是从切线空间到世界空间的变换矩阵。不知道下面的推导过程是否正确,先做个记录。

  • 相关阅读:
    按键消抖电路设计——你们遇到的都是伪消抖
    FPGA工程中用C语言对文件进行处理_生成mif文件
    verilog中always块延时总结
    FPGA中改善时序性能的方法_advanced FPGA design
    verilog中连续性赋值中的延时
    verilog中读取文件中的字符串_modelsim高级仿真
    FPGA知识大梳理(四)FPGA中的复位系统大汇总
    c++虚函数几种实现方法
    c++逐渐退化的虚函数
    c++管理内存的几种方式
  • 原文地址:https://www.cnblogs.com/p0e0o0p0l0e0/p/7339881.html
Copyright © 2011-2022 走看看