Unity – GrabPass 的重複使用

2020/03/31 – 修正一些語意不清楚的地方.


這是在使用 Unity 內建 Glass-Stained-BumpDistort 的這個 shader 時,多個物件使用時會讓 FPS 狂掉的問題。

推測是 grab pass 所造成的效能衝擊,本來嘗試先用一個空物件把 grab 的 texture 存下,之後用一般 texture 的方式傳給物件使用,來達成重複利用的方式。

結果最後沒搞定投影反轉的問題…幸好沒搞定(?)

繞了一大圈,回頭再看了一次官方文件,再看看 glass shader 後…

從原本的…

GrabPass {}

改為…

GrabPass  { "xxxxx"; }

一行 code 就搞定這一切惹!! 就一行!
※剛才特地開了一個新專案匯入,已經解掉了=3= (還是當初被我誤刪?)


順路翻譯:

ShaderLab syntax: GrabPass

語法 (Syntax)

GrabPass 是一個特殊的 passtype – 它會將該物件要在螢幕上被繪製區塊的資訊擷取到一張 texture 上。 這個 texture 可被隨後的 passes 使用於基於圖像的進階特效。

GrabPass 所屬於 subshader 裡面。它可以有兩種形式:

  • 僅寫 GrabPass { }就可把目前的螢幕資訊存入 texture 內。之後的 pass 可以透過 _GrabTexture 這個名稱來存取。注意:這個形式的 grab pass 會為每一個物件各執行一次這個高消耗的操作。
  • GrabPass { "TextureName" } 也同樣會把螢幕資訊存入 texture 內,但是每幀只有第一個使用到該名稱的物件會進行擷取。這是一個當你有多個物件會在場景中使用 grab pass 時的一個高效做法

另外,GrabPass 可以使用 NameTags 指令。

Example

這是一個高消耗的方式,來反轉之前被繪製顏色:

Shader "GrabPassInvert"
{
    SubShader
    {
        // Draw ourselves after all opaque geometry
        Tags { "Queue" = "Transparent" }

        // Grab the screen behind the object into _BackgroundTexture
        GrabPass
        {
            "_BackgroundTexture"
        }

        // Render the object with the texture generated above, and invert the colors
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 pos : SV_POSITION;
            };

            v2f vert(appdata_base v) {
                v2f o;
                // use UnityObjectToClipPos from UnityCG.cginc to calculate 
                // the clip-space of the vertex
                o.pos = UnityObjectToClipPos(v.vertex);
                // use ComputeGrabScreenPos function from UnityCG.cginc
                // to get the correct texture coordinate
                o.grabPos = ComputeGrabScreenPos(o.pos);
                return o;
            }

            sampler2D _BackgroundTexture;

            half4 frag(v2f i) : SV_Target
            {
                half4 bgcolor = tex2Dproj(_BackgroundTexture, i.grabPos);
                return 1 - bgcolor;
            }
            ENDCG
        }

    }
}

這個 shader 有兩個 passes:第一個 pass 會擷取任何在繪製時位在物件後方的東西,然後將之帶進第二個 pass 套用效果。當然,這可以使用 blend mode 這樣低消耗的方式來達成同樣的效果。

其他參考

Page last updated: 2012-07-10

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google photo

您的留言將使用 Google 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.