UnityShader使用速度映射图实现运动模糊

本文实例为大家分享了UnityShader实现运动模糊的具体代码,供大家参考,具体内容如下

原理:

像素的当前帧的NDC坐标(x,y值由uv映射而来,z值由深度值映射而来)——(使用_CurrentViewProjectionInverseMartix变换,并除以w分量)—— 像素的世界坐标 ——(使用_PreviousViewProjectionMatrix变换,并除以w分量)—— 像素的前一帧的NDC坐标 —— (当前帧NDC-前一帧NDC)—— 速度

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 MotionBlurWithDepthTexture : PostEffectsBase
{
 public Shader MotionBlurShader;
 private Material _motionBlurMaterial = null;

 public Material Material
 {
 get
 {
  _motionBlurMaterial = CheckShaderAndCreateMaterial(MotionBlurShader, _motionBlurMaterial);
  return _motionBlurMaterial;
 }
 }

 //定义运动模糊时模糊图像使用的大小
 [Range(0.0f, 1.0f)] public float BlurSize = 0.5f;
 //定义一个Camera变量,获取该脚本所在的摄像机组建,得到摄像机的视角和投影矩阵
 private Camera _myCamera;

 public Camera Camera
 {
 get
 {
  if (_myCamera == null)
  {
  _myCamera = GetComponent<Camera>();
  }
  return _myCamera;
 }
 }

 //定义一个变量保存 上一帧摄像机的视角 * 投影矩阵
 private Matrix4x4 _previousViewProjectionMatrix;

 //在OnEnable中设置摄像机的状态,以获得深度纹理
 void OnEnable()
 {
 Camera.depthTextureMode = DepthTextureMode.Depth;
 }

 void OnRenderImage(RenderTexture src, RenderTexture dest)
 {
 if (Material != null)
 {
  //将模糊大小传给Shader
  Material.SetFloat("_BlurSize", BlurSize);

  //使用 视角 * 投影矩阵 对NDC(归一化的设备坐标)下的顶点坐标进行变换,得到该像素在世界空间下的位置
  //计算前一帧与当前帧的位置差,生成该像素的速度

  //将 前一帧视角 * 投影矩阵 传给Shader
  Material.SetMatrix("_PreviousViewProjectionMatrix", _previousViewProjectionMatrix);
  //计算 当前帧视角 * 投影矩阵
  //Camera.projectionMatrix获得当前摄像机投影矩阵
  //Camera.worldToCameraMatrix获得当前摄像机视角矩阵
  Matrix4x4 currentViewProjectionMartix = Camera.projectionMatrix * Camera.worldToCameraMatrix;
  //计算 当前帧视角 * 投影矩阵 的逆矩阵
  Matrix4x4 currentViewProjectionInverseMartix = currentViewProjectionMartix.inverse;
  //将当前帧视角 * 投影矩阵 的逆矩阵 传递给Shader
  Material.SetMatrix("_CurrentViewProjectionInverseMartix", currentViewProjectionInverseMartix);
  //将 当前帧视角 * 投影矩阵 保存为 前一帧视角 * 投影矩阵
  _previousViewProjectionMatrix = currentViewProjectionMartix;

  Graphics.Blit(src, dest, Material);
 }
 else
 {
  Graphics.Blit(src, dest);
 }
 }
}

3.此Shader赋值给代码2

Shader "Unity Shaders Book/Chapter 13/MotionBlurWithDepthTexture"
{
 Properties
 {
 _MainTex ("Base (RGB)", 2D) = "white" {}
 //模糊图像时使用的参数
 _BlurSize ("Blur Size", Float) = 1.0

 //这里并没有声明_PreviousViewProjectionMatrix和_CurrentViewProjectionInverseMartix
 //是因为Unity并没有提供矩阵类型的属性,但仍然可以在CG代码块中定义这些矩阵,并从脚本中设置它们
 }
 SubShader
 {
 CGINCLUDE
 #include "UnityCG.cginc"

 sampler2D _MainTex;
 //使用_MainTex_TexelSize变量来对深度纹理的采样坐标进行平台化差异处理
 half4 _MainTex_TexelSize;
 //Unity传递来的深度纹理
 sampler2D _CameraDepthTexture;
 //声明_PreviousViewProjectionMatrix和_CurrentViewProjectionInverseMartix
 float4x4 _PreviousViewProjectionMatrix;
 float4x4 _CurrentViewProjectionInverseMartix;
 half _BlurSize;

 //定义顶点着色器
 struct v2f {
 float4 pos : SV_POSITION;
 half2 uv : TEXCOORD0;
 //添加了用于深度纹理采样的纹理坐标变量
 half2 uv_depth : TEXCOORD1;
 };

 v2f vert(appdata_img v) {
 v2f o;
 o.pos = UnityObjectToClipPos(v.vertex);
 o.uv = v.texcoord;
 o.uv_depth = v.texcoord;

 //平台差异化处理
 #if UNITY_UV_STARTS_AT_TOP
 if (_MainTex_TexelSize.y < 0) {
 o.uv_depth.y = 1 - o.uv_depth.y;
 }
 #endif

 return o;
 }

 //定义片元着色器
 fixed4 frag(v2f i) : SV_Target{
 //使用宏和纹理坐标对深度纹理进行采样,得到深度值
 float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);

 //构建当前像素的NDC坐标,xy坐标由像素的纹理坐标映射而来,z坐标由深度值d映射而来
 float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);
 //使用 当前帧的视角 * 投影矩阵 的逆矩阵 对H进行变换
 float4 D = mul(_CurrentViewProjectionInverseMartix, H);
 //把结果除以它的w分量,得到该像素世界空间下的坐标
 float4 worldPos = D / D.w;

 //像素当前帧NDC坐标
 float4 currentPos = H;

 //使用 前一帧视角 * 投影矩阵 变换世界空间的的坐标worldPos,并除以它的w分量,得到前一帧的NDC坐标
 float4 previousPos = mul(_PreviousViewProjectionMatrix, worldPos);
 previousPos /= previousPos.w;

 //计算当前帧与前一帧在屏幕空间下的位置差,得到该像素的速度
 float2 velocity = (currentPos.xy - previousPos.xy) / 2.0f;

 //使用速度值对邻域像素进行采样,相加后取平均值得到一个模糊效果,使用_BlurSize控制采样距离
 float2 uv = i.uv;
 float4 c = tex2D(_MainTex, uv);
 uv += velocity * _BlurSize;
 for (int it = 1; it < 3; it++, uv += velocity * _BlurSize) {
 float4 currentColor = tex2D(_MainTex, uv);
 c += currentColor;
 }
 c /= 3;

 return fixed4(c.rgb, 1.0);
 }
 ENDCG

 Pass
 {
 ZTest Always Cull Off ZWrite Off
 CGPROGRAM
 #pragma vertex vert
 #pragma fragment frag
 ENDCG
 }
 }
 Fallback Off
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 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 =

  • UnityShader使用速度映射图实现运动模糊

    本文实例为大家分享了UnityShader实现运动模糊的具体代码,供大家参考,具体内容如下 原理: 像素的当前帧的NDC坐标(x,y值由uv映射而来,z值由深度值映射而来)--(使用_CurrentViewProjectionInverseMartix变换,并除以w分量)-- 像素的世界坐标 --(使用_PreviousViewProjectionMatrix变换,并除以w分量)-- 像素的前一帧的NDC坐标 -- (当前帧NDC-前一帧NDC)-- 速度 1.此代码挂在摄像机上,使摄像机运动起

  • 无限循环轮播图之运动框架(原生JS实现)

    封装运动框架 function getStyle(obj,name){ if(obj.currentStyle){ return obj.currentStyle[name]; }else{ return getComputedStyle(obj,false)[name]; } } function move(obj,json,options){ var options=options || {}; var duration=options.duration || 800; var easing

  • Opencv+Python实现图像运动模糊和高斯模糊的示例

    运动模糊:由于相机和物体之间的相对运动造成的模糊,又称为动态模糊 Opencv+Python实现运动模糊,主要用到的函数是cv2.filter2D(): # coding: utf-8 import numpy as np import cv2 def motion_blur(image, degree=12, angle=45): image = np.array(image) # 这里生成任意角度的运动模糊kernel的矩阵, degree越大,模糊程度越高 M = cv2.getRotat

  • Python imgaug库安装与使用教程(图片加模糊光雨雪雾等特效)

    目录 简介 安装 Overview 特效 Project 结构 程序 参考的源代码(来源于网络) 简易变换 试效果 使用 模糊光雨雪雾 else 重命名00001.jpg 重命名1.jpg 效果图 简介 imgaug:机器学习实验中的图像增强库,特别是卷积神经网络.支持以多种不同方式增强图像.关键点/地标.边界框.热图和分割图. 安装 在anaconda prompt里进行 pip install imgaug 看了几篇文章,出错的话可以先安装依赖库shapely Overview 特效 官网网

  • 超详细注释之OpenCV实现视频实时人脸模糊和人脸马赛克

    目录 1. 效果图 2. 原理 2.1 什么是人脸模糊,如何将其用于人脸匿名化? 2.2 执行人脸模糊/匿名化的步骤 3. 源码 3.1 图像人脸模糊源码 3.2 实时视频流人脸模糊源码 参考 这篇博客将介绍人脸检测,然后使用Python,OpenCV模糊它们来"匿名化"每张图像,以确保隐私得到保护,保证没有人脸可以被识别如何使用. 并介绍俩种模糊的方法:简单高斯模糊.像素模糊. 人脸模糊和匿名化的实际应用包括: 公共/私人区域的隐私和身份保护 在线保护儿童(即在上传的照片中模糊未成年

  • 浅谈php扩展imagick

    PHP建图通常都用GD库,因为是内置的不需要在服务器上额外安装插件,所以用起来比较省心,但是如果你的程序主要的功能就是处理图像,那麼就不建议用GD了,因为GD不但低效能而且能力也比较弱,佔用的系统资源也颇多,另外GD的creatfrom也有bug,而imagick却是一个很好的替代品,为此最近把我的一个项目由GD改成了imagick,但是改完之后出现了一些状况在此分享给大家. 首先说一下我这边出现的状况: 状况一:需要重写图像操作class 状况二:imagick多线程时会导致cpu使用率暴增到

  • js+ajax实现的A*游戏路径算法整理第1/2页

    作者:llinzzi 日期:2007-05-24 去年做了个小东西,一个在线WebGame,目前只实现了多人聊天,移动,拖动画面移动,场景系统等,可以当场景聊天室使用.不过扔了一年了.如图 美工由静电设计后台将由老于开发 今年想再捡起来好好做做,由于是基于坐标点的,所以移动路径非常费资源.找到了一个A*的路径算法,挺智能. 转载一些介绍[转自 http://data.gameres.com/message.asp?TopicID=25439]译者序:很久以前就知道了A*算法,但是从未认真读过相关

  • 使用jQuery实现的掷色子游戏动画效果

    实现原理:当色子掷出后,通过jQuery的animate()函数改变色子位移,中间加入延时效果,并变换色子背景,最终动画运行到随机产生的点数时停止,并显示掷出的点数.其实就是动画过程加入多个不同图片的帧(同flash动画影片中的帧),帧数越多效果越好,然后逐帧运行后就形成了动画效果.一.准备工作我们需要准备色子素材,本示例中,我采用从网络上获取到的色子素材,我们要做处理的是将6个色子图片(1-6点),以及中间过渡效果的图片(做运动模糊处理)放在同一张图片上,保存为dice.png,用作色子背景图

  • PHP中imagick函数的中文解释

    imagick的:: adaptiveBlurImage - 增加了自适应模糊滤镜图像  imagick的:: adaptiveResizeImage - 自适应调整图像数据依赖三角  imagick的:: adaptiveSharpenImage - 自适应锐化图像  imagick的:: adaptiveThresholdImage - 选择一个阈值,根据每个像素上的强度范围  imagick的:: addImage - imagick的物体图像列表中添加新形象  imagick的:: ad

随机推荐