美文网首页
【Unity Shader入门精要学习】高级(一)

【Unity Shader入门精要学习】高级(一)

作者: 小王子称号发放NPC | 来源:发表于2019-11-04 17:18 被阅读0次

    屏幕后处理效果

    屏幕后处理效果(screen post-processing effects),是游戏中实现屏幕特效的常见方法。屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,在对这个图像进行一系列操作,实现各种屏幕特效,如景深(Depth of Field),运动模糊(Motion Blur)。

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    

    因此,想要实现屏幕后处理的基础在于得到渲染后的屏幕图像,Unity提供了方便的接口——OnRenderImage(只在摄像机脚本中生效),在OnRenderImage函数中,经常使用Graphics.Blit函数来完成对渲染纹理的处理:

    public static void Blit(Texture source, RenderTexture dest);
    public static void Blit(Texture source, RenderTexture dest, Material mat, int pass = -1);
    public static void Blit(Texture source, Material mat, int pass = -1);
    public static void Blit(Texture source, RenderTexture dest, Vector2 scale, Vector2 offset);
    public static void Blit(Texture source, RenderTexture dest, int sourceDepthSlice, int destDepthSlice);
    public static void Blit(Texture source, Material mat, int pass, int destDepthSlice);
    public static void Blit(Texture source, RenderTexture dest, Vector2 scale, Vector2 offset, int sourceDepthSlice, int destDepthSlice);
    

    在默认情况下,OnRenderImage函数会在所有不透明和透明的Pass执行完毕后被调用,以便对场景中所有游戏对象都产生影响。但有时,我们希望在不透明的Pass(即渲染队列小于等于2500的Pass,内置的Background、Geometry和AlphaTest渲染队列均在此范围内)执行完毕后立即调用OnRenderImage,从而不对透明物体产生任何影响。此时可以在OnRenderImage函数前添加ImageEffectOpaque属性来实现这样的目的:

        [ImageEffectOpaque]
        private void OnRenderImage(RenderTexture src, RenderTexture dest)
    

    调整屏幕的亮度,饱和度,对比度

    调整前
    调整后

    摄像机脚本

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    [ExecuteInEditMode]
    [RequireComponent(typeof(Camera))]
    public class PostEffectsBase : MonoBehaviour
    {
        protected Material CheckShaderAndCreateMaterial(Shader shader, Material material)
        {
            if (shader == null || !shader.isSupported)
            {
                return null;
            }
    
            if (shader.isSupported && material && material.shader == shader)
            {
                return material;
            }
            
            material = new Material(shader);
            material.hideFlags = HideFlags.DontSave;
            if (material)
            {
                return material;
            }
            else
            {
                return null;
            }
        }
    }
    
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class BrightnessSaturationContrast : PostEffectsBase
    {
        public Shader briSatConShader;
    
        protected Material briSatConMaterial;
    
        public Material material
        {
            get
            {
                briSatConMaterial = CheckShaderAndCreateMaterial(briSatConShader, briSatConMaterial);
                return briSatConMaterial;
            }
        }
    
        [Range(0.0f, 3.0f)] public float brightness = 1.0f;
    
        [Range(0.0f, 3.0f)] public float saturation = 1.0f;
    
        [Range(0.0f, 3.0f)] public float contrast = 1.0f;
        
        [ImageEffectOpaque]
        private void OnRenderImage(RenderTexture src, RenderTexture dest)
        {
           // Debug.Log("BrightnessSaturationContrast OnRenderImage");
            if (material != null)
            {
                material.SetFloat("_Brightness",brightness);
                material.SetFloat("Saturation",saturation);
                material.SetFloat("_Contrast",contrast);
                
                Graphics.Blit(src,dest,material);
            }
            else
            {
                Graphics.Blit(src,dest);
            }
        }
    }
    

    对应Shader

    Shader "Unlit/BrightnessSaturationConstrat"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
            _Brightness("Brightness",float)=1
            _Saturation("Saturation",float)=1
            _Contrast("Contrast",float)=1
        }
        SubShader
        {
          //下面三项是屏幕后处理标配
            ZTest Always 
            Cull Off 
            ZWrite Off
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
    
                #include "UnityCG.cginc"
    
                struct v2f
                {
                    float4 pos: SV_POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
                float _Brightness;
                float _Saturation;
                float _Contrast;
    
                v2f vert (appdata_img v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv = v.texcoord;
                    return o;
                }
    
                fixed4 frag (v2f i) : SV_Target
                {
                    fixed4 renderTex = tex2D(_MainTex, i.uv);
    
                    fixed3 finalCol = renderTex.rgb * _Brightness;
    
                    fixed luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
                    fixed3 luminanceColor = fixed3(luminance, luminance, luminance);
                    finalCol = lerp(luminanceColor,finalCol,_Saturation);
    
                    fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
                    finalCol = lerp(avgColor, finalCol, _Contrast);
                    
                    return fixed4(finalCol, renderTex.a);  
                }
                ENDCG
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:【Unity Shader入门精要学习】高级(一)

          本文链接:https://www.haomeiwen.com/subject/tdjwvctx.html