ShaderLab 法线贴图(凹凸材质)

xiaoxiao2021-02-28  88

http://www.manew.com/thread-97665-1-1.html

内容说明:     1. 法线贴图的原理     2. 法线贴图的unity实现 1. 法线贴图的原理     1.1 什么是法线贴图?     每个顶点都有一条法线,三角形内部法线由插值计算得出,颜色则是直接从纹理取数据。法线贴图的基本思想就是像纹理采样一样为法线取值。     1.2法线纹理     下图是一张法线的纹理图:     每个纹素的RGB值实际上表示的是XYZ向量:颜色的分量取值范围为0到1,而向量的分量取值范围是-1到1;可以建立从纹素到法线的简单映射: normal = (2*color)-1    法线纹理的映射方式和漫反射纹理相似。麻烦之处在于如何将法线从各三角形局部空间(切线空间tangent space,亦称图像空间image space)变换到模型空间(着色计算所采用的空间)。     1.3切线空间     大家对矩阵已经十分熟悉了,应该知道定义一个空间需要三个向量。现在Up向量已经有了,即法线:      然后是切线T:垂直于法线的向量。但这样的切线有很多个:   这么多切线中该选哪个呢?理论上哪一个都行。但我们必须保持连续一致性,以免衔接处出现瑕疵。Unity已经给我提供好了Tangent。     定义一组基需要三个向量,因此我们还得计算副切线B。可以使用法线和切线叉乘计算得到。那么切空间就可以表示成如下图这样了。   已知T、B、N向量之后,即可得下面这个漂亮的矩阵,完成从切线空间到模型空间的变换:   只需对上述矩阵求逆即可得逆变换。这个矩阵(正交阵,即各向量相互正交的矩阵,参见下文“延伸阅读”小节)的逆矩阵恰好也就是其转置矩阵,计算十分简单:   2. unity中的实现    我们看下unity实现的代码: [C#]  纯文本查看  复制代码 ?   01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 Shader "Custom/NewSurfaceShader" {      Properties {                  _MainText( "MainText" ,2D)= "white" {}                                 _BumpMap( "BumpMap" ,2D)= "white" {}          }          SubShader {                  pass{                  Tags{ "LightMode" = "ForwardBase" }                  CGPROGRAM                  #pragma vertex vert                  #pragma fragment frag                  #include "UnityCG.cginc"                    float4 _LightColor0;                  sampler2D _BumpMap;                  sampler2D _MainText;                  struct v2f {                          float4 pos:SV_POSITION;                          float2 uv:TEXCOORD0;                          float3 lightDir:TEXCOORD1;                  };                    v2f vert (appdata_full v) {                          v2f o;                          o.pos=mul(UNITY_MATRIX_MVP,v.vertex);                          o.uv=v.texcoord.xy;                          TANGENT_SPACE_ROTATION;                          o.lightDir= mul(_World2Object, _WorldSpaceLightPos0).xyz; //Direction Light                          o.lightDir=mul(rotation,o.lightDir);                          return o;                  }                  float4 frag(v2f i):COLOR                  {                          float4 c=1;                          float3 N=UnpackNormal(tex2D(_BumpMap,i.uv));                          float diff=max(0,dot(N,i.lightDir));                          c=_LightColor0*diff;                          c*=tex2D(_MainText,i.uv);                          return c;                  }                  ENDCG                  }          } }    我们把光照贴图给附上,材质分别给一个平面和一个球看下效果:     2.3 UnpackNormal函数说明 [C#]  纯文本查看  复制代码 ?   01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 inline fixed3 UnpackNormalDXT5nm (fixed4 packednormal) {          fixed3 normal;          normal.xy = packednormal.wy * 2 - 1;          normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));          return normal; }   inline fixed3 UnpackNormal(fixed4 packednormal) { #if defined(UNITY_NO_DXT5nm)          return packednormal.xyz * 2 - 1; #else          return UnpackNormalDXT5nm(packednormal); #endif } 可以看见不同的压缩格式解析有一定的区别,上面讲解的不是很全面,想了解更多可以自行百度下。 2.4 用Surface Shader来实现下 [C#]  纯文本查看  复制代码 ?   01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Shader "Custom/SurfaceShader" {          Properties {                  _MainTex ( "Base (RGB)" , 2D) = "white" {}                  _BumpMap ( "Normalmap" , 2D) = "bump" {}          }            SubShader {                  Tags { "RenderType" = "Opaque" }                  LOD 250                    CGPROGRAM                  #pragma surface surf Lambert noforwardadd                  sampler2D _MainTex;                  sampler2D _BumpMap;                  struct Input {                          float2 uv_MainTex;                  };                    void surf (Input IN, inout SurfaceOutput o) {                          fixed4 c = tex2D(_MainTex, IN.uv_MainTex);                          o.Albedo = c.rgb;                          o.Alpha = c.a;                          o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_MainTex));                  }                  ENDCG           }          FallBack Off } 代码下载地址http://pan.baidu.com/s/1boCvoIz

转载请注明原文地址: https://www.6miu.com/read-57543.html

最新回复(0)