• UnityShader之屏幕特效基础


    1、什么是屏幕特效

    我们这里讲的屏幕特效技术,指的是在渲染完整个场景后得到的屏幕图象的基础上,再对这个屏幕图像做一系列处理,实现出屏幕特效,使用这种技术可以为屏幕画面增添各种风格的艺术效果,比如泛光、景深、模糊等等。
     

    2、unity实现屏幕特效的原理

    如上所述,要实现屏幕特效,首先要抓取渲染完整个场景得到的屏幕图像,在unity中,提供了OnRenderImage函数,方便我们进行这样的操作。它的声明如下:MonoBehaviour.OnRenderImage(RenderTexture src,RenderTexture dest);unity会把当前渲染得到的图像存储在第一个参数对应的渲染纹理中,通过自定义的一系列操作后,得到目标渲染纹理(第二个参数中的渲染纹理),目标渲染纹理会最终显示在屏幕上。在OnRenderImage函数中,使用Graphics.Blit函数来对渲染纹理进行处理。这里我们做一个可以改变画面亮度、饱和度、以及对比度的简单屏幕特效。
     

    3、C#脚本实现

    ////////////////////////////////////////////////////////////////////
    //                          _ooOoo_                               //
    //                         o8888888o                              //
    //                         88" . "88                              //
    //                         (| ^_^ |)                              //
    //                         O  =  /O                              //
    //                      ____/`---'\____                           //
    //                    .'  \|     |//  `.                         //
    //                   /  \|||  :  |||//                          //
    //                  /  _||||| -:- |||||-                         //
    //                  |   | \  -  /// |   |                       //
    //                  | \_|  ''---/''  |   |                       //
    //                    .-\__  `-`  ___/-. /                       //
    //                ___`. .'  /--.--  `. . ___                     //
    //              ."" '<  `.___\_<|>_/___.'  >'"".                  //
    //            | | :  `- \`.;` _ /`;.`/ - ` : | |                 //
    //               `-.   \_ __ /__ _/   .-` /  /                 //
    //      ========`-.____`-.___\_____/___.-`____.-'========         //
    //                           `=---='                              //
    //      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
    //                 佛祖保佑          永无BUG                      //
    ////////////////////////////////////////////////////////////////////
    
    
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    [ExecuteInEditMode]
    [RequireComponent(typeof(Camera))]
    public class ScreenEffect : MonoBehaviour {
    
        public Shader effectShader;  
        private Material effectMaterial;
        public Material EffectMaterial
        {
            get
            {
                effectMaterial = CreateMaterial(effectShader, effectMaterial);
                return effectMaterial;
            }
        }
    
        [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;    //对比度
    
    
        void OnRenderImage(RenderTexture src, RenderTexture dest)
        {
            if (EffectMaterial != null)
            {
                EffectMaterial.SetFloat("_Brightness", brightness);
                EffectMaterial.SetFloat("_Saturation", saturation);
                EffectMaterial.SetFloat("_Contrast", contrast);
                //对渲染纹理进行处理
                Graphics.Blit(src, dest, EffectMaterial);
            }
            else
            {
                Graphics.Blit(src, dest);
            }
        }
    
        private void Start()
        {
            bool isSupported = CheckSupport();
    
            if (isSupported == false)
            {
                this.enabled = false;
            }
        }
    
       
        // 检测当前平台是否支持屏幕特效
        private bool CheckSupport()
        {
            if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false)
            {
                Debug.LogWarning("当前平台不支持!");
                return false;
            }
            return true;
        }
    
        
        // 创建材质
        private Material CreateMaterial(Shader shader, Material material)
        {
            if (shader == null)
            {
                return null;
            }
    
            if (shader.isSupported && material && material.shader == shader)
                return material;
    
            if (!shader.isSupported)
            {
                return null;
            }
            else
            {
                material = new Material(shader);
                material.hideFlags = HideFlags.DontSave;
                if (material)
                    return material;
                else
                    return null;
            }
        }
    }

    4、Shader实现

    Shader "yzpShader/ScreenEffect" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}  //需要处理的渲染纹理
            _Brightness ("Brightness", Float) = 1     //亮度
            _Saturation("Saturation", Float) = 1      //饱和度
            _Contrast("Contrast", Float) = 1          //对比度
        }
        SubShader {
            Pass {  
                ZTest Always Cull Off ZWrite Off
                
                CGPROGRAM  
                #pragma vertex vert  
                #pragma fragment frag  
                  
                #include "UnityCG.cginc"  
                  
                sampler2D _MainTex;  
                half _Brightness;
                half _Saturation;
                half _Contrast;
                  
                struct v2f {
                    float4 pos : SV_POSITION;
                    half2 uv: TEXCOORD0;
                };
                  
                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 finalColor = renderTex.rgb * _Brightness;
                    
                    // 计算饱和度改变后的颜色
                    fixed luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
                    fixed3 luminanceColor = fixed3(luminance, luminance, luminance);
                    finalColor = lerp(luminanceColor, finalColor, _Saturation);
                    
                    // 计算对比度改变后的颜色
                    fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
                    finalColor = lerp(avgColor, finalColor, _Contrast);
                    
                    return fixed4(finalColor, renderTex.a);  
                }  
                  
                ENDCG
            }  
        }
        
        Fallback Off
    }

    5、测试结果

    首先将C#脚本挂在场景相机上,并将上面写好的shader拖拽到ScreenEffect脚本的effectShader上,修改该脚本的brightness、saturation、contrast值,可以得出下面这样的效果:

  • 相关阅读:
    NIO编程介绍
    伪异步IO
    BIO模型
    Json
    Jquery笔记
    JQuery与Ajax
    jQuery之事件和动画
    JQueryDOM节点操作
    认识Jquery
    javascript之DOM
  • 原文地址:https://www.cnblogs.com/IAMTOM/p/10072794.html
Copyright © 2020-2023  润新知