如何制作適配全屏的Quad圖形?
2023-03-25 13:50 作者:CarelessWP | 我要投稿
在Unity中,Quad是一個能夠跟隨攝像機鏡頭旋轉(zhuǎn)的長方形面片,有的時候項目要求將Quad面片適配屏幕,那要如何實現(xiàn)呢?
我的實現(xiàn)思路很簡單:通過采樣屏幕空間的UV坐標(biāo)來實現(xiàn)。
大致的思路步驟如下:
1、獲取的攝像機的裁剪空間坐標(biāo);
2、通過透視剔除法,將裁剪空間坐標(biāo)轉(zhuǎn)化為屏幕空間坐標(biāo);
3、添加2D紋理貼圖,對屏幕空間的uv坐標(biāo)進行采樣;
首先,添加一個Quad面片,然后給面片增加增加一個surface unlit 的shader,自定義材質(zhì),材質(zhì)也選擇這個shader。
最關(guān)鍵的兩個步驟
第一、在頂點shader的函數(shù)中,使用變量screen_pos 接收裁剪空間頂點坐標(biāo)。
v2f?vert?(appdata?v) ????????????{ ????????????????v2f?o; ????????????????//?裁剪空間下的頂點坐標(biāo) ????????????????o.pos?=?UnityObjectToClipPos(v.vertex); ????????????????o.uv?=?v.textCoord; ????????????????o.screen_pos?=?o.pos; ????????????????o.screen_pos.y?=?-?o.screen_pos.y; ????????????????return?o; ????????????}
第二歩、在片元shader函數(shù)中,定義一個二維向量screen_uv,用裁剪空間頂點坐標(biāo)的x、y的值,分別除以寬度值,就能得到屏幕空間的uv坐標(biāo)。
但這個uv坐標(biāo)的范圍在[-1,1]之間,要將它轉(zhuǎn)換為[0,1]的范圍,因此加上1之后再乘以0.5,這樣就完成了空間范圍的轉(zhuǎn)化。
最后再使用text2D 方法,對screen_uv進行采樣。
half4?frag?(v2f?i)?:?SV_Target ????????????{ ????????????????//?透視除法,裁剪空間坐標(biāo)?/?屏幕寬度,得到屏幕uv?(-1,1) ????????????????half2?screen_uv?=?i.screen_pos.xy?/?i.screen_pos.w; ????????????????//?轉(zhuǎn)換范圍到(0,1) ????????????????screen_uv?=?(screen_uv?+?1.0)?*?0.5; ????????????????//?sample?the?texture ????????????????half4?col?=?tex2D(_MainTex,?screen_uv); ????????????????return?col; ????????????}
這樣就能得到Quad面片適配屏幕大小的效果。
來看最終效果:
附上完整shader代碼:
Shader?"Unlit/ScreenImage" { ????Properties ????{ ????????_MainTex?("Texture",?2D)?=?"white"?{} ????} ????SubShader ????{ ????????Tags?{?"RenderType"="Opaque"?} ????????LOD?100 ????????Pass ????????{ ????????????CGPROGRAM ????????????#pragma?vertex?vert ????????????#pragma?fragment?frag ????????????//?make?fog?work ????????????#pragma?multi_compile_fog ????????????#include?"UnityCG.cginc" ????????????struct?appdata ????????????{ ????????????????float4?vertex?:?POSITION; ????????????????float2?textCoord?:?TEXCOORD0; ????????????}; ????????????struct?v2f ????????????{ ????????????????float2?uv?:?TEXCOORD0; ????????????????float4?pos?:?SV_POSITION; ????????????????float4?screen_pos:?TEXCOORD1; ????????????}; ????????????sampler2D?_MainTex; ????????????float4?_MainTex_ST; ????????????v2f?vert?(appdata?v) ????????????{ ????????????????v2f?o; ????????????????//?裁剪空間下的頂點坐標(biāo) ????????????????o.pos?=?UnityObjectToClipPos(v.vertex); ????????????????o.uv?=?v.textCoord; ????????????????o.screen_pos?=?o.pos; ????????????????o.screen_pos.y?=?-?o.screen_pos.y; ????????????????return?o; ????????????} ????????????half4?frag?(v2f?i)?:?SV_Target ????????????{ ????????????????//?透視除法,裁剪空間坐標(biāo)?/?屏幕寬度,得到屏幕uv?(-1,1) ????????????????half2?screen_uv?=?i.screen_pos.xy?/?i.screen_pos.w; ????????????????//?轉(zhuǎn)換范圍到(0,1) ????????????????screen_uv?=?(screen_uv?+?1.0)?*?0.5; ????????????????//?sample?the?texture ????????????????half4?col?=?tex2D(_MainTex,?screen_uv); ????????????????return?col; ????????????} ????????????ENDCG ????????} ????} }