比如如下效果:
代碼不是很多,使用的函數包括ZTest,ZWrite,Blend等,看起來都是些內置參數,但是很多人不一定了解其意義和原理。
光柵化階段的後期,會有一個深度測試和顏色混合的過程,此效果就是針對這個過程進行的一種特殊處理。
問題1:什麼是深度?
深度就是該像素點在3D世界中距離攝像機的距離,離攝像機越近,深度值越小。
問題2:什麼是深度測試?
首先要有【深度緩存】這個名詞的概念,想象屏幕上每一個點,都存放在一個緩存列表中。如果啓用深度緩存【ZWrite On】,那麼在繪製每個像素前,底層會將當前點的深度值和已經存儲在這個位置的點的深度值進行比較。如果新點的深度值小於原來點的深度值,則新的點會代替原來的點。反之新的點會被遮擋,其顏色值和深度值會被丟棄。
知道了上面的兩個答案後,我們就可以分析,怎樣實現遮擋顯示的效果?
1.定義2個pass,一個輸出純色,一個輸出模型色
2.當對象沒有被擋住時,先執行的純色pass輸出了純色,然後模型的pass輸出了模型色,最終純色被替換顯示正常模型。
3.當對象被牆壁擋住時,如果我們什麼也不做,純色pass輸出的顏色和模型pass輸出的顏色都會被牆壁代替【因爲它們的深度值都比牆壁深度值大】。
4.當對象被牆壁擋住時,我們想要的效果是顯示純色,那麼我們可以關閉純色的【ZWrite】,就是不將它的深度值寫入【深度緩存】,此時它的深度測試參數ZTest默認是LEqual,而它的深度值是大於牆壁(存於當前深度緩存)的,所以也不會顯示。
這時設置ZTest爲GEqual,就是說此pass的輸出的顏色深度值大於當前的屏幕的深度值就會顯示,顯然純色深度值是大於牆壁色深度值的,所以最終顯示了純色。
5.被牆壁擋住時,模型色已經被剔除了,最終的顏色混合爲
Blend SrcAlpha OneMinusSrcAlpha
最終色 = 純色rgb * 純色a + 牆壁rgb * (1-純色a)
代碼如下:
- Shader "Custom/XRay"
- {
- Properties
- {
- _Color("Color", Color) = (1,1,1,1)
- _MainTex("Albedo", 2D) = "white" {}
- _AfterColor ("After Color", Color) = (0.435, 0.851, 1, 0.419)
- }
- SubShader
- {
- Tags { "Queue" = "Geometry+1" "RenderType"="Opaque" }
- LOD 300
- Blend SrcAlpha OneMinusSrcAlpha // 源RGB*源A + 背景RGB*1-源A
- // 1.沒有被牆擋住時,先執行純色的pass,然後執行模型的pass,純色會被模型顏色替換
- // 2.1被牆擋住時,模型pass因爲開啓[ZWrite],[ZTest]爲默認的LEqual,因爲牆的Z值更小,模型顏色被牆替換
- // 2.2而純色沒有寫入【深度緩存】,【ZTest】爲GEqual,而純色是在牆後面,Z值大於牆,所以顯示
- // 3.此時再融合,純色RGB*純色A + 牆RGB*(1-純色A)
- pass
- {
- // 深度測試的Pass
- ZTest GEqual // 深度測試 大於等於當前最小【深度緩存】中的值時,就會顯示
- ZWrite Off // 不寫入到【深度緩存】
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- float4 _AfterColor;
- struct appdata
- {
- float4 vertex : POSITION;
- };
- struct v2f
- {
- float4 pos : POSITION;
- };
- v2f vert (appdata v)
- {
- v2f o;
- o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
- return o;
- }
- float4 frag (v2f i) : COLOR
- {
- return _AfterColor;
- }
- ENDCG
- }
- pass
- {
- //深度測試默認值,即當前的Z值小於等於【深度緩存】中的值,則顯示當前Z
- //沒有被牆擋住時它的Z值最小即正常顯示,被牆擋住時,牆的Z值更小
- ZTest LEqual
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- sampler2D _MainTex;
- float4 _MainTex_ST;
- struct appdata
- {
- float4 vertex : POSITION;
- float4 texcoord : TEXCOORD0;
- };
- struct v2f
- {
- float4 pos : POSITION;
- float4 uv : TEXCOORD0;
- };
- v2f vert (appdata v)
- {
- v2f o;
- o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
- o.uv = v.texcoord;
- return o;
- }
- float4 frag (v2f i) : COLOR
- {
- float4 texCol = tex2D(_MainTex, i.uv);
- return texCol;
- }
- ENDCG
- }
- }
- }
原文:http://blog.sina.com.cn/s/blog_89d90b7c0102vvd9.html