zoukankan      html  css  js  c++  java
  • 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值,可以得出下面这样的效果:

  • 相关阅读:
    我的WCF之旅(1):创建一个简单的WCF程序
    与众不同 windows phone (15) Media(媒体)之后台播放音频
    与众不同 windows phone (14) Media(媒体)之音频播放器, 视频播放器, 与 Windows Phone 的音乐和视频中心集成
    与众不同 windows phone (10) Push Notification(推送通知)之推送 Tile 通知, 推送自定义信息
    与众不同 windows phone (17) Graphic and Animation(画图和动画)
    与众不同 windows phone (5) Chooser(选择器)
    与众不同 windows phone (26) Contacts and Calendar(联系人和日历)
    与众不同 windows phone (7) Local Database(本地数据库)
    与众不同 windows phone (19) Device(设备)之陀螺仪传感器, Motion API
    与众不同 windows phone (16) Media(媒体)之编辑图片, 保存图片到相册, 与图片的上下文菜单“应用程序...”和“共享...”关联, 与 Windows Phone 的图片中心集成
  • 原文地址:https://www.cnblogs.com/IAMTOM/p/10072794.html
Copyright © 2011-2022 走看看