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