这篇文章主要为大家详细介绍了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使用图像叠加实现运动模糊
基础教程推荐
猜你喜欢
- C# windows语音识别与朗读实例 2023-04-27
- 一个读写csv文件的C#类 2022-11-06
- C#类和结构详解 2023-05-30
- unity实现动态排行榜 2023-04-27
- winform把Office转成PDF文件 2023-06-14
- linux – 如何在Debian Jessie中安装dotnet core sdk 2023-09-26
- C#控制台实现飞行棋小游戏 2023-04-22
- ZooKeeper的安装及部署教程 2023-01-22
- C# 调用WebService的方法 2023-03-09
- C# List实现行转列的通用方案 2022-11-02