Unity 相机花式分屏

花式分屏,顾名思义,可以实现各种不规则几何边界的分屏,是无法直接通过调整相机视口能达到效果的(只能实现矩形的分屏),例如斜对角分屏,几何图形分屏:

 

假设我们有两个相机,需要上面的斜对角分屏画面,和镜子效果(假如我们想通过分屏的方式实现)。

方式1:两个相机分别添加两个RenderTexture,绘制在两张Image上,上层的Image可以通过遮罩实现剔除。

缺点:RenderTexture占内存高,遮罩也比较耗性能。

方式2:一个主相机渲染画面,一个辅助相机生成RenderTexture。实现一个shader,在Fragment Shader时,通过UV坐标区域判定(比如斜对角分割,分割线UV坐标必然是y =  x)选择性将辅助相机的像素替换主相机的像素。

Shader "Custom/Shader" {
    Properties{
        _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}//主相机的纹理
    _OtherTex("Other Tex", 2D) = "white" {}//辅助相机的纹理
    }
    SubShader{
        Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
        LOD 100

        Cull Off
        Blend Off//关闭混合
        Pass{
            CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"

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

            struct v2f {
                float4 vertex : SV_POSITION;
                half2 texcoord : TEXCOORD0;
            };

            sampler2D _MainTex;
            sampler2D _OtherTex;
            float4 _MainTex_ST;

            v2f vert(appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.texcoord)*ceil( i.texcoord.x - i.texcoord.y) + tex2D(_OtherTex, i.texcoord)*ceil( -i.texcoord.x + i.texcoord.y);
                return col;
            }
            ENDCG
        }
    }
        FallBack "Diffuse"
}

实例化自定义shader的材质球,给主相机添加OnRenderImage回调方法,传入辅助相机的纹理,并重新通过材质渲染:

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (cam)
        {
            if (cam.targetTexture == null)
            {
                cam.targetTexture = new RenderTexture(cam.pixelWidth, cam.pixelHeight, 0); //根据主相机的宽高创建一个同样宽高的纹理,记录辅助相机的图像
            }
            mat.SetTexture("_OtherTex", cam.targetTexture);//传入辅助相机的纹理
        }

        Graphics.Blit(src, dest, mat);
    }

  效果图:

缺点: 还是有一个RenderTexture。

方式3:添加一个主相机,一个副相机,主相机设置更高的深度。副相机的CullingMask去掉TransparentFX层。

然后添加自定义shader,不需要显示纹理,RenderQueue指定为BackGround,并添加对应的材质球。

Shader "Mask/SplitScreen" {
	//Simple depthmask shader 
	SubShader {
	    Tags {Queue = Background}
	    Pass {ColorMask 0}
	}
}

接下来在主相机下添加一个Plane,设置Layer为TransparentFx,指定刚才的材质球,调整合适位置和角度,就实现了特殊的分屏效果。

 

posted @ 2019-01-23 17:54  newShit  阅读(1141)  评论(0编辑  收藏