shader入门精要读书笔记35 使用深度纹理获取像素速度来控制运动模糊

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

一、运动模糊

之前说的两种方式:运动模糊实现

一种是累积缓存,来混和多张连续的图像,消耗性能。

还有一种是采用速度缓存,这个缓存存储了各个像素当前的运动速度,然后使用该值决定模糊的方向和大小。

速度缓存就是通过深度纹理逆运算得出NDC坐标再乘以逆矩阵从而还原出世界空间中的坐标,再使用上一帧的变换矩阵乘以坐标来得到上一帧的NDC坐标,然后根据两个NDC坐标计算像素速度,从而使用速度对主纹理进行相邻像素采样,然后混合得到运动模糊效果。

二、实现

摄像机屏幕后处理脚本代码:(详细解释都在注释)

using UnityEngine;
using System.Collections;

public class MotionBlurWithDepthTexture : PostEffectsBase {

	public Shader motionBlurShader;
	private Material motionBlurMaterial = null;

	public Material material {  
		get {
			motionBlurMaterial = CheckShaderAndCreateMaterial(motionBlurShader, motionBlurMaterial);
			return motionBlurMaterial;
		}  
	}

	private Camera myCamera;			//定义获取摄像机组件
	public Camera camera {
		get {
			if (myCamera == null) {
				myCamera = GetComponent<Camera>();
			}
			return myCamera;
		}
	}

	[Range(0.0f, 1.0f)]
	public float blurSize = 0.5f;			//模糊大小

	private Matrix4x4 previousViewProjectionMatrix;			//定义一个变量用来保存上一帧的	 视角*投影矩阵
	
	void OnEnable() {
		camera.depthTextureMode |= DepthTextureMode.Depth;			//深度纹理

		previousViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;		//得到矩阵
	}
	
	void OnRenderImage (RenderTexture src, RenderTexture dest) {
		if (material != null) {
			material.SetFloat("_BlurSize", blurSize);           //给Shader传递blurSize

			material.SetMatrix("_PreviousViewProjectionMatrix", previousViewProjectionMatrix);			//传递上一帧矩阵
			Matrix4x4 currentViewProjectionMatrix = camera.projectionMatrix * camera.worldToCameraMatrix;			//计算当前帧矩阵和逆矩阵
			Matrix4x4 currentViewProjectionInverseMatrix = currentViewProjectionMatrix.inverse;
			material.SetMatrix("_CurrentViewProjectionInverseMatrix", currentViewProjectionInverseMatrix);			//传递
			previousViewProjectionMatrix = currentViewProjectionMatrix;				//更新上一帧矩阵为本帧矩阵

			Graphics.Blit (src, dest, material);		//进行效果处理。
		} else {
			Graphics.Blit(src, dest);
		}
	}
}

Shader:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 13/Motion Blur With Depth Texture" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}			//输入的渲染纹理,也就是OnRenderImage函数的src
		_BlurSize ("Blur Size", Float) = 1.0			//模糊系数
	}
	SubShader {
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		sampler2D _MainTex;
		half4 _MainTex_TexelSize;				//×××_TexelSize,可以让Untiy为我们提供×××纹理对应的每个纹素的大小
		sampler2D _CameraDepthTexture;			//Unity传递给我们的深度纹理
		float4x4 _CurrentViewProjectionInverseMatrix;		//现在的矩阵
		float4x4 _PreviousViewProjectionMatrix;				//上一帧的矩阵
		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			//处理平台差异化,用来判断是否在DX平台,如果在dx平台开启了抗锯齿,y值会为负值,
			if (_MainTex_TexelSize.y < 0)
				o.uv_depth.y = 1 - o.uv_depth.y;		//如果是,我们对Y坐标进行翻转
			#endif
					 
			return o;
		}
		
		fixed4 frag(v2f i) : SV_Target {
			
			float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv_depth);			//对深度纹理采样,得到深度值d
			
			float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d * 2 - 1, 1);		//得到NDC空间的坐标
			
			float4 D = mul(_CurrentViewProjectionInverseMatrix, H);			//对NDC坐标进行逆变换,返回到世界空间
			
			float4 worldPos = D / D.w;				//反过来透视除法?
			//应该是,反顺序的话正常齐次除法应在屏幕映射之后,但是前面并没有w,所以安排到最后不影响,应该是这样?
			
			//这样就得到了世界空间下的坐标

			
			float4 currentPos = H;			//现在的NDC坐标
			
			float4 previousPos = mul(_PreviousViewProjectionMatrix, worldPos);			//上一帧的视角投影矩阵变换世界坐标,这里应该还是视锥体,用来得到前一帧的NDC坐标
			
			previousPos /= previousPos.w;		//齐次除法 得到前一帧的NDC坐标
			
			float2 velocity = (currentPos.xy - previousPos.xy)/2.0f;			//计算像素的速度
			
			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
}

Unity Shader入门精要:从核心概念到实战效果实现 Shader作为运行在GPU上的核心渲染程序,是决定三维场景中每个像素最终颜色的算法规则。其工作原理是通过顶点着色器和片元着色器,分别处理模型的几何变换与像素着色计算,实现对光照、纹理和特效的精准控制。掌握Shader技术对于游戏开发、实时渲染和交互式应用具有重要价值,它使开发者能够从简单的材质应用者转变为视觉效果的创造者,实现诸如动态溶解、边缘发光、卡通渲染等定制化视觉效果。在Unity引擎中,无论是通过编写Surface Shader、Vertex/Fragment Shader,还是利用Shader 阅读详情

相关推荐

Unity深度感知动态模糊系统:分层控制与UI隔离实战

动态模糊是3D实时渲染中模拟人眼运动拖影的关键视觉技术,其本质并非简单的时间域图像平均,而是需结合深度缓冲、运动矢量与相机空间关系进行物理化建模。传统基于速度纹理的方案因缺乏深度衰减、UI图层耦合及帧率适应性,常导致晕动、文字发虚与空间感丧失。本文聚焦深度缓冲采样与运动矢量重映射两大核心热词,构建可编程、可验证、可分层的模糊管线——支持焦点距离驱动的模糊梯度、LayerMask级图层过滤、以及移动端帧率自适应降级,广泛适用于第三人称游戏、VR沉浸应用与AR工业可视化等对视觉精度有严苛要求的工程场景。

weixin_33674976的博客 663

Unity3D】运动模糊特效

开启混合(Blend)后,通过Alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合,当有物体运动时,就会将当前位置的物体影像与历史位置的物体影像进行混合,从而实现运动模糊效果。第一个 Pass通过Alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合,通过 ColorMask RGB保证融合不影响Alpha通道值;第二个Pass对当前屏幕的Alpha通道进行采样,通过 ColorMask A保证采样不影响RGB通道的值。

little_fat_sheep 2684

Unity径向模糊Shader实现:中心清晰边缘模糊的视觉特效

在计算机图形学中,图像后处理技术是提升视觉表现力的关键手段,它通过在渲染管线末端对屏幕图像进行二次加工,实现各种艺术化效果。其核心原理是通过着色器编程对像素进行数学运算和采样混合,从而改变最终输出画面。这项技术的工程价值在于能以较低性能成本显著增强场景氛围、引导玩家注意力或模拟物理现象。在游戏开发、影视特效和交互媒体等应用场景中,模糊类效果尤为常见,其中径向模糊通过模拟镜头变焦或旋转拖影,能有效表现速度感、冲击力或能量汇聚。本文聚焦于一种进阶实现——中心清晰、边缘渐变的径向模糊,通过自定义Shader精确控

weixin_29474431的博客 271

UnityShader入门精要——运动模糊(2)

适用于场景静止、摄像机快速运动的情况

weixin_51327051的博客 4083

Shader运动模糊

using UnityEngine; using System.Collections; [ExecuteInEditMode] [RequireComponent (typeof(Camera))] public class PostEffectsBase : MonoBehaviour { protected void Start() { CheckResource

Zok93 894

Unity Shader实现运动模糊(二) : 物体运动产生模糊

上一篇 关于运动模糊的效果是根据VP矩阵重建世界空间坐标,然后根据上一帧和当前帧的位置差作为速度方向,这种方式需要摄像机有位移才能产生效果,如果摄像机静止不动,那么VP矩阵也就不会有变化,所以上一帧和当前帧在NDC空间的位置也没有变化,即speed==0,也就不会有运动模糊的效果,而想要在摄像机不动而物体移动时产生模糊效果,则需要另一种实现方式,这种方式更简洁直观。 大致思路是: C#中记录运动...

博客标题 3157

UnityShader高级篇——运动模糊(使用速度映射图实现)

原理:像素的当前帧的NDC坐标(x,y值由uv映射而来,z值由深度值映射而来)——(使用_CurrentViewProjectionInverseMartix变换,并除以w分量)—— 像素的世界坐标 ——(使用_PreviousViewProjectionMatrix变换,并除以w分量)—— 像素的前一帧的NDC坐标 —— (当前帧NDC-前一帧NDC)—— 速度1.此代码挂在摄像机上,使摄像机运...

weixin_37994402的博客 6652

Shader入门精要读书笔记12

第13、14章 深度和法线纹理、非真实渲染 实现更加贴近应用的渲染效果(运动模糊、雾、卡通风格、素描风格),往往需要更加巧妙的思路和数学计算。 透视投影和正交投影的原理复习。 2种获取深度和法线纹理的方法:延迟渲染将纹理存入G-buffer中;正确的设置RenderType,使用单独的Pass渲染得到纹理。 脚本中相机的设置和纹理获取的代码实现,使用包装好的函数处理纹理采样后得到的线性的深度值。 使用Frame Debugger查看深度纹理的渲染效果(远裁剪平面太远或太近效果变差) 使用深度信息实现运动

武功高强的盲僧的博客 185

Unity开发者必学:KinoMotion源码深度剖析之运动向量渲染原理

KinoMotion是一款专为Unity引擎设计的运动模糊后处理效果插件,通过精确的运动向量渲染技术,为游戏画面带来电影级的动态模糊效果。本文将从源码角度深度解析其运动向量渲染原理,帮助开发者理解如何在Unity项目中实现高质量的动态模糊效果。 ## 运动向量渲染基础:从原理到实现 运动向量渲染是实现运动模糊的核心技术,它通过记录物体在连续帧之间的位置变化,计算出每个像素运动方向和距离。在K

gitblog_00469的博客 585

Unity水墨Shader开发:纹理撕裂、边缘模糊与性能优化实战指南

在实时渲染领域,Shader是实现复杂视觉效果的核心技术,它通过编写程序控制GPU的渲染管线,对顶点、像素等图形元素进行处理。其原理在于将艺术需求转化为数学与算法,在渲染管线的不同阶段(如顶点着色器、片元着色器)执行计算,从而生成最终像素颜色。这项技术的价值在于能够高效、灵活地实现从基础光照到风格化渲染的各类效果,是连接艺术创意与硬件性能的关键桥梁。在游戏开发、影视动画、数字艺术等应用场景中,Shader技术尤为重要,例如在实现具有东方美学的水墨风格渲染时,开发者常需面对纹理撕裂、边缘模糊等挑战。本文聚焦于

weixin_30729609的博客 570

unity shader入门精要_Unity后处理效果学习资源汇总

分享一下近期学习的Unity后处理资源和一些待研究的文章。大部分都是笔记,要学习的话建议看原文~后处理(Post-Processing),在图形学和游戏开发等领域是提升最终画面呈现品质的重要渲染技术。后处理渲染技术的好坏,往往决定了游戏画面是否能够达到令人惊艳的级别。《Unity Shader入门精要》中的后处理示例相关源码都在Github项目里,详细原理和说明建议看书~https://githu...

weixin_39785165的博客 788

Unity HDRP动态模糊实战优化:从运动向量原理到性能调优

动态模糊是一种模拟相机快门开启期间物体运动轨迹的后处理技术,其核心原理基于运动向量纹理。该技术通过追踪像素在帧间的位移,沿轨迹进行多次采样与混合,从而实现物理正确的运动模糊效果,能显著提升高速运动场景的视觉沉浸感和电影感。在实时渲染管线中,运动向量的生成精度与性能开销是关键挑战,涉及顶点变换、蒙皮动画和粒子系统的差异化处理。对于Unity HDRP项目,优化需从运动向量质量源头把控,通过合理配置采样数、速度钳制及分辨率,并结合Shader与脚本级定制,以平衡视觉质量与渲染性能,尤其在高规格项目及移动端平台中

weixin_34417200的博客 300

Unity高斯模糊Shader实现:从卷积原理到性能优化全解析

在计算机图形学与实时渲染领域,卷积操作是图像处理的核心基础技术之一,它通过一个权重窗口在图像上滑动并加权计算,实现对像素值的空间滤波。高斯模糊作为卷积的经典应用,其原理基于高斯函数(正态分布)计算权重,使离中心越近的像素贡献越大,从而实现平滑自然的过渡效果,避免了均值模糊的锯齿问题。这一技术具有重要的工程价值,它不仅提升了视觉效果的品质,还通过二维核分离优化(将N×N次采样降为N+N次)大幅提升了实时渲染性能。在游戏开发与UI设计等应用场景中,高斯模糊是实现Bloom泛光、景深模拟和毛玻璃效果的关键预处理步

congsikuai0611的博客 304

Unity深度纹理实现水面渲染:从原理到实战的完整Shader开发指南

在实时渲染中,深度纹理(Camera Depth Texture)是获取场景几何信息的关键技术,它存储了像素到摄像机的深度值,为后续渲染效果提供数据基础。其核心原理是通过深度缓冲机制,将不透明物体的深度信息编码为纹理,再通过线性解码函数(如LinearEyeDepth)转换为有物理意义的距离。这一技术价值在于,它使得Shader能够精确感知场景深度,从而驱动基于物理的视觉效果,如透明度衰减、边缘检测和动态交互。在游戏开发的应用场景中,深度纹理常用于实现水体渲染、体积雾、软阴影和屏幕空间反射等高级效果。本文聚

weixin_30729609的博客 382

Unity分层模糊实现:ShaderShaderGraph双方案详解

在实时渲染与游戏开发中,图像后处理是提升视觉表现力的关键技术之一,其中模糊算法是实现景深、UI聚焦等效果的核心手段。其原理基于图像卷积,通过高斯核等权重矩阵对像素进行加权平均,达到平滑图像、分离视觉层次的目的。这项技术的工程价值在于能够高效引导用户注意力,并增强场景的艺术沉浸感,广泛应用于游戏对话、UI模态框及特效突出等场景。本文聚焦于Unity引擎中的分层模糊实现,针对Shader代码与ShaderGraph可视化两种主流方案,深入探讨了基于渲染纹理与摄像机管理的技术细节,并提供了完整的性能优化指南,帮助

weixin_34160277的博客 352

GMS2 Shader入门:从像素操作到视觉特效的完整指南

Shader(着色器)是运行在GPU上的小程序,它接管了图形渲染的最终环节,允许开发者直接控制每个像素的生成过程。其核心原理在于利用GPU的大规模并行计算能力,同时处理成千上万个像素或顶点,从而实现远超CPU脚本模拟的渲染效率。这一技术为游戏和图形应用带来了巨大的价值,能够高效实现颜色滤镜、动态光照、溶解特效、全屏后处理等复杂视觉效果,广泛应用于2D/3D游戏、数据可视化及需要高性能图形处理的领域。例如,在Cesium这样的三维地球库中,Shader是实现复杂地形渲染和大气效果的关键;而在GameMaker

weixin_34293911的博客 402

【URP】Unity[后处理]运动模糊MotionBlur

URP仅支持相机运动模糊,而HDRP还支持物体独立运动模糊,并能分离处理旋转/平移分量(通过Camera Clamp Mode)。Unity URP中的MotionBlur(运动模糊)效果通过模拟真实相机在曝光时间内物体快速移动或相机自身运动导致的图像模糊现象实现。Motion Blur(运动模糊)是一种模拟真实相机在拍摄快速移动物体或自身移动时产生的模糊效果的后处理技术。这种方法适合静态场景的相机运动模糊。‌帧模糊Frame Blur‌:早期最简单的实现方式,通过混合当前帧与前一帧图像来模拟模糊效果。

2501_94593780的博客 312

Shader纹理映射核心原理:从UV坐标到采样优化,打造真实感渲染基石

纹理映射是计算机图形学中实现真实感渲染的核心技术,它解决了二维图像与三维模型表面精确关联的问题。其基本原理是通过UV坐标系统,将模型顶点映射到纹理图像上,再经由纹理采样和过滤技术,将离散的纹素转换为连续的颜色信息。这项技术的价值在于,它能够在不增加模型几何复杂度的前提下,极大地丰富表面细节,提升视觉真实感。在游戏开发、影视特效、三维可视化等应用场景中,纹理映射是构建材质系统的基础。本文深入探讨了纹理坐标、采样过滤、寻址模式等关键概念,并解析了在Shader中实现纹理映射的具体步骤,涵盖了法线贴图、金属度贴图

weixin_34234721的博客 323
上一篇: shader入门精要读书笔记34 使用深度纹理和法线纹理
下一篇: shader入门精要读书笔记36 关于平台差异一些总结
ChgMaker
博客等级 码龄9年 15粉丝 64原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值