扭曲效果 效率優化 GrapPass,CommandBuffer對比

屏幕圖像捕捉:

  • Shader的GrabPass
    GrabPass能夠很方便地捕獲當前渲染時刻的FrameBuffer中的圖像。
    其原理就是從當前FrameBuffer中copy一份紋理,經過SetTexture的方式設置紋理。
    至於GrabPass的性能問題,通常認爲是對FrameBuffer 進行的一些pixel copy operations形成的,
    具體Unity是怎麼實現的,不得而知。
    GrabPass { } 不帶參數的 默認名字爲 "_GrabTexture" 會在當時爲每一的使用的obj抓取一次
    GrabPass { "TextureName" } 每一個名字在 每幀,第一次使用時抓取一次
  • commandBuffer
    GrapPass在每幀至少捕獲一次,優化思路是能夠統一關閉,減小抓取次數
    基本思路是,獨立一個只繪製扭曲層的相機,在OnPreRender中檢查抓取cd,引用次數,扭曲開關等,
    用Graphics.ExecuteCommandBuffer(commandBuffer);的方式手動抓取

核心部分代碼函數

private void Awake()
{
    ... ...
    var cam = GetComponent<Camera>();
    rt = RenderTexture.GetTemporary(cam.pixelWidth, cam.pixelHeight, 16, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Default, 1);

    commandBuffer = new CommandBuffer();
    commandBuffer.name = "GrabScreenCommand";
    commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, rt);
}

void OnPreRender()
{
    if (UseCount <= 0 || Time.time < nextGrapTime)
      return;

     nextGrapTime = Time.time + grapCD;
     Graphics.ExecuteCommandBuffer(commandBuffer);
}

扭曲效果

主要使用兩個內置函數 https://www.jianshu.com/p/df878a386bec 性能

  • float4 ComputeScreenPos(float4 pos)

    將攝像機的齊次座標下的座標轉爲齊次座標系下的屏幕座標值,其範圍爲[0, w]
    值用做tex2Dproj指令的參數值,tex2Dproj會在對紋理採樣前除以w份量。
    固然你也能夠本身除以w份量後進行採樣,可是效率不如內置指令tex2Dproj優化

  • half4 tex2Dproj(sampler2D s, in half4 t) { return tex2D(s, t.xy / t.w); }

    扭曲使用貼圖計算UV偏移ui

核心部分:spa

v2f vert (input v) {
    v2f o;
    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    o.texcoord = v.texcoord;
    o.uvgrab = ComputeGrabScreenPos(o.vertex);
    return o;
}

fixed4 frag (v2f i) : COLOR {
    fixed2 norm = UnpackNormal(tex2D(_Distortion, i.texcoord)).rg;
    i.uvgrab.xy -= _Strength * norm.rg * _RaceDropTex_TexelSize.xy;
    fixed4 col = tex2Dproj(_RaceDropTex, i.uvgrab);
    return col;
}
相關文章
相關標籤/搜索