zoukankan      html  css  js  c++  java
  • 单相机做分屏混合

      做了一个单相机实现分屏混合的功能, 需求大概就是在同一视角下, 相机通过不同的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
            }
        }
    }

      

  • 相关阅读:
    python接口测试(二)——配置文件的使用
    python接口测试(一)——http请求及token获取
    jmeter接口测试--响应结果Unicode转码成中文
    jmeter接口测试--获取token
    jmeter接口测试--参数化
    Sysbench安装步骤及详情
    云数据库安装及使用
    npm start 和 npm run start的关系
    使用JS控制伪元素的几种方法
    html5新属性
  • 原文地址:https://www.cnblogs.com/tiancaiwrk/p/11611578.html
Copyright © 2011-2022 走看看