Unity Shaders——屏幕特效老电影效果(Old Movie Screen Effect)
Posted 御雪妃舞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shaders——屏幕特效老电影效果(Old Movie Screen Effect)相关的知识,希望对你有一定的参考价值。
本文参考《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 struct
half2 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 Texture
fixed4 vignetteTex = tex2D(_VignetteTex, i.uv);
//Process the Scratches UV and pixels
half2 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 pixels
half2 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 values
fixed4 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 effects
fixed3 constantWhite = fixed3(1,1,1);
//Composite together the different layers to create finsl Screen Effect
finalColor = 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 Variables
public 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 Properties
Material material
get
if(curMaterial == null)
curMaterial = new Material(oldFilmShader);
curMaterial.hideFlags = HideFlags.HideAndDontSave;
return curMaterial;
#endregion
void 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);
最终运行结果如图:
以上是关于Unity Shaders——屏幕特效老电影效果(Old Movie Screen Effect)的主要内容,如果未能解决你的问题,请参考以下文章
Unity Shaders——屏幕灰度效果(Screen Effect)
Unity Shader——夜晚视觉屏幕特效(night vision Screen Effect)
Unity Shaders and Effects Cookbook (D-1) 设置 ZTest 来实现遮挡半透效果
Unity Shaders and Effects Cookbook (3-6) 创建各向异性高光类型(Anisotropic) 模拟金属拉丝效果