Unity中使用CommondBuffer完成分屏功能

本文地址:https://blog.csdn.net/t163361/article/details/112957147
最近准备申请新星创作者,需要2000个粉丝关注,觉得文章有用的,请点一下左侧边栏的关注,谢谢。

公司项目要求实现把一个屏幕的内容,分割后映射到另外4个屏幕上
最开始的想法是弄四个相机照射UI,然后把主相机的RenderTexture拿到后分割,再拼接成4副分割的画面
结果实现了后,发现直接对主UI相机,获取RenderTexture直接分割就可以用了
Unity早期的技术有两种获取相机RenderTexture的方式
1.相机直接设置到RenderTexture
2.相机上挂脚本使用OnPostRender,里面使用Graphics.Blit也可以获得
本文用的是Unity5推出的CommandBuffer功能,其实也不算啥新技术了,不过之前没用过
借这个机会使用了一次,还是很好用的,非常灵活

具体实现也没啥难度,不过感觉CommandBuff的教程还是少,经过这么多年也没几篇写的特别好的文章
下面是完成的截图
原始画面
在这里插入图片描述
分割后的画面
在这里插入图片描述
实现思路如下
1.默认分辨率是1920 * 1080
2.预先创建5个RenderTexture,第一个是1920 * 1080分辨率,其余4个是960 * 540
3.根据RenderTecture创建对应的RenderTargetIdentifier,这样才能在CommandBuffer中使用
4.使用CommandBuffer.Bilt函数选择一个合适的渲染时间,把当前渲染画面渲染到等大的RenderTexture中
5.然后开始分割图片,分割图片用的也是CommandBuffer的Bilt函数,分割需要一个shader,通过修改UV偏移,把画面分割

应该还有优化空间,比如能否不创建第一个等大的原始图,四个小图能否一个Bilt生成出来。没有验证,等后面机会在测试吧。

分割实现类

using System;
using UnityEngine;
using UnityEngine.Rendering;

public class UICameraSplite : MonoBehaviour
{
    private Camera _camera;

    public RenderTexture rt;
    
    public RenderTexture rt2;
    public RenderTexture rt3;
    public RenderTexture rt4;
    public RenderTexture rt5;

    public Material mt;
    // Start is called before the first frame update
    void Start()
    {
        _camera = GetComponent<Camera>();
        
        CommandBuffer buf = null;
        buf = new CommandBuffer();
        
        RenderTargetIdentifier id = new RenderTargetIdentifier(rt);
        
        buf.Blit(BuiltinRenderTextureType.CurrentActive, id);
        
        RenderTexture[]          rts   = new[] {rt2, rt3, rt4, rt5};
        RenderTargetIdentifier[] mrtID = new RenderTargetIdentifier[rts.Length];
       
        mrtID[0] = new RenderTargetIdentifier(rts[0]);
        buf.SetGlobalVector("offsetUV", new Vector4(0, 0.5f, 0, 0));
        buf.Blit(id, mrtID[0], mt);
        
        mrtID[1] = new RenderTargetIdentifier(rts[1]);
        buf.SetGlobalVector("offsetUV", new Vector4(0, 0, 0, 0));
        buf.Blit(id, mrtID[1], mt);
        
        mrtID[2] = new RenderTargetIdentifier(rts[2]);
        buf.SetGlobalVector("offsetUV", new Vector4(0.5f, 0f, 0, 0));
        buf.Blit(id, mrtID[2], mt);
        
        mrtID[3] = new RenderTargetIdentifier(rts[3]);
        buf.SetGlobalVector("offsetUV", new Vector4(0.5f, 0.5f, 0, 0));
        buf.Blit(id, mrtID[3], mt);
        

        _camera.AddCommandBuffer(CameraEvent.AfterHaloAndLensFlares, buf);
    }

    private void OnPostRender()
    {
        throw new NotImplementedException();
    }
}

对应的shader

Shader "Image/CopyHalfRT"
{
	Properties {
		_MainTex ("Base (RGB)", 2D) = "" {}
	}

	CGINCLUDE
	
	#include "UnityCG.cginc"
	
	struct v2f {
		float4 pos : POSITION;
		float2 uv : TEXCOORD0;
	};
	
	float4 offsetUV;
	
	sampler2D _MainTex;
	
	v2f vert (appdata_img v) {
		v2f o;
		o.pos = UnityObjectToClipPos(v.vertex);

		o.uv.xy = v.texcoord.xy*0.5 + offsetUV.xy;

		return o;
	}
	
	half4 frag (v2f i) : COLOR {

		half4 color = tex2D (_MainTex, i.uv);
		
		return color;
	}

	ENDCG
	
Subshader {
 Pass {
	  ZTest Always Cull Off ZWrite Off
	  Fog { Mode off }

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

Fallback off


} // shader

具体实现的工程可以点击链接查看

制作过程中遇到两个问题
1.屏幕翻转问题
测试的时候没问题,项目中用的时候发现第一次转化的画面是反的,具体原因看这个链接
解决画面翻转问题
2.半透颜色对不上问题
分割后的小图片,在主UI是半透的部分,颜色对不上,不确定原因,怀疑和线性转换有关系,不过也没尝试去解决
通过修改相机的Background颜色来缓解一下

uiCamera.backgroundColor = new Color32(80, 80, 80, 255);
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值