做了一個單相機實作分屏混合的功能, 需求大概就是在同一視角下, 相機通過不同的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; } } } }
混用用到的Shader也很簡單:
Shader "Unlit/BlendRenderTexture" { Properties { _MainTex("Texture", 2D) = "white" {} _Left("Texture", 2D) = "white" {} _Right("Texture", 2D) = "white" {} _Blend("Blend", Range(0,1)) = 0.5 [Enum(Horizontal,0,Vertical,1)] _Direction("Blend Direction", Float) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; sampler2D _Left; sampler2D _Right; float _Blend; float _Direction; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = 1; // sample the texture bool blend_left = (_Direction == 0) ? (i.uv.x <= _Blend) : (i.uv.y <= _Blend); if (blend_left) { col = tex2D(_Left, i.uv); } else { col = tex2D(_Right, i.uv); } // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } }
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/17924.html
標籤:其他
