UnityShader使用图像叠加实现运动模糊
本文实例为大家分享了UnityShader实现运动模糊的具体代码,供大家参考,具体内容如下
1.此代码挂在摄像机上,使摄像机运动起来
using UnityEngine;
using System.Collections;
public class Translating : MonoBehaviour {
public float speed = 10.0f;
public Vector3 startPoint = Vector3.zero;
public Vector3 endPoint = Vector3.zero;
public Vector3 lookAt = Vector3.zero;
public bool pingpong = true;
private Vector3 curEndPoint = Vector3.zero;
// Use this for initialization
void Start () {
transform.position = startPoint;
curEndPoint = endPoint;
}
// Update is called once per frame
void Update () {
transform.position = Vector3.Slerp(transform.position, curEndPoint, Time.deltaTime * speed);
transform.LookAt(lookAt);
if (pingpong) {
if (Vector3.Distance(transform.position, curEndPoint) < 0.001f) {
curEndPoint = Vector3.Distance(curEndPoint, endPoint) < Vector3.Distance(curEndPoint, startPoint) ? startPoint : endPoint;
}
}
}
}
2.此代码挂在摄像机上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MotionBlur : PostEffectsBase
{
public Shader MotionBlurShader;
private Material _motionBlurMaterial = null;
public Material Material
{
get
{
_motionBlurMaterial = CheckShaderAndCreateMaterial(MotionBlurShader, _motionBlurMaterial);
return _motionBlurMaterial;
}
}
//定义运动模糊在混合图像时使用的模糊参数,值越大,拖尾越明显,但过大会完全替代当前帧的渲染结果,所以最大为0.9
[Range(0.0f, 0.9f)] public float BlurAmount = 0.5f;
//定义一个RenderTexture类型的变量,保存之前图像叠加的结果
private RenderTexture _accumulationTexture;
//当脚本不运行时,立即销毁,这样在下一次开始运行时会重新叠加图像
void OnDisable()
{
DestroyImmediate(_accumulationTexture);
}
void OnRenderImage(RenderTexture src, RenderTexture dest)
{
if (Material != null)
{
//判断用于混合图像的_accumulationTexture是否为空,或者是否与当前屏幕分辨率相等
//如果不满足,需要重新创建
if (_accumulationTexture == null || _accumulationTexture.width != src.width ||
_accumulationTexture.height != src.height)
{
//立即销毁当前_accumulationTexture
DestroyImmediate(_accumulationTexture);
//创建一个与当前屏幕分辨率相等的
_accumulationTexture = new RenderTexture(src.width, src.height, 0);
//由于我们自己控制这个变量的销毁,所以不需要他显示在Hierarchy中,也不需要保存在场景中
_accumulationTexture.hideFlags = HideFlags.HideAndDontSave;
//使用当前的帧图像初始化_accumulationTexture
Graphics.Blit(src, _accumulationTexture);
}
//对渲染纹理进行恢复操作,发生在渲染的纹理而该纹理又没有被提前清空或销毁的情况下
//运动模糊每次调用OnRenderImage函数,都需要把当前纹理与_accumulationTexture中的图像混合,所以_accumulationTexture不需要被提前清空
_accumulationTexture.MarkRestoreExpected();
//将参数传给材质
Material.SetFloat("_BlurAmount", 1.0f - BlurAmount);
//把当前的屏幕图像叠加到_accumulationTexture
Graphics.Blit(src, _accumulationTexture, Material);
//把叠加后的图像输出到屏幕
Graphics.Blit(_accumulationTexture, dest);
}
else
{
Graphics.Blit(src, dest);
}
}
}
3.此Shader赋值给代码2
Shader "Unity Shaders Book/Chapter 12/MotionBlur"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
//混合系数
_BlurAmount("Blur Amount", Float) = 1.0
}
SubShader
{
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed _BlurAmount;
//定义顶点着色器
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;
}
//定义第一个片元着色器,用于更新渲染纹理的RGB通道部分
fixed4 fragRGB(v2f i) : SV_Target{
//将A通道的值设为_BlurAmount,这样在后面混合时可直接使用透明通道进行混合
return fixed4(tex2D(_MainTex, i.uv).rgb, _BlurAmount);
}
//定义第二个片元着色器,用于更新渲染纹理的A通道部分
half4 fragA(v2f i) : SV_Target{
//直接返回采样结果,为了维护渲染纹理的透明通道值,不让其受到混合时使用的透明度值的影响
return tex2D(_MainTex, i.uv);
}
ENDCG
ZTest Always Cull Off Zwrite Off
//第一个Pass,用于更新渲染纹理的RGB通道
Pass
{
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
CGPROGRAM
#pragma vertex vert
#pragma fragment fragRGB
ENDCG
}
//第二个Pass,用于更新渲染纹理的A通道
Pass
{
Blend One Zero
ColorMask A
CGPROGRAM
#pragma vertex vert
#pragma fragment fragA
ENDCG
}
}
Fallback Off
}
以上是 UnityShader使用图像叠加实现运动模糊 的全部内容, 来源链接: utcz.com/z/351970.html