Unity中的半透明阴影
Unity中的半透明陰影
在Unity中渲染半透明陰影可以使用Unity提供的dither texture。在這之前,先考慮一般半透明物體的渲染流程:
- 設置render queue為Transparent,這樣不透明的物體會先渲染,然后位于被不透明物體遮擋的透明物體就可以不必渲染,減少開銷
- 設置render type為Transparent,便于一些replacement操作
- 設置blend mode,例如fade是srcBlend = SrcAlpha,dstBlend = OneMinusSrcAlpha,而Transparent是srcBlend = One,dstBlend = OneMinusSrcAlpha
- 關閉深度寫入,zwrite = false
Unity中的半透明陰影本質上是不透明的,只是對dither texture進行采樣,根據采樣的結果,clip掉一些fragment,使得shadow caster過程中只有一部分陰影信息會被繪制到shadowmap上。Unity builtin shaders提供的參考寫法如下:
struct Interpolators {UNITY_VPOS_TYPE vpos : VPOS;... };float4 MyShadowFragmentProgram (Interpolators i) : SV_TARGET {...half alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25,alpha*0.9375)).a;clip(dither - 0.01);... }vpos表示的是當前像素在screen space下的坐標,_DitherMaskLOD是一個尺寸為4×4×16的3D紋理,這個可以從frame debug中看出:
這個紋理長啥樣呢?我們可以寫一個shader手動把它輸出:
Shader "Custom/TextureViewShader" {Properties{}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;};sampler3D _DitherMaskLOD;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{// sample the texturei.uv *= 16;fixed4 col = tex3D(_DitherMaskLOD, float3(i.uv, floor(i.uv.x) * 0.0625)).a;return col;}ENDCG}} }從frame debug可知紋理是alpha8格式,因而只需輸出alpha通道值:
由于_DitherMaskLOD紋理是4×4×16的,我們實際上在v方向也重復了16次,因此真正的紋理長這樣:
可以看出,該紋理從4×4的全黑像素開始,隨著維度z的增加,黑色像素每次減少1個,直至最后全部變成4×4的全白像素。通過這個規律,不難理解前面代碼tex3D的采樣坐標z的寫法為alpha*0.9375。alpha表示透明度,0為完全透明1為完全不透明,而0.9375實際上就是15/16。這就是說在0的情況下采樣的3D紋理是純黑像素,會被clip掉,不會產生陰影;而1的情況下采樣的3D紋理是全白像素,會完全產生陰影,就仿佛跟不透明物體一樣。
最后再看一下這個vpos*0.25是干啥的。vpos表示的是pixel在screen space下的坐標,x和y取值范圍類似[0, screenWidth],[0, screenHeight]。乘以0.25的系數就是對取值范圍進行縮放處理,換言之就是將_DitherMaskLOD紋理進行放大,使其更明顯??梢钥聪虏煌s放比例的效果對比:
最后提一點的是,由于半透明的物體,render queue設置為transparent,所以在平行光繪制陰影前的depth pass階段,是不會把半透明物體的深度信息寫入depth buffer的,不過在shadow caster階段,半透明陰影的信息還是正常繪制到shadowmap中的。這些都可以從frame debug中看出來:
如果你覺得我的文章有幫助,歡迎關注我的微信公眾號(大齡社畜的游戲開發之路)-
總結
以上是生活随笔為你收集整理的Unity中的半透明阴影的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信内部浏览器打开网页时提示外部浏览器打
- 下一篇: 科技进步计算机开机速度,笔者教你电脑开机