1. 概述
在文章《Unity3D學習筆記11——後處理》中論述了後處理是幀緩存(Framebuffer)技術實現之一;而另外一個幀緩存技術實現就是渲染紋理了。通常來說,我們渲染的場景會直接顯示到屏幕的顏色緩衝區,但其實紋理和屏幕一樣都是二維的,通過把場景渲染到紋理,可以實現很多特別的三維應用場景。三維渲染引擎中,通常給相機封裝一個渲染目標(Render Target)的接口,如果不設置,就渲染到屏幕;如果將其設置成一個紋理對象,就渲染到紋理。
2. 詳論
一個渲染紋理的例子是鏡面效果。鏡面效果的原理是,在正常渲染場景之外,額外再離屏渲染一張紋理圖,渲染的內容是鏡面面前的場景;然後,將這個渲染紋理傳遞到鏡面物體上,左右顛倒繪製出來。
案例非常簡單,甚至不需要腳本。首先我們創建一個quad網格作爲鏡面,並且在鏡面前放置一些三維物體:
然後創建一張渲染紋理:
接着在場景中創建渲染到紋理的相機。將相機的渲染目標設置成剛剛創建的渲染紋理,同時也應該調整相機的位置和旋轉,使其於觀察方向相反:
修改鏡面物體上的材質,使其調用的Shader爲:
Shader "Custom/Mirrior"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.uv.x = 1 - o.uv.x;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
Shader的內容非常簡單,給Shader傳入渲染紋理,給橫向的紋理座標取反,最後得到一個左右顛倒的效果圖:
3. 問題
大部分介紹渲染紋理的文章,基本上都是這個案例。但是我覺得這個只是略具意思而已。
- 單從案例本身來說,渲染紋理需要相機的支持,但相機的位置和旋轉影像最終鏡面的效果。當然我們可以根據實際的效果來調整,但最好根據鏡面的成像原理算出合理的參數。
- 渲染紋理實際上是通過相機把場景又給渲染了一遍。渲染批次加倍,所以渲染紋理往往是比較耗費性能的。有時需要控制一些物體進入鏡面,一些物體不用進入,那麼就要用到Unity的Layer(圖層)設置了。