CommandBuffer使用 - 分屏

原理

先抓取整个屏幕画面到RenderTexture1上,然后把左边一半复制到RenderTexture2,右边一半复制到RenderTexture3

 

效果

 

c#代码

using UnityEngine;
using UnityEngine.Rendering;

[RequireComponent(typeof(Camera))]
public class SplitScreen : MonoBehaviour
{
    public RenderTexture m_SrcScreenRT;

    public RenderTexture m_SplitLeftRT;
    public RenderTexture m_SplitRightRT;

    public Shader m_Shader;
    public Material m_Material;
    private CommandBuffer m_Cmd;

    void OnEnable()
    {
        if (null == m_Cmd)
        {
            m_Cmd = new CommandBuffer();
            m_Cmd.name = "My Render Cmd";

            InitMaterial();

            //抓取当前屏幕
            var srcScreenRTId = new RenderTargetIdentifier(m_SrcScreenRT);
            m_Cmd.Blit(BuiltinRenderTextureType.CurrentActive, srcScreenRTId);

            //横向分成2个屏幕
            var splitLeftRTId = new RenderTargetIdentifier(m_SplitLeftRT);
            m_Cmd.SetGlobalFloat("offset", 0);
            m_Cmd.Blit(srcScreenRTId, splitLeftRTId, m_Material);

            var splitRightRTId = new RenderTargetIdentifier(m_SplitRightRT);
            m_Cmd.SetGlobalFloat("offset", 0.5f);
            m_Cmd.Blit(srcScreenRTId, splitRightRTId, m_Material);

        }
        GetComponent<Camera>().AddCommandBuffer(CameraEvent.AfterForwardAlpha, m_Cmd);
    }

    private void InitMaterial()
    {
        if (false == SystemInfo.supportsImageEffects)
        {
            Debug.LogWarning("This platform does not support image effects or render textures.");
            this.enabled = false;
            return;
        }

        if (null == m_Material)
        {
            if (null != m_Shader && m_Shader.isSupported)
            {
                m_Material = new Material(m_Shader);
                m_Material.hideFlags = HideFlags.DontSave;
            }
        }
        else if (null != m_Shader && m_Material.shader != m_Shader)
        {
            if (m_Shader.isSupported) //优先shader
            {
                m_Material = new Material(m_Shader);
                m_Material.hideFlags = HideFlags.DontSave;
            }
        }
    }

    void OnDisable()
    {
        GetComponent<Camera>().RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, m_Cmd);
    }

    void OnDestroy()
    {
        m_Cmd.Clear(); //清空所有渲染指令
        m_Cmd.Dispose();
        m_Cmd = null;
    }

}

 

shader

Shader "My/Cmd/Split2ScreenHorizontal"
{
	Properties
	{
		_MainTex("Base (RGB)", 2D) = "" {} //主贴图
	}

	CGINCLUDE

	#include "UnityCG.cginc"

	struct v2f //片元(段)着色器输入参数
	{
		float4 pos : POSITION; //裁剪空间坐标值
		float2 uv : TEXCOORD0; //贴图uv坐标
	};

	float offset; //外部参数
	sampler2D _MainTex;

	v2f vert(appdata_img v)
	{
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);
		o.uv = v.texcoord;
		o.uv.x = v.texcoord.x*0.5 + offset; //x方向将uv从[0, 1]缩放为[0, 0.5], 然后用offset参数在做调整

		return o;
	}

	half4 frag(v2f i) : COLOR
	{
		half4 color = tex2D(_MainTex, i.uv);
		return color;
	}

	ENDCG


	Subshader
	{
		Pass
		{
			ZTest Always //深度测试
			ZWrite Off //关闭写入深度buff
			Cull Off //剔除关闭
			Fog { Mode off } //内置雾效

			CGPROGRAM
			#pragma fragmentoption ARB_precision_hint_fastest
			#pragma vertex vert
			#pragma fragment frag
			ENDCG
		}
	}

	Fallback off
}

 

参考

Unity中使用CommondBuffer完成分屏功能_unity 分屏-CSDN博客

 

posted @ 2024-03-28 22:47  yanghui01  阅读(2)  评论(0编辑  收藏  举报