Unity 通用透明物体漫反射Shader(双面渲染&多光源&光照衰减&法线贴图&凹凸透明度控制)
生活随笔
收集整理的這篇文章主要介紹了
Unity 通用透明物体漫反射Shader(双面渲染&多光源&光照衰减&法线贴图&凹凸透明度控制)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Shader "MyUnlit/AlphaBlendDiffuse"
{
Properties
{
_Color("Color Tint(貼圖染色)",Color)=(1,1,1,1)
_MainTex ("Texture(主貼圖)", 2D) = "white" {}
//bump為unity內(nèi)置的法線紋理,當(dāng)未配置任何法線紋理時(shí),bump對(duì)應(yīng)模型自帶的法線信息
_NormalMap("Normal Map(法線貼圖)",2D)="bump"{}
_BumpScale("Bump Scale(凹凸程度)",float) = 1.0
_Cutoff("Alpha(整體透明度)",range(0,1)) = 0.5
}
SubShader
{
//透明度混合需要定義的標(biāo)簽
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
//1.Base Pass背面(順序,透明物體先渲染背面再渲染正面)
Pass
{
//提示此Pass為前向渲染中的Base Pass,計(jì)算環(huán)境光,自發(fā)光,平行光中的陰影,不計(jì)算其他疊加光照效果
Tags{ "LightMode" = "ForwardBase" }
//透明度混合需要關(guān)閉深度寫入
ZWrite Off
//開(kāi)啟混合操作并設(shè)置混合類型,此處類型為透明度混合
Blend SrcAlpha OneMinusSrcAlpha
//透明物體要考慮雙面渲染,第一個(gè)Pass只渲染背面,剔除正面
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//Base Pass指令,用于得到對(duì)應(yīng)的光照變量
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
//包含接收陰影的宏
#include "AutoLight.cginc"
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
//用于控制對(duì)應(yīng)紋理的縮放和偏移,格式固定為xx_ST
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _BumpScale;
fixed _Cutoff;//[0,1]范圍內(nèi)用fixed
struct appdata
{
float4 vertex : POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT;//與法線不同,w需要用于控制朝向
float2 uv : TEXCOORD0;
};
struct v2f
{
//節(jié)約空間,xy分量存主貼圖uv;zw存法線貼圖的
float4 uv : TEXCOORD0;
float4 pos : SV_POSITION;//變量名為pos,有關(guān)陰影計(jì)算的宏中使用了此變量
//寄存器中沒(méi)法存矩陣,所以分別存矩陣的每一行
float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
SHADOW_COORDS(4)//此陰影紋理坐標(biāo)存儲(chǔ)在TEXCOORD4中
};
//此處采用在世界空間中計(jì)算法線
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//用兩個(gè)分量分別存儲(chǔ)貼圖的縮放和偏移
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.uv, _NormalMap);
float3 worldPos= mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
//叉積計(jì)算第三個(gè)標(biāo)準(zhǔn)正交基軸向,w指示朝向的正負(fù)
fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
//節(jié)約空間,順便將世界空間中的頂點(diǎn)位置存在w分量中
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
//計(jì)算陰影紋理坐標(biāo)
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//還原世界坐標(biāo)
float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
//還原出矩陣,用于將紋理從頂點(diǎn)空間(切線空間)變?yōu)槭澜缈臻g,統(tǒng)一計(jì)算
float3x3 TtoW= float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz);
//得到世界空間中的光源方向和視線方向
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
//從zw分量中采樣出法線并進(jìn)行凹凸程度的縮放,但此時(shí)法線依然處于頂點(diǎn)空間(切線空間)
fixed3 tanNormal = UnpackNormalWithScale(tex2D(_NormalMap, i.uv.zw), _BumpScale);
//通過(guò)之前構(gòu)造的變換矩陣將法線從頂點(diǎn)空間變換到世界空間
fixed3 worldNormal = mul(TtoW, tanNormal);
//采樣主紋理并染色,得到反射率
fixed4 col = tex2D(_MainTex, i.uv);
fixed3 albedo = col.rgb*_Color.rgb;
//計(jì)算環(huán)境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
//計(jì)算漫反射
fixed3 diffuse = _LightColor0.rgb*albedo*saturate(dot(lightDir, worldNormal));
//計(jì)算光照和陰影衰減值,結(jié)果為第一個(gè)參數(shù)
UNITY_LIGHT_ATTENUATION(atten, i, worldPos);
//返回計(jì)算結(jié)果
return fixed4(ambient + diffuse * atten, col.a * _Cutoff);
}
ENDCG
}
//2.Base Pass正面
Pass
{
Tags{ "LightMode" = "ForwardBase" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//透明物體要考慮雙面渲染,此Pass只渲染正面,剔除背面
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _BumpScale;
fixed _Cutoff;
struct appdata
{
float4 vertex : POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
SHADOW_COORDS(4)
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.uv, _NormalMap);
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
float3x3 TtoW = float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
fixed3 tanNormal = UnpackNormalWithScale(tex2D(_NormalMap, i.uv.zw), _BumpScale);
fixed3 worldNormal = mul(TtoW, tanNormal);
fixed4 col = tex2D(_MainTex, i.uv);
fixed3 albedo = col.rgb*_Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb*albedo*saturate(dot(lightDir, worldNormal));
UNITY_LIGHT_ATTENUATION(atten, i, worldPos);
return fixed4(ambient + diffuse * atten, col.a * _Cutoff);
}
ENDCG
}
//3.Add Pass正常渲染
Pass
{
//提示此Pass為前向渲染中的Add Pass,計(jì)算其他疊加光照效果,每個(gè)光源計(jì)算一次
Tags{ "LightMode" = "ForwardAdd" }
ZWrite Off
Blend SrcAlpha One
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//Add Pass指令,用于得到對(duì)應(yīng)的光照變量
//#pragma multi_compile_fwdadd
//陰影情況下使用:
#pragma multi_compile_fwdadd_fullshadows
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _BumpScale;
fixed _Cutoff;
struct appdata
{
float4 vertex : POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
SHADOW_COORDS(4)
};
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.uv, _NormalMap);
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
float3x3 TtoW = float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
fixed3 tanNormal = UnpackNormalWithScale(tex2D(_NormalMap, i.uv.zw), _BumpScale);
fixed3 worldNormal = mul(TtoW, tanNormal);
fixed4 col = tex2D(_MainTex, i.uv);
fixed3 albedo = col.rgb*_Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb*albedo*saturate(dot(lightDir, worldNormal));
UNITY_LIGHT_ATTENUATION(atten, i, worldPos);
return fixed4(ambient + diffuse * atten, col.a * _Cutoff);
}
ENDCG
}
}
//無(wú)陰影
//FallBack "Transparent/VertexLit"
//強(qiáng)制產(chǎn)生陰影
FallBack "VertexLit"
}
對(duì)于至今為止Shader學(xué)習(xí)內(nèi)容的一個(gè)總結(jié),算是一個(gè)比較綜合通用的shader了,因?yàn)槭锹瓷渌詴簳r(shí)沒(méi)有計(jì)算高光部分,之后再出一個(gè)帶高光版本的。
備注都有比較詳細(xì)的說(shuō)明,基本思路是利用多個(gè)Pass分別進(jìn)行正反面的渲染,再結(jié)合前向渲染的分光照渲染來(lái)實(shí)現(xiàn)。
最后擺出效果圖w~
總結(jié)
以上是生活随笔為你收集整理的Unity 通用透明物体漫反射Shader(双面渲染&多光源&光照衰减&法线贴图&凹凸透明度控制)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 置顶带滚动效果_前端面试:如何实现轮播图
- 下一篇: lol台服账号注册(艾欧尼亚VS诺克萨斯