屏幕圖像捕捉:
- 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; }