CommandBuffer

应用一、 屏幕截图

CommandBuffer buf = new CommandBuffer();
buf.name = "Grab Screen Texture";

// 名称任意起
screenCopyID = Shader.PropertyToID("_ScreenCopyTexture");

// 创建临时 RT。
// 像素宽度,或为 -1,表示“摄像机像素宽度”。
// 像素高度,或为 -1,表示“摄像机像素高度”。
buf.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear);

// 复制当前屏幕到 RT
buf.Blit(BuiltinRenderTextureType.CurrentActive, screenCopyID);

// 如何使用这个 rt, 这里测试,赋值给Shader 贴图。
//buf.SetGlobalTexture("_CustomMainTex", screenCopyID);

m_camera.AddCommandBuffer(_cameraEvent, buf);

接下来使用 RawImage 作为输出实验。

Shader 1

Shader "Unlit/GrabScreenTexture"
{
    SubShader
    {
        Tags { "RenderType"="Overlay" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uvgrab : TEXCOORD0;
            };

            struct v2f
            {
                float2 uvgrab : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            // 1. 作为普通图使用
            sampler2D _CustomMainTex;
            float4 _CustomMainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                //o.uvgrab = TRANSFORM_TEX(v.uvgrab, _CustomMainTex);
                o.uvgrab = v.uvgrab.xy *  _CustomMainTex_ST.xy + _CustomMainTex_ST.zw;
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_CustomMainTex, i.uvgrab);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

作为普通图使用,这样出来的效果: 1. 图像为全屏图 2. Dx和 OpenGL 坐标没有适应, 导致颠倒图。

Shader 2

Shader "Unlit/GrabScreenTextureFinal"
{
    // 调试作用
    Properties{
        _Color("Color", Color) = (1, 1, 1, 1)
        _OffetX("OffetX", Range(-0.5, 0.5)) = 0
    }

    SubShader
    {
        Tags { "RenderType" = "Overlay" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 texcoord: TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 uvgrab : TEXCOORD0;
                UNITY_FOG_COORDS(1)
            };

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

                //1。 OpenGL /DX 坐标适应
#if UNITY_UV_STARTS_AT_TOP
                float scale = -1.0;
#else
                float scale = 1.0;
#endif
                //2. 齐次坐标 转换为 屏幕坐标
                // 齐次坐标,原点在中间, (-w, w)
                // 屏幕坐标, 原点左下角(统一OpenGL系)
                o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
                o.uvgrab.zw = o.vertex.zw;

                // 添加调试  _OffetX
                o.uvgrab.x = o.uvgrab.x+ _OffetX;
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            sampler2D _CustomMainTex;
            float4 _CustomMainTex_TexelSize;
            half4 _Color;
            fixed4 frag(v2f i) : SV_Target
            {

                // 屏幕比例, 转换为图像比例, 把这个比例作为 uv采样。
                i.uvgrab.xy = _CustomMainTex_TexelSize.xy * i.uvgrab.z + i.uvgrab.xy;

                // sample the texture
                // 添加调试  _Color
                half4 col = tex2Dproj(_CustomMainTex, UNITY_PROJ_COORD(i.uvgrab)) * _Color;
                UNITY_APPLY_FOG(i.fogCoord, col);
                col.a = 1.0;
                return col;
            }
            ENDCG
        }
    }
}

修正后: 1. 图像为渲染物体区域图 2. Dx和 OpenGL 坐标适应。

从效果上看到和没有渲染一样,那是因为一模一样的完全重合。 调整 OffsetX 和Color 就能看到了。

关于坐标徐转换


文章作者: Yonggang Long
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Yonggang Long !
 上一篇
2022-08-10 Yonggang Long
下一篇 
2022-08-10 Yonggang Long
  目录