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 }
  • 相关阅读:
    《Programming WPF》翻译 第8章 1.动画基础
    一些被遗忘的设计模式
    《Programming WPF》翻译 第4章 数据绑定
    《Programming WPF》翻译 第3章 控件
    《Programming WPF》翻译 第5章 样式和控件模板
    《Programming WPF》翻译 第7章 绘图
    《Programming WPF》翻译 第9章 自定义控件
    《Programming WPF》翻译 第7章 绘图 (2)
    《Programming WPF》翻译 第8章 前言
    关于Debug和Release之本质区别
  • 原文地址:https://www.cnblogs.com/SeaSwallow/p/6895109.html
Copyright © 2011-2022 走看看