中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么利用Stencil來優化局部后處理特效

發布時間:2022-01-05 09:38:00 來源:億速云 閱讀:432 作者:柒染 欄目:大數據

這篇文章將為大家詳細講解有關怎么利用Stencil來優化局部后處理特效,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

只是例子就不要再和我說什么十字片,廣告牌疊加了。這個效果的實現就是用純色在RT上重繪原模型給一次高斯模糊后疊回原圖。

怎么利用Stencil來優化局部后處理特效

加了Stencil后計算量下降了一半(為方便對比,我砍掉了后處理流程最后的原圖Blit流程和人物繪制部分,僅顯示了downsample和高斯模糊的量)

原理:

Stencil和ZTest就如同兩兄弟,非常相似,但前者卻常常被忽略。大家都知道,在擁有Early-Z(準確的說是Early-ZS,也就是Z+Stencil)機制的當代GPU里,我們可以通過由前向后繪制,通過ZTest讓被遮擋的物體免于繪制,這是一個最基本的fillrate優化手段。

Stencil本身是一個比較+改寫特定Buff的技術,和ZTest的比較深度+改寫深度其實是一樣的機制,只是擁有更多的變化。所以它也可以通過先改寫Buff,然后讓后面的物體在讀取這個Buff的時候檢測不通過,從而直接跳過像素計算階段。

局部物體使用后處理特效很不合算,就是因為即使只有局部需要計算,GPU也必須計算整個屏幕。如果先用Stencil在屏幕上繪制一個標記區域,就可以將后面的計算限定在小范圍內。

怎么利用Stencil來優化局部后處理特效

用的是一個簡單的法線延伸OutLine,擴大了棒子的體積。并在繪制過的地方標記Stencil為1

Pass
{
	CULL OFF
	ZTest OFF
	COLORMASK 0

	Stencil
	{
		Ref 1
		Comp NotEqual
		Pass Replace
		ReadMask 1
		WriteMask 1
	}

	CGPROGRAM
	#pragma vertex vert
	#pragma fragment frag
			
	#include "UnityCG.cginc"
	struct appdata
	{
		float4 vertex : POSITION;
		float3 normal : NORMAL;
	};

	struct v2f
	{
		float4 vertex : SV_POSITION;
	};

	float _Outline;

	v2f vert (appdata v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);

		float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);  
		float2 offset = TransformViewToProjection(norm.xy);  
		o.vertex.xy += normalize(offset) * o.vertex.z * _Outline;  

		UNITY_TRANSFER_FOG(o,o.vertex);
		return o;
	}

	fixed4 frag (v2f i) : SV_Target
	{
		return 1;
	}

	ENDCG
}

然后再在之后的后處理流程里,給需要的Pass加上

Stencil
{
	Ref 1
	Comp Equal
	Pass Keep
	ReadMask 1
	WriteMask 1
}

即可。

不過……

1. Stencil只能通過繪制實體來寫入,不能在多張Buff間復制。所以一旦經過downsample就會丟失,而downsample是后處理中非常常見的。

2. 由于這個原因,RT繪制的順序也非常重要,只有作為繪制目標的RT才有獲得Stencil檢測的機會。

3.Stencil在其他RT中的利用,只能通過Graphics.SetRenderTarget(source.colorBuffer, stencil.depthBuffer)來完成,指向一張RT的顏色Buffer,卻同時指向另一張RT的depthBuff,且這兩張RT的分辨率必須完全一樣。

具體代碼(普通的Blit是沒法用的,會強制切換RenderTarget):

private void DepthBlit(RenderTexture source, RenderTexture destination, Material mat, int pass, RenderTexture depth)
{
            if (depth == null)
            {
                Graphics.Blit(source, destination, mat, pass);
                return;
            }
            Graphics.SetRenderTarget(destination.colorBuffer, depth.depthBuffer);
            GL.PushMatrix();
            GL.LoadOrtho();
            mat.mainTexture = source;
            mat.SetPass(pass);
            GL.Begin(GL.QUADS);
            GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.1f);
            GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(1.0f, 1.0f, 0.1f);
            GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(1.0f, 0.0f, 0.1f);
            GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(0.0f, 0.0f, 0.1f);
            GL.End();
            GL.PopMatrix();
}

紋理大小限制是最麻煩的,其它都還好。實際用法就是,保留保存著Stencil的那張RT,然后在需要的時候掛接在目標RT上。

繪制標記是有代價的,但也可以在繪制正常畫面時順帶繪制,這樣代價就小很多。

在可以用到的時候記得使用即可。

好吧,我知道你們可能會問Bloom本身具體是怎么做的。Bloom本身Unity內置后處理有一個,但是是全屏的。想做到局部,確實只能單開一張RT來繪制要泛光的物體。

但這就涉及到保留深度緩沖的問題,否則那個物體就必須顯示在最前面而無法被障礙物遮擋。因為同時還要切換RT繪制,唯一的辦法就是剛才的Graphics.SetRenderTarget(source.colorBuffer, stencil.depthBuffer),繪制新RT,同時使用以前的深度緩沖區。

我為了圖簡單,是直接在后處理階段里切換RenderTarget,然后用Graphics.DrawMeshNow來繪制要泛光的物體的,這會導致Mesh無法Batch。想要Batch,必須讓攝像機來繪制這些物體,應該是必須用到CommandBuffer這些東西。

關于怎么利用Stencil來優化局部后處理特效就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

廊坊市| 漯河市| 白城市| 山丹县| 南溪县| 监利县| 镇沅| 华容县| 库尔勒市| 建始县| 柞水县| 高唐县| 昌乐县| 峨眉山市| 巨鹿县| 栖霞市| 盐亭县| 黑龙江省| 广汉市| 祁阳县| 虞城县| 武胜县| 寿宁县| 农安县| 孝义市| 海门市| 渝北区| 汕尾市| 沧州市| 定边县| 东阿县| 张掖市| 邵阳市| 伊金霍洛旗| 旺苍县| 湟源县| 西乌珠穆沁旗| 通道| 仙游县| 焦作市| 新蔡县|