做了一个单相机实现分屏混合的功能, 需求大概就是在同一视角下, 相机通过不同的CullingMask获取不同的渲染图片RenderTexture之后, 通过某种方式一起显示在界面的功能. 其实核心逻辑就是怎样用一个相机渲染不同的图片罢了, 直接上代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class BlendRenderTexture : MonoBehaviour
{
public enum BlendDirection
{
Horizontal = 0,
Vertical = 1
}
[SerializeField]
[Range(0, 1)]
public float blend = 0.5f;
[SerializeField]
public BlendDirection blendDirection = BlendDirection.Horizontal;
[SerializeField]
public LayerMask tagLayerMask;
[SerializeField]
public RenderingTools.BlendRenderTextureTarget blendRenderTextureTarget;
private bool m_grabbing = false;
private void OnEnable()
{
if(blendRenderTextureTarget == null)
{
blendRenderTextureTarget = new RenderingTools.BlendRenderTextureTarget("Unlit/BlendRenderTexture");
}
}
private void OnDisable()
{
if(blendRenderTextureTarget != null)
{
blendRenderTextureTarget.Release();
}
}
void OnRenderImage(RenderTexture src, RenderTexture dest)
{
if(m_grabbing)
{
m_grabbing = false;
Graphics.Blit(src, dest);
return;
}
if(blendRenderTextureTarget.renderTexture && blendRenderTextureTarget.material)
{
blendRenderTextureTarget.material.SetTexture("_Left", src);
blendRenderTextureTarget.material.SetTexture("_Right", blendRenderTextureTarget.renderTexture);
blendRenderTextureTarget.material.SetFloat("_Blend", Mathf.Clamp01(blend));
blendRenderTextureTarget.material.SetInt("_Direction", (int)blendDirection);
Graphics.Blit(src, dest, blendRenderTextureTarget.material);
}
else
{
Graphics.Blit(src, dest);
}
}
private void LateUpdate()
{
RenderTargetTexture();
}
public void RenderTargetTexture()
{
var material = blendRenderTextureTarget.GetMaterial();
if (m_grabbing = material)
{
var lastMask = Camera.main.cullingMask;
var lastTex = Camera.main.targetTexture;
Camera.main.cullingMask = tagLayerMask;
Camera.main.targetTexture = blendRenderTextureTarget.GetRenderTexture();
Camera.main.Render();
Camera.main.cullingMask = lastMask;
Camera.main.targetTexture = lastTex;
}
}
}
知识兔在LateUpdate中请求目标图片渲染, 标记了m_grabbing之后, 调用到OnRenderImage, 直接就把目标渲染图片输出到我们的临时RenderTexture上了, 然后再通过正常渲染时调用OnRenderImage之后, 就会通过Material进行混合了.
BlendRenderTextureTarget 只是一个资源的封装:
知识兔using System.Collections;using System.Collections.Generic;using UnityEngine;public static class RenderingTools{ [System.Serializable] public class BlendRenderTextureTarget { [SerializeField] public Material material = null; [SerializeField] public string shaderName = string.Empty; public RenderTexture renderTexture { get; set; } public BlendRenderTextureTarget(string shaderName) { this.shaderName = shaderName; } public Material GetMaterial() { if(material == false) { var shader = Shader.Find(shaderName); if(shader) { material = new Material(shader); material.hideFlags = HideFlags.DontSave; } } return material; } public RenderTexture GetRenderTexture() { if(renderTexture) { if(renderTexture.width != Screen.width || renderTexture.height != Screen.height) { RenderTexture.ReleaseTemporary(renderTexture); renderTexture = null; } } if(renderTexture == false) { renderTexture = RenderTexture.GetTemporary(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); renderTexture.hideFlags = HideFlags.DontSave; } return renderTexture; } public void Release() { if(renderTexture) { RenderTexture.ReleaseTemporary(renderTexture); renderTexture = null; } if(material) { material = null; } } }}