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,指定刚才的材质球,调整合适位置和角度,就实现了特殊的分屏效果。