• Unity Shader:(九)基础纹理


    一、UV坐标

    Q:什么是UV坐标?

    A:顶点在纹理中对应的2D坐标,通常用(u,v)表示。

    Q:UV坐标取值范围?

    A:纹理有很多种像素大小,但是UV坐标通常被归一化在[0,1]范围内。

    Q:原点(0,0)在纹理哪个位置?

    A:左下角。

     二、单张纹理

     1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
     2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
     3 
     4 Shader "Unlit/SingleTexture"
     5 {
     6     Properties
     7     {
     8         _MainTex("Texture", 2D) = "white" {}
     9         _Color("Color",Color) = (1,1,1,1)
    10         _Specular("Specular", Color) = (1, 1, 1, 1)
    11         _Gloss("Gloss",Range(8.0,256)) = 20
    12     }
    13         SubShader
    14         {
    15             Pass
    16             {
    17                 Tags { "LightMode" = "ForwardBase" }
    18 
    19                 CGPROGRAM
    20                 #pragma vertex vert
    21                 #pragma fragment frag
    22 
    23                 #include "Lighting.cginc"
    24 
    25                 sampler2D _MainTex;
    26                 fixed4 _Color;
    27                 fixed4 _Specular;
    28                 float _Gloss;
    29                 float4 _MainTex_ST;
    30 
    31             struct a2v //顶点着色器的输入结构体
    32             {
    33                 float4 vertex : POSITION;
    34                 float3 normal:NORMAL;
    35                 float4 texcoord : TEXCOORD0;
    36             };
    37 
    38             struct v2f  //顶点着色器的输出结构体
    39             {
    40                 float4 pos : SV_POSITION;
    41                 float3 worldNormal:TEXCOORD0;
    42                 float3 worldPos:TEXCOORD1;
    43                 float2 uv:TEXCOORD2;
    44             };
    45 
    46             //顶点着色器
    47             v2f vert(a2v v)
    48             {
    49                 v2f o;
    50                 o.pos = UnityObjectToClipPos(v.vertex);
    51                 o.worldNormal = UnityObjectToWorldNormal(v.normal);
    52                 o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
    53                 o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    54                 return o;
    55             }
    56 
    57             fixed4 frag(v2f i) : SV_Target
    58             {
    59                 fixed3 worldNormal = normalize(i.worldNormal);//计算世界空间下的法线方向
    60                 fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));//计算世界空间下的光照方向
    61                 //材质的反射率
    62                 fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb; //tex2D纹理采样:第一个参数:需要被采样的纹理,第二个参数:纹理坐标
    63                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo; //环境光照*材质反射率=环境光
    64                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));//漫反射
    65                 fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
    66                 fixed3 halfDir = normalize(worldLightDir + viewDir);
    67                 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss); //高光反射
    68                 return fixed4(ambient + diffuse + specular, 1.0);
    69             }
    70             ENDCG
    71         }
    72 
    73         }
    74             Fallback "Specular"
    75 }
    View Code

    三、凹凸映射

    使用一张纹理来修改模型的表面法线。

    方法一:高度纹理:模拟表面位移然后得到一个修改后的发现值。

    高度图的颜色越浅表示越凸。

    优点:直观。

    缺点:计算复杂。由像素灰度值计算而得。

    方法二:法线纹理:直接存储表面法线。

    法线方向分量范围 [-1,1]

    像素分量范围[0,1]

    相互转换:pixel = ( normal + 1 ) / 2

           normal = pixel * 2 -1

    切线空间的法线纹理

    优点:实现简单;边界更平滑;自由度高(见与模型空间法线区别);可进行UV动画;可重用;可压缩。

    与模型空间法线区别:模型空间法线纹理记录的是绝对法线信息,仅可用于创建它时的那个模型,不能应用到其他模型。

    而切线空间下法线纹理是相对法线信息,就算应用到不同网格上,也可以得到一个合理的结果。

    实现:

    1. 切线空间下计算:

    思路:在片元着色器中通过纹理采样 => 切线空间下的法线

    顶点着色器:从模型空间变换到切线空间 =>

    计算视角方向、光照方向 => 光照结果

     1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
     2 
     3 Shader "Unity Shaders Book/Chapter 7/Normal Map In Tangent Space" {
     4     Properties {
     5         _Color ("Color Tint", Color) = (1, 1, 1, 1)
     6         _MainTex ("Main Tex", 2D) = "white" {}
     7         _BumpMap ("Normal Map", 2D) = "bump" {}  //法线纹理,bump是内置纹理
     8         _BumpScale ("Bump Scale", Float) = 1.0   //控制凹凸层度
     9         _Specular ("Specular", Color) = (1, 1, 1, 1)
    10         _Gloss ("Gloss", Range(8.0, 256)) = 20
    11     }
    12     SubShader {
    13         Pass { 
    14             Tags { "LightMode"="ForwardBase" }
    15         
    16             CGPROGRAM
    17             
    18             #pragma vertex vert
    19             #pragma fragment frag
    20             
    21             #include "Lighting.cginc"
    22             
    23             fixed4 _Color;
    24             sampler2D _MainTex;
    25             float4 _MainTex_ST;
    26             sampler2D _BumpMap;
    27             float4 _BumpMap_ST;
    28             float _BumpScale;
    29             fixed4 _Specular;
    30             float _Gloss;
    31             
    32             struct a2v {
    33                 float4 vertex : POSITION;
    34                 float3 normal : NORMAL;
    35                 float4 tangent : TANGENT;   //切线方向 第4个坐标用来表示副切线的方向
    36                 float4 texcoord : TEXCOORD0;
    37             };
    38             
    39             struct v2f {
    40                 float4 pos : SV_POSITION;
    41                 float4 uv : TEXCOORD0;
    42                 float3 lightDir: TEXCOORD1;
    43                 float3 viewDir : TEXCOORD2;
    44             };
    45             
    46             v2f vert(a2v v) {
    47                 v2f o;
    48                 o.pos = UnityObjectToClipPos(v.vertex);
    49                 
    50                 o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    51                 o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
    52                 
    53                 //UnityCG.cginc中定义,直接得到rotation变换矩阵
    54                 TANGENT_SPACE_ROTATION;
    55                 
    56                 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;//把模型空间下的光照变换到切线空间
    57                 o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz; //把模型空间下的视角方向变换到切线空间
    58                 
    59                 return o;
    60             }
    61             
    62             fixed4 frag(v2f i) : SV_Target {                
    63                 fixed3 tangentLightDir = normalize(i.lightDir);
    64                 fixed3 tangentViewDir = normalize(i.viewDir);
    65                 
    66                 fixed4 packedNormal = tex2D(_BumpMap, i.uv.zw); //对法线纹理采样
    67                 fixed3 tangentNormal;
    68                 
    69                 tangentNormal = UnpackNormal(packedNormal);
    70                 tangentNormal.xy *= _BumpScale;
    71                 tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
    72                 
    73                 fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
    74                 
    75                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
    76                 
    77                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
    78 
    79                 fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
    80                 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss);
    81                 
    82                 return fixed4(ambient + diffuse + specular, 1.0);
    83             }
    84             
    85             ENDCG
    86         }
    87     } 
    88     FallBack "Specular"
    89 }
    View Code

    效果图:

    凹凸层度调成-1,就是凸起效果:

     2. 世界空间下计算

    在片元着色器中把法线方向从切线空间变换到世界空间下。

    顶点着色器:顶点切线、副切线、法线 => 从切线空间到世界空间的变换矩阵,传递给片元着色器。

    片元着色器:法线方向从切空间转换到世界空间。

     1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
     2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
     3 
     4 Shader "Unity Shaders Book/Chapter 7/Normal Map In World Space" {
     5     Properties {
     6         _Color ("Color Tint", Color) = (1, 1, 1, 1)
     7         _MainTex ("Main Tex", 2D) = "white" {}
     8         _BumpMap ("Normal Map", 2D) = "bump" {}
     9         _BumpScale ("Bump Scale", Float) = 1.0
    10         _Specular ("Specular", Color) = (1, 1, 1, 1)
    11         _Gloss ("Gloss", Range(8.0, 256)) = 20
    12     }
    13     SubShader {
    14         Pass { 
    15             Tags { "LightMode"="ForwardBase" }
    16         
    17             CGPROGRAM
    18             
    19             #pragma vertex vert
    20             #pragma fragment frag
    21             
    22             #include "Lighting.cginc"
    23             
    24             fixed4 _Color;
    25             sampler2D _MainTex;
    26             float4 _MainTex_ST;
    27             sampler2D _BumpMap;
    28             float4 _BumpMap_ST;
    29             float _BumpScale;
    30             fixed4 _Specular;
    31             float _Gloss;
    32             
    33             struct a2v {
    34                 float4 vertex : POSITION;
    35                 float3 normal : NORMAL;
    36                 float4 tangent : TANGENT;
    37                 float4 texcoord : TEXCOORD0;
    38             };
    39             
    40             struct v2f {
    41                 float4 pos : SV_POSITION;
    42                 float4 uv : TEXCOORD0;
    43                 float4 TtoW0 : TEXCOORD1;  
    44                 float4 TtoW1 : TEXCOORD2;  
    45                 float4 TtoW2 : TEXCOORD3; 
    46             };
    47             
    48             v2f vert(a2v v) {
    49                 v2f o;
    50                 o.pos = UnityObjectToClipPos(v.vertex);
    51                 
    52                 o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    53                 o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;
    54                 
    55                 float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
    56                 fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
    57                 fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
    58                 fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 
    59                 
    60                 // Compute the matrix that transform directions from tangent space to world space
    61                 // Put the world position in w component for optimization
    62                 o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
    63                 o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
    64                 o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
    65                 
    66                 return o;
    67             }
    68             
    69             fixed4 frag(v2f i) : SV_Target {
    70                 // Get the position in world space        
    71                 float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
    72                 // Compute the light and view dir in world space
    73                 fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
    74                 fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
    75                 
    76                 // Get the normal in tangent space
    77                 fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
    78                 bump.xy *= _BumpScale;
    79                 bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
    80                 // Transform the narmal from tangent space to world space
    81                 bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
    82                 
    83                 fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
    84                 
    85                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
    86                 
    87                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));
    88 
    89                 fixed3 halfDir = normalize(lightDir + viewDir);
    90                 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);
    91                 
    92                 return fixed4(ambient + diffuse + specular, 1.0);
    93             }
    94             
    95             ENDCG
    96         }
    97     } 
    98     FallBack "Specular"
    99 }
    View Code

    四、渐变纹理

     1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
     2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
     3 
     4 Shader "Unity Shaders Book/Chapter 7/Ramp Texture" {
     5     Properties {
     6         _Color ("Color Tint", Color) = (1, 1, 1, 1)
     7         _RampTex ("Ramp Tex", 2D) = "white" {}
     8         _Specular ("Specular", Color) = (1, 1, 1, 1)
     9         _Gloss ("Gloss", Range(8.0, 256)) = 20
    10     }
    11     SubShader {
    12         Pass { 
    13             Tags { "LightMode"="ForwardBase" }
    14         
    15             CGPROGRAM
    16             
    17             #pragma vertex vert
    18             #pragma fragment frag
    19 
    20             #include "Lighting.cginc"
    21             
    22             fixed4 _Color;
    23             sampler2D _RampTex;
    24             float4 _RampTex_ST;
    25             fixed4 _Specular;
    26             float _Gloss;
    27             
    28             struct a2v {
    29                 float4 vertex : POSITION;
    30                 float3 normal : NORMAL;
    31                 float4 texcoord : TEXCOORD0;
    32             };
    33             
    34             struct v2f {
    35                 float4 pos : SV_POSITION;
    36                 float3 worldNormal : TEXCOORD0;
    37                 float3 worldPos : TEXCOORD1;
    38                 float2 uv : TEXCOORD2;
    39             };
    40             
    41             v2f vert(a2v v) {
    42                 v2f o;
    43                 o.pos = UnityObjectToClipPos(v.vertex);
    44                 
    45                 o.worldNormal = UnityObjectToWorldNormal(v.normal);
    46                 
    47                 o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    48                 
    49                 o.uv = TRANSFORM_TEX(v.texcoord, _RampTex);
    50                 
    51                 return o;
    52             }
    53             
    54             fixed4 frag(v2f i) : SV_Target {
    55                 fixed3 worldNormal = normalize(i.worldNormal);
    56                 fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
    57                 
    58                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    59                 
    60                 // Use the texture to sample the diffuse color
    61                 fixed halfLambert  = 0.5 * dot(worldNormal, worldLightDir) + 0.5;//半兰伯特模型
    62                 fixed3 diffuseColor = tex2D(_RampTex, fixed2(halfLambert, halfLambert)).rgb * _Color.rgb;
    63                 
    64                 fixed3 diffuse = _LightColor0.rgb * diffuseColor;
    65                 
    66                 fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
    67                 fixed3 halfDir = normalize(worldLightDir + viewDir);
    68                 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
    69                 
    70                 return fixed4(ambient + diffuse + specular, 1.0);
    71             }
    72             
    73             ENDCG
    74         }
    75     } 
    76     FallBack "Specular"
    77 }
    View Code

    需要注意,要把渐变纹理的Wrap Mode改为Clamp模式,因为精度问题,Repeat模式可能会在高光区域反黑点。

    五、遮罩纹理

    遮罩有什么作用?遮罩允许我们可以保护某些区域,使他们免于某些修改。

     1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
     2 
     3 Shader "Unity Shaders Book/Chapter 7/Mask Texture" {
     4     Properties {
     5         _Color ("Color Tint", Color) = (1, 1, 1, 1)
     6         _MainTex ("Main Tex", 2D) = "white" {}
     7         _BumpMap ("Normal Map", 2D) = "bump" {}
     8         _BumpScale("Bump Scale", Float) = 1.0
     9         _SpecularMask ("Specular Mask", 2D) = "white" {} //遮罩纹理
    10         _SpecularScale ("Specular Scale", Float) = 1.0  //遮罩影响度
    11         _Specular ("Specular", Color) = (1, 1, 1, 1)
    12         _Gloss ("Gloss", Range(8.0, 256)) = 20
    13     }
    14     SubShader {
    15         Pass { 
    16             Tags { "LightMode"="ForwardBase" }
    17         
    18             CGPROGRAM
    19             
    20             #pragma vertex vert
    21             #pragma fragment frag
    22             
    23             #include "Lighting.cginc"
    24             
    25             fixed4 _Color;
    26             sampler2D _MainTex;
    27             float4 _MainTex_ST;
    28             sampler2D _BumpMap;
    29             float _BumpScale;
    30             sampler2D _SpecularMask;
    31             float _SpecularScale;
    32             fixed4 _Specular;
    33             float _Gloss;
    34             
    35             struct a2v {
    36                 float4 vertex : POSITION;
    37                 float3 normal : NORMAL;
    38                 float4 tangent : TANGENT;
    39                 float4 texcoord : TEXCOORD0;
    40             };
    41             
    42             struct v2f {
    43                 float4 pos : SV_POSITION;
    44                 float2 uv : TEXCOORD0;
    45                 float3 lightDir: TEXCOORD1;
    46                 float3 viewDir : TEXCOORD2;
    47             };
    48             
    49             v2f vert(a2v v) {
    50                 v2f o;
    51                 o.pos = UnityObjectToClipPos(v.vertex);
    52                 
    53                 o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    54                 
    55                 TANGENT_SPACE_ROTATION;
    56                 o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
    57                 o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;
    58                 
    59                 return o;
    60             }
    61             
    62             fixed4 frag(v2f i) : SV_Target {
    63                  fixed3 tangentLightDir = normalize(i.lightDir);
    64                 fixed3 tangentViewDir = normalize(i.viewDir);
    65 
    66                 fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uv));
    67                 tangentNormal.xy *= _BumpScale;
    68                 tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
    69 
    70                 fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
    71                 
    72                 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
    73                 
    74                 fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
    75                 
    76                  fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
    77                  // Get the mask value
    78                  fixed specularMask = tex2D(_SpecularMask, i.uv).r * _SpecularScale;
    79                  // Compute specular term with the specular mask
    80                  fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss) * specularMask;
    81             
    82                 return fixed4(ambient + diffuse + specular, 1.0);
    83             }
    84             
    85             ENDCG
    86         }
    87     } 
    88     FallBack "Specular"
    89 }
    View Code
  • 相关阅读:
    linux系统编程程序员必备
    postgresql查询优化之GIN(Generalized Inverted Index)索引与全文检索
    postgresql并行执行
    lightdb for postgresql日志详解
    PostgreSQL 使用数组类型
    postgresql wal文件误删恢复
    汉语词性标注集
    postgresql----JSON类型、函数及全文检索的支持
    postgresql等待事件之wait_event为空解析
    lightdb for pg查看锁
  • 原文地址:https://www.cnblogs.com/tomatokely/p/15884665.html
Copyright © 2020-2023  润新知