zoukankan      html  css  js  c++  java
  • Unity Shader 法线贴图的实现

    这里有一个细节,关于法线贴图是有两个不同的空间的,如下:

      切线空间:法线贴图颜色为偏蓝色

      模型空间:法线贴图颜色为五颜六色

    因此根据不同的空间变换位置方便一致计算。

      1 // 法线贴图映射的编写+透明
      2 Shader "TMoon/05-NormalMapAndAlpha" {
      3     Properties{
      4         _Color("Color",Color) = (1,1,1,1)
      5         _MainTex("Main Tex",2D) = "white"{}
      6         _NormalMap("Normal Map",2D) = "bump"{} //bump默认值的意思:若没有法线贴图,则使用顶点自带的
      7         _BumpScale("Bump Scale",Float) = 1
      8         _AlphaScale("Alpha Scale",Float) = 1
      9     }
     10 
     11     SubShader{
     12 
     13         Tags{ "Queue" = "Transparent" "IngnoreProjector" = "True" "RenderType" = "Transparent" }
     14         
     15         Pass{
     16         
     17             Tags {"LightMode" = "ForwardBase"}
     18 
     19             ZWrite Off
     20             Blend SrcAlpha OneMinusSrcAlpha
     21 
     22             CGPROGRAM
     23 
     24             #include "Lighting.cginc"
     25 
     26             #pragma vertex vert
     27             #pragma fragment frag
     28 
     29             fixed4 _Color;
     30             sampler2D _MainTex;
     31             float4 _MainTex_ST;
     32             sampler2D _NormalMap;
     33             float4 _NormalMap_ST;
     34             float _BumpScale;
     35             float _AlphaScale;
     36 
     37             // application to vertex
     38             // 由应用程序传递给顶点函数
     39             struct a2v {
     40                 float4 vertex:POSITION;
     41                 float3 normal:NORMAL; // 切线空间的确定是通过(存储模型里的)法线和(存储模型里的)切线确定的,所以需要模型的法线
     42                 float4 texcoord:TEXCOORD0; // 模型的纹理坐标
     43                 float4 tangent:TANGENT;// 模型空间的切线
     44             };
     45 
     46             // vertex to fragment
     47             // 由顶点函数传递给片元函数
     48             struct v2f {
     49                 float4 svPos:SV_POSITION;
     50                 float4 uv:TEXCOORD0; // uv.xy 存储MainTex的纹理坐标,uv.zw 存储法线贴图的纹理坐标
     51                 float3 lightDir : TEXCOORD1; // 切线空间下平行光的方向
     52             };
     53 
     54             v2f vert(a2v v) {
     55                 v2f f;
     56 
     57                 f.svPos = mul(UNITY_MATRIX_MVP, v.vertex);
     58 
     59                 // 将MainTex纹理坐标赋值给v2f.uv.xy并赋值面板贴图的旋转缩放
     60                 f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
     61                 // 将法线贴图纹理坐标赋值给v2f.uv.zw并赋值面板贴图的旋转缩放
     62                 f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw;
     63 
     64                 // 调用这个宏之后,会得到一个矩阵 rotation
     65                 // 这个矩阵用来把模型空间下的方向转换成切线空间下
     66                 TANGENT_SPACE_ROTATION;
     67 
     68                 //ObjSpaceLightDir(v.vertex) 得到模型空间下的平行光方向
     69                 f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
     70                     
     71                 return f;
     72             }
     73 
     74             float4 frag(v2f f) : SV_Target{
     75 
     76                 // tex2D 根据法线贴图的纹理坐标获取颜色值
     77                 fixed4 normalColor = tex2D(_NormalMap,f.uv.zw);
     78 
     79                 // 切线空间下的法线
     80                 fixed3 tangentNormal = UnpackNormal(normalColor);
     81                 tangentNormal.xy = tangentNormal.xy * _BumpScale;
     82                 tangentNormal = normalize(tangentNormal);
     83 
     84                 fixed3 lightDir = normalize(f.lightDir);
     85 
     86                 // tex2D 根据MainTex贴图的纹理坐标获取颜色值
     87                 fixed3 texColor = tex2D(_MainTex,f.uv.xy) * _Color.rgb;
     88 
     89                 // 为漫反射混合上每个像素点的纹理颜色
     90                 fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(tangentNormal, lightDir), 0);
     91 
     92                 return fixed4(diffuse, _AlphaScale);
     93             }
     94 
     95             ENDCG
     96         }
     97     }
     98 
     99     Fallback "VertexLit"
    100 }
  • 相关阅读:
    最小费用流(km的另一种使用思路)
    最小费用流(km的另一种使用思路)
    Python 字符串格式化
    Python字符串运算符
    Python 字符串连接
    Python 访问字符串中的值
    虚拟纹理与几何图像技术
    深度学习与传统图像识别
    ASML光刻机PK 原子弹,难度?
    L4自动驾驶技术
  • 原文地址:https://www.cnblogs.com/SeaSwallow/p/6895109.html
Copyright © 2011-2022 走看看