设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间02 现在时间02 缓存数据 “秋是慢慢入的但冷是突然的” 就像失望是慢慢累积的 但不爱是突然的

“秋是慢慢入的但冷是突然的” 就像失望是慢慢累积的 但不爱是突然的 -- 拾忆

查看: 1786|回复: 2

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

[复制链接]

  离线 

TA的专栏

  • 打卡等级:热心大叔
  • 打卡总天数:203
  • 打卡月天数:0
  • 打卡总奖励:3146
  • 最近打卡:2023-08-27 07:10:01
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
367
主题
345
精华
0
金钱
4233
积分
740
注册时间
2022-12-23
最后登录
2025-5-31

发表于 2023-2-26 16:58:53 | 显示全部楼层 |阅读模式
本文实例为大家分享了UnityShader实现运动模糊的具体代码,供大家参考,具体内容如下
原理:
像素的当前帧的NDC坐标(x,y值由uv映射而来,z值由深度值映射而来)——(使用_CurrentViewProjectionInverseMartix变换,并除以w分量)—— 像素的世界坐标 ——(使用_PreviousViewProjectionMatrix变换,并除以w分量)—— 像素的前一帧的NDC坐标 —— (当前帧NDC-前一帧NDC)—— 速度
1.此代码挂在摄像机上,使摄像机运动起来
  1. using UnityEngine;
  2. using System.Collections;

  3. public class Translating : MonoBehaviour {

  4. public float speed = 10.0f;
  5. public Vector3 startPoint = Vector3.zero;
  6. public Vector3 endPoint = Vector3.zero;
  7. public Vector3 lookAt = Vector3.zero;
  8. public bool pingpong = true;

  9. private Vector3 curEndPoint = Vector3.zero;

  10. // Use this for initialization
  11. void Start () {
  12. transform.position = startPoint;
  13. curEndPoint = endPoint;
  14. }

  15. // Update is called once per frame
  16. void Update () {
  17. transform.position = Vector3.Slerp(transform.position, curEndPoint, Time.deltaTime * speed);
  18. transform.LookAt(lookAt);
  19. if (pingpong) {
  20.   if (Vector3.Distance(transform.position, curEndPoint) < 0.001f) {
  21.   curEndPoint = Vector3.Distance(curEndPoint, endPoint) < Vector3.Distance(curEndPoint, startPoint) ? startPoint : endPoint;
  22.   }
  23. }
  24. }
  25. }
复制代码
2.此代码挂在摄像机上
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;

  4. public class MotionBlurWithDepthTexture : PostEffectsBase
  5. {
  6. public Shader MotionBlurShader;
  7. private Material _motionBlurMaterial = null;

  8. public Material Material
  9. {
  10. get
  11. {
  12.   _motionBlurMaterial = CheckShaderAndCreateMaterial(MotionBlurShader, _motionBlurMaterial);
  13.   return _motionBlurMaterial;
  14. }
  15. }

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

  20. public Camera Camera
  21. {
  22. get
  23. {
  24.   if (_myCamera == null)
  25.   {
  26.   _myCamera = GetComponent<Camera>();
  27.   }
  28.   return _myCamera;
  29. }
  30. }

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

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

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

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

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

  58.   Graphics.Blit(src, dest, Material);
  59. }
  60. else
  61. {
  62.   Graphics.Blit(src, dest);
  63. }
  64. }
  65. }
复制代码
3.此Shader赋值给代码2
  1. Shader "Unity Shaders Book/Chapter 13/MotionBlurWithDepthTexture"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Base (RGB)", 2D) = "white" {}
  6. //模糊图像时使用的参数
  7. _BlurSize ("Blur Size", Float) = 1.0

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

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

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

  31. v2f vert(appdata_img v) {
  32. v2f o;
  33. o.pos = UnityObjectToClipPos(v.vertex);
  34. o.uv = v.texcoord;
  35. o.uv_depth = v.texcoord;

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

  42. return o;
  43. }

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

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

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

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

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

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

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

  73. Pass
  74. {
  75. ZTest Always Cull Off ZWrite Off
  76. CGPROGRAM
  77. #pragma vertex vert
  78. #pragma fragment frag
  79. ENDCG
  80. }
  81. }
  82. Fallback Off
  83. }
复制代码
180013txh5zyex3hu8uqey.jpg

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


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
16
积分
12
注册时间
2022-12-24
最后登录
2022-12-24

发表于 2025-3-20 08:25:33 | 显示全部楼层
感谢楼主,顶。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~

  离线 

TA的专栏

等级头衔

等級:晓枫资讯-列兵

在线时间
0 小时

积分成就
威望
0
贡献
0
主题
0
精华
0
金钱
12
积分
4
注册时间
2023-4-22
最后登录
2023-4-22

发表于 昨天 15:16 | 显示全部楼层
顶顶更健康!!!
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1楼
2楼
3楼

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表