UnityShader入门精要学习笔记(九):基础纹理之渐变纹理与遮罩纹理

来源:互联网 发布:淘宝的pc是什么意思 编辑:程序博客网 时间:2024/05/17 22:45

一.渐变纹理

利用半兰伯特构建float2变量,以此对一张渐变纹理进行采样。漫反射的颜色靠此方式获得。

Shader "Custom/Edu/RampTexture" {    Properties {        _Color ("Color", Color) = (1,1,1,1)        //_MainTex ("Albedo (RGB)", 2D) = "white" {}        _Specular("Specular",Color) = (1,1,1,1)        _RampTex("Ramp Texture",2D) = "white"{}        _Gloss("Gloss",Range(9,256)) = 40    }    SubShader {        Pass        {            Tags{"LightMode" = "ForwardBase"}            CGPROGRAM            #pragma vertex vert            #pragma fragment frag            #include "UnityCG.cginc"            #include "Lighting.cginc"            fixed4 _Color;            //sampler2D _MainTex;            sampler2D _RampTex;            float4 _RampTex_ST;            fixed4 _Specular;            float _Gloss;            struct a2v            {                float4 vertex:POSITION;                float3 normal:NORMAL;                //float4 texcoord:TEXCOORD0;            };            struct v2f            {                float4 pos:SV_POSITION;                float3 worldNormal:TEXCOORD0;                float3 worldPos:TEXCOORD1;                //float2 uv:TEXCOORD2;            };            v2f vert(a2v v)            {                v2f o;                o.pos = mul(UNITY_MATRIX_MVP,v.vertex);                o.worldNormal = mul(v.normal,(float3x3)_World2Object);                o.worldPos = mul((float3x3)_Object2World,v.vertex);                //o.uv = TRANSFORM_TEX(v.texcoord,_RampTex);                return o;            }            fixed4 frag(v2f i):SV_Target            {                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;                float3 worldNormal = normalize(i.worldNormal);                float3 worldLightDir = normalize( UnityWorldSpaceLightDir(i.worldPos) );                float halfLambert = dot(worldNormal,worldLightDir) * 0.5 + 0.5;                fixed3 diffuseColor = tex2D(_RampTex,float2(halfLambert,halfLambert)).rgb;                fixed3 diffuse = diffuseColor * _LightColor0.rgb;                float3 worldViewDir = UnityWorldSpaceViewDir(i.worldPos);                float3 halfDir = normalize(worldViewDir + worldLightDir);                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow( saturate(dot(worldNormal,halfDir)), _Gloss);                return fixed4(ambient + diffuse + specular, 1.0);            }            ENDCG        }    }    FallBack "Diffuse"}

效果图:

这里写图片描述

二.遮罩纹理

这遮罩纹理的使用是对高光效果进行遮罩,使用同一组uv坐标,对同一位置处的遮罩纹理进行采样,这里只使用了r分量。
同样,可以分为切线空间下计算以及世界空间下计算。

1.切线空间下的高光遮罩纹理实现:

Shader "Custom/Edu/MaskTexTangent" {    Properties    {        _MainTex("MainTex",2D) = "white"{}        _BumpMap("BumpMap",2D) = "white"{}        _BumpScale("BumpScale",float) = 1        _SpecularMask("SpecularMask",2D) = "white"{}        _Specular("Specular",Color) = (1,1,1,1)        _Color("ColorTint",Color) = (1,1,1,1)        _Diffuse("DIffuse",Color) = (1,1,1,1)        _SpecularScale("SpecularScale",float) = 1.0        _Gloss("Gloss",Range(8,256)) = 8    }    SubShader    {        Pass        {            Tags{"LightMode" = "ForwardBase"}            CGPROGRAM            #pragma vertex vert            #pragma fragment frag            #include "UnityCG.cginc"            #include "Lighting.cginc"            sampler2D _MainTex;float4 _MainTex_ST;            sampler2D _SpecularMask;float4 _SpecularMask_ST;            sampler2D _BumpMap;float4 _BumpMap_ST;            float _BumpScale;            fixed4 _Specular;            fixed4 _Color;            fixed4 _Diffuse;            float _Gloss;            float _SpecularScale;            struct a2v            {                float4 vertex:POSITION;                float3 normal:NORMAL;                //注意因为我们要使用tangent的w分量,所以这里的类型是float4                float4 tangent:TANGENT;                float4 texcoord:TEXCOORD0;            };            struct v2f            {                float4 pos:SV_POSITION;                float2 uv:TEXCOORD0;                float3 viewDir:TEXCOORD1;                float3 lightDir:TEXCOORD2;            };            v2f vert(a2v v)            {                v2f o;                o.pos = mul(UNITY_MATRIX_MVP,v.vertex);                float3 bionormal = cross(normalize(v.normal),normalize(v.tangent.xyz))*v.tangent.w;                //float3x3是一种类型,不需要类型转换时不用加括号                float3x3 rotation = float3x3(v.tangent.xyz,bionormal,v.normal);                //or just use TANGENT_SPACE_ROTATION;                //注意,注意取xyz分量                o.viewDir = mul(rotation,ObjSpaceViewDir(v.vertex)).xyz;                o.lightDir = mul(rotation,ObjSpaceLightDir(v.vertex)).xyz;                //o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;                //o.uv.zw = v.texcoord.xy * _BumpTex_ST.xy + _BumpMap_ST.zw;                o.uv.xy = TRANSFORM_TEX(v.texcoord,_MainTex);                //o.uv.zw = TRANSFORM_TEX(v.texcoord,_BumpMap);                return o;            }            fixed4 frag(v2f i):SV_Target            {                float3 tangentViewDir = normalize(i.viewDir);                float3 tangentLightDir = normalize(i.lightDir);                //使用的是fixed3类型                fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap,i.uv));                tangentNormal.xy *= _BumpScale;                tangentNormal.z = sqrt(1.0-saturate(dot(tangentNormal.xy,tangentNormal.xy)));                fixed3 albedo = tex2D(_MainTex,i.uv).rgb * _Color.rgb;                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;                //半兰伯特模型                //fixed3 halfLambert = dot(tangentNormal,tangentLightDir) * 0.8 + 0.2;                //fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert;                fixed3 diffuse = _LightColor0.rgb * albedo * _Diffuse * saturate(dot(tangentNormal,tangentLightDir));                //潜意识中的错误写法,误以为和渐变纹理的使用方式一样?!                fixed3 halfDir = normalize(tangentViewDir + tangentLightDir);                //fixed3 maskColor = tex2D(_MaskTex,float2(halfDir,halfDir)).rgb;                //正确写法:通过uv对MaskTex对应位置进行采样!!!                //fixed3 specularMask = tex2D(_MaskTex,i.uv.xy).rgb * _SpecularScale;                //不好意思上面仍然不是正确的写法                //所谓的 specularMask 实际上只利用采样纹理的一个分量通道,这里仅仅利用r。                fixed specularMask = tex2D(_SpecularMask,i.uv).r * _SpecularScale;                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tangentNormal,halfDir)),_Gloss) * specularMask;                return fixed4(ambient + diffuse + specular,1.0);            }            ENDCG        }    }}

2.世界空间下高光遮罩纹理实现:

Shader "Custom/Edu/MaskTexWorld" {    Properties {        _Color ("ColorTint", Color) = (1,1,1,1)        _MainTex ("Albedo (RGB)", 2D) = "white" {}        _Gloss ("Gloss", Range(8,256)) = 20        _BumpMap("BumpMap",2D) = "white"{}        _BumpScale("BumpScale",Range(-1,1)) = 1        _Specular("Specular",Color) = (1,1,1,1)        _SpecularMask("SpecularMask",2D) = "white"{}        _SpecularScale("SpecularScale",float) = 1.0    }    SubShader {        Pass        {            Tags{"LgihtMode" = "ForwarBase"}            CGPROGRAM            #pragma vertex vert            #pragma fragment frag            #include "UnityCG.cginc"            #include "Lighting.cginc"            fixed4 _Color;            sampler2D _MainTex;            float4 _MainTex_ST;            float _Gloss;            sampler2D _BumpMap;            float _BumpScale;            fixed4 _Specular;            sampler2D _SpecularMask;            float _SpecularScale;            struct a2v            {                float4 vertex:POSITION;                float3 normal:NORMAL;                float4 texcoord:TEXCOORD0;                float4 tangent:TANGENT;            };            struct v2f            {                float4 pos:SV_POSITION;                float4 TtoW0:TEXCOORD0;                float4 TtoW1:TEXCOORD1;                float4 TtoW2:TEXCOORD2;                float2 uv:TEXCOORD3;            };            v2f vert(a2v v)            {                v2f o;                o.pos = mul(UNITY_MATRIX_MVP,v.vertex);                //需要归一化么?(其实返回的结果已经归一化了)                float3 worldNormal = normalize( UnityObjectToWorldNormal(v.normal) );                float3 worldTangent = normalize( UnityObjectToWorldDir(v.tangent.xyz) );                float3 worldBionormal = cross(worldNormal,worldTangent)*v.tangent.w;                float3 worldPos = mul(_Object2World,v.vertex);                o.TtoW0 = float4(worldTangent.x,worldBionormal.x,worldNormal.x,worldPos.x);                o.TtoW1 = float4(worldTangent.y,worldBionormal.y,worldNormal.y,worldPos.y);                o.TtoW2 = float4(worldTangent.z,worldBionormal.z,worldNormal.z,worldPos.z);                o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;                return o;            }            fixed4 frag(v2f i):SV_Target            {                float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);                //为啥老是忘记归一化呢                float3 worldLightDir =normalize(UnityWorldSpaceLightDir(worldPos));                //为啥老是忘记归一化呢                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));                float3 bump = UnpackNormal(tex2D(_BumpMap,i.uv));                bump.xy *= _BumpScale;                bump.z = sqrt(1-saturate(dot(bump.xy,bump.xy)));                float3 worldNormal = normalize( float3(dot(bump,i.TtoW0.xyz),dot(bump,i.TtoW1.xyz),dot(bump,i.TtoW2.xyz)) );                fixed3 albedo = tex2D(_MainTex,i.uv).rgb;                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;                fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(worldNormal,worldLightDir));                fixed specularMask = tex2D(_SpecularMask,i.uv).r * _SpecularScale;                fixed3 halfDir = normalize(worldLightDir + worldViewDir);                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfDir)),_Gloss) * specularMask;                return fixed4(ambient + diffuse + specular,1.0);            }            ENDCG        }    }    FallBack "Diffuse"}

3.效果图:

这里写图片描述

两种方式看不出任何差别。

阅读全文
0 0
原创粉丝点击