Unity Shaders——屏幕特效老电影效果(Old Movie Screen Effect)

来源:互联网 发布:淘宝美工多久能学会 编辑:程序博客网 时间:2024/04/30 10:03

本文参考《Unity Shaders and Effects CookBook》。


很多时候我们游戏需要带入不同的场景,比如老电影的那种效果



像这种效果我们怎么实现呢?


下面分析下结构图:




这也是这个效果的思路图,虚光照,尘土,划痕都是通过图片混合的,然后深褐色Shader直接处理,再让尘土和划痕的uv动起来,最终就能达到老电影的效果。


下面我们看下我们需要的三张图片:


虚光照:



灰尘:



划痕:



然后脚本跟前面的屏幕特效的模式类似,就是略微复杂些:


shader脚本:

Shader "MyShaders/OldFilmEffectShader" {Properties {_MainTex ("Base (RGB)", 2D) = "white" {}_VignetteTex ("Vignette Texture", 2D) = "white"{}_ScratchesTex ("Scartches Texture", 2D) = "white"{}_DustTex ("Dust Texture", 2D) = "white"{}_SepiaColor ("Sepia Color", Color) = (1,1,1,1)_EffectAmount ("Old Film Effect Amount", Range(0,1)) = 1.0_VignetteAmount ("Vignette Opacity", Range(0,1)) = 1.0_ScratchesYSpeed ("Scratches Y Speed", Float) = 10.0_ScratchesXSpeed ("Scratches X Speed", Float) = 10.0_dustXSpeed ("Dust X Speed", Float) = 10.0_dustYSpeed ("Dust Y Speed", Float) = 10.0_RandomValue ("Random Value", Float) = 1.0_Contrast ("Contrast", Float) = 3.0_distortion ("Distortion", Float) = 0.2_cubicDistortion ("Cubic Distortion", Float) = 0.6_scale ("Scale (Zoom)", Float) = 0.8}SubShader {Pass{CGPROGRAM#pragma vertex vert_img#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastest#include "UnityCG.cginc"uniform sampler2D _MainTex;uniform sampler2D _VignetteTex;uniform sampler2D _ScratchesTex;uniform sampler2D _DustTex;fixed4 _SepiaColor;fixed _VignetteAmount;fixed _ScratchesYSpeed;fixed _ScratchesXSpeed;fixed _dustXSpeed;fixed _dustYSpeed;fixed _EffectAmount;fixed _RandomValue;fixed _Contrast;float _distortion;float _cubicDistortion;float _scale;float2 barrelDistortion(float2 coord) {float2 h = coord.xy - float2(0.5, 0.5);float r2 = h.x * h.x + h.y * h.y;float f = 1.0 + r2 * (_distortion + _cubicDistortion * sqrt(r2));return f * _scale * h + 0.5;}fixed4 frag(v2f_img i) : COLOR{//Get the colors from the RenderTexture and the uv's//from the v2f_img structhalf2 distortedUV = barrelDistortion(i.uv);distortedUV = half2(i.uv.x, i.uv.y + (_RandomValue * _SinTime.z * 0.005));fixed4 renderTex = tex2D(_MainTex, i.uv);//Get the pixels from the Vignette Texturefixed4 vignetteTex = tex2D(_VignetteTex, i.uv);//Process the Scratches UV and pixelshalf2 scratchesUV = half2(i.uv.x + (_RandomValue * _SinTime.z * _ScratchesXSpeed), i.uv.y + (_Time.x * _ScratchesYSpeed));fixed4 scratchesTex = tex2D(_ScratchesTex, scratchesUV);//Process the Dust UV and pixelshalf2 dustUV = half2(i.uv.x + (_RandomValue * (_SinTime.z * _dustXSpeed)), i.uv.y + (_RandomValue * (_SinTime.z * _dustYSpeed)));fixed4 dustTex = tex2D(_DustTex, dustUV);// get the luminosity values from the render texture using the YIQ values.fixed lum = dot (fixed3(0.299, 0.587, 0.114), renderTex.rgb);//Add the constant color to the lum valuesfixed4 finalColor = lum + lerp(_SepiaColor, _SepiaColor +    fixed4(0.1f,0.1f,0.1f,1.0f), _RandomValue);finalColor = pow(finalColor, _Contrast);//Create a constant white color we can use to adjust opacity of effectsfixed3 constantWhite = fixed3(1,1,1);//Composite together the different layers to create finsl Screen EffectfinalColor = lerp(finalColor, finalColor * vignetteTex, _VignetteAmount);finalColor.rgb *= lerp(scratchesTex, constantWhite, (_RandomValue));finalColor.rgb *= lerp(dustTex.rgb, constantWhite, (_RandomValue * _SinTime.z));finalColor = lerp(renderTex, finalColor, _EffectAmount);return finalColor;}ENDCG}} FallBack off}

cs脚本:


using UnityEngine;using System.Collections;[ExecuteInEditMode]public class OldFilmEffect : MonoBehaviour {#region Variablespublic Shader oldFilmShader;public float OldFilmEffectAmount = 1.0f;public float contrast = 3.0f;public float distortion = 0.2f;public float cubicDistortion = 0.6f;public float scale = 0.8f;public Color sepiaColor = Color.white;public Texture2D vignetteTexture;public float vignetteAmount = 1.0f;public Texture2D scratchesTexture;public float scratchesYSpeed = 10.0f;public float scratchesXSpeed = 10.0f;public  Texture2D dustTexture;public float dustYSpeed = 10.0f;public float dustXSpeed = 10.0f;private Material curMaterial;private float randomValue;#endregion#region PropertiesMaterial material{get{if(curMaterial == null){curMaterial = new Material(oldFilmShader);curMaterial.hideFlags = HideFlags.HideAndDontSave;}return curMaterial;}}#endregionvoid Start(){if(!SystemInfo.supportsImageEffects){enabled = false;return;}if(!oldFilmShader && !oldFilmShader.isSupported){enabled = false;}}void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture){if(oldFilmShader != null){material.SetColor("_SepiaColor", sepiaColor);material.SetFloat("_VignetteAmount", vignetteAmount);material.SetFloat("_EffectAmount", OldFilmEffectAmount);material.SetFloat("_Contrast", contrast);material.SetFloat("_cubicDistortion", cubicDistortion);material.SetFloat("_distortion", distortion);material.SetFloat("_scale",scale);if(vignetteTexture){material.SetTexture("_VignetteTex", vignetteTexture);}if(scratchesTexture){material.SetTexture("_ScratchesTex", scratchesTexture);material.SetFloat("_ScratchesYSpeed", scratchesYSpeed);material.SetFloat("_ScratchesXSpeed", scratchesXSpeed);}if(dustTexture){material.SetTexture("_DustTex", dustTexture);material.SetFloat("_dustYSpeed", dustYSpeed);material.SetFloat("_dustXSpeed", dustXSpeed);material.SetFloat("_RandomValue", randomValue);}Graphics.Blit(sourceTexture, destTexture, material);}else{Graphics.Blit(sourceTexture, destTexture);}}void Update(){vignetteAmount = Mathf.Clamp01(vignetteAmount);OldFilmEffectAmount = Mathf.Clamp(OldFilmEffectAmount, 0f, 1.5f);randomValue = Random.Range(-1f,1f);contrast = Mathf.Clamp(contrast, 0f, 4f);distortion = Mathf.Clamp(distortion, -1f,1f);cubicDistortion = Mathf.Clamp(cubicDistortion, -1f, 1f);scale = Mathf.Clamp(scale, 0f, 1f);}void OnDisable(){if(curMaterial){DestroyImmediate(curMaterial);}}}

最终运行结果如图:




贴图素材下载


0 0
原创粉丝点击