Unity Shader實現(xiàn)紋理遮罩效果
紋理遮罩用處很多,簡單來講就是允許我們可以保護(hù)模型中的某些區(qū)域不受某些因素的影響。例如我們有時希望模型表面某些區(qū)域的反光強(qiáng)烈一些,而某些區(qū)域弱一些。為了得到更加細(xì)膩的結(jié)果,我們需要用一張遮罩紋理來控制該光照。還有一些情況就是某些模型需要多張紋理混合時,此時使用遮罩紋理可以控制如何混合這些紋理。
具體流程為:通過采樣得到遮罩紋理的紋素值,然后使用其中某個或者幾個通道的值來與某種表面屬性進(jìn)行相乘。當(dāng)該通道的值為0時,此時該表面屬性不受遮罩紋理的影響。
shader代碼如下:
Shader "Custom/MaskTexture"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Main Tex", 2D) = "white" {}
_BumpMap("Normal Map", 2D) = "white" {}
_BumpScale("Bump Scale", Float) = 1.0
_SpecularMask("Specular Mask", 2D) = "white" {}
_SpecularScale("Specular Scale", Float) = 1.0
_Specular("Specular", Color) = (1,1,1,1)
_Gloss("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST; //紋理變量名+_ST為unity內(nèi)置宏,存儲了該紋理的縮放大小和偏移量,分別對應(yīng).xy和.zw屬性
sampler2D _BumpMap;
float _BumpScale; //控制凹凸程度的變量
sampler2D _SpecularMask; //遮罩紋理
float _SpecularScale; //控制遮罩紋理的可見度
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 lightDir : TEXCOORD1;
float3 viewDir : TEXCOORD2;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//將_MainTex紋理信息(縮放大小和偏移量以及坐標(biāo)信息)存儲到o.uv.xy中
o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
//unity內(nèi)置宏,計算并得到從模型空間到切線空間的變換矩陣rotation
TANGENT_SPACE_ROTATION;
//獲取切線空間下的光照方向
o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
//獲取切線空間下的視角方向
o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//將切線空間下的光照方向和視角方向單位化
fixed3 tangentLightDir = normalize(i.lightDir);
fixed3 tangentViewDir = normalize(i.viewDir);
//獲取切線空間下的法向量
fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uv));
tangentNormal.xy *= _BumpScale;
tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
//獲取片元上的主紋理,并和變量_Color相乘得到其混合結(jié)果
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
//獲取環(huán)境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
//漫反射計算
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));
//高光反射計算,其計算方式跟前文的計算一樣,這里只能另外跟specularMask的遮罩紋理相乘得到其與遮罩紋理的混合結(jié)果
fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
fixed specularMask = tex2D(_SpecularMask, i.uv).r * _SpecularScale;
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss) * specularMask;
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#中DataTable的創(chuàng)建與遍歷實現(xiàn)
這篇文章主要介紹了C#中DataTable的創(chuàng)建與遍歷實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
ItemsControl 數(shù)據(jù)綁定的兩種方式
這篇文章主要介紹了ItemsControl 數(shù)據(jù)綁定的兩種方式,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03
C#操作Clipboard讀取剪切板中數(shù)據(jù)實例詳解
這篇文章主要介紹了C#操作Clipboard讀取剪切板中數(shù)據(jù)的方法,實例分析了C#讀取剪貼板數(shù)據(jù)的具體步驟與實現(xiàn)技巧,需要的朋友可以參考下2015-05-05
C# ManagementObjectSearcher操作window案例詳解
這篇文章主要介紹了C# ManagementObjectSearcher操作window案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法
這篇文章主要介紹了Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法,Windows?11下所有控件已經(jīng)默認(rèn)采用圓角,其效果更好、相對有著更好的優(yōu)化,只是這是默認(rèn)的行為,無法進(jìn)一步自定義,更多詳情需要的小伙伴可以參考下面文章內(nèi)容2022-08-08
c#異步讀取數(shù)據(jù)庫與異步更新ui的代碼實現(xiàn)
這篇文章主要介紹了c#從數(shù)據(jù)庫里取得數(shù)據(jù)并異步更新ui的方法,大家參考使用吧2013-12-12

