Velocity map is mainly used in order to obtain a texture depth of each pixel of the camera with respect to motion vectors of the previous frame, wherein the method is derived.
Derived as follows:
Release first by the inverse depth texture coordinates of the vertices in the NDC (normalized device coordinates), using VP matrix (perspective projection matrix *) the inverse matrix of inverse transform for each pixel position in world space,
And then using the coordinate of the previous frame forward transform matrix VP world space under a front frame NDC coordinates, to determine the direction of the velocity using the coordinate difference and a previous frame rather NDC frame,
Finally, the direction of the texture sampling rate results and weighted averaging is performed repeatedly drawn, in order to achieve the object with motion blur direction.
Based on this principle, the elements need to be prepared are:
1. The camera's depth texture (coordinates are mapped by the NDC to, we need to reverse mapped back NDC)
2. Current VP inverse matrix of the matrix frames
3. VP matrix of the previous frame
Camera depth value and depth of the texture acquisition method has written a blog before, specifically refer to:
https://www.cnblogs.com/koshio0219/p/11178215.html
Perspective matrix (V matrix):
MyCamera.worldToCameraMatrix; (that is, to transform the world's space camera space (also known as the perspective of space, space observation))
Projection matrix (P matrix):
MyCamera.projectionMatrix; (camera space is transformed into clip space)
Specific mathematical derivation can see this article:
http://feepingcreature.github.io/math.html
The following are specific procedures to achieve:
1. This script is mounted on the camera, the parameters for fuzzy control, depth textures ready, transfer matrix:
1 using UnityEngine; 2 3 public class MotionBlurWithDepthTexCtrl : ScreenEffectBase 4 { 5 private const string _BlurSize = "_BlurSize"; 6 private const string _PreViewMatrix = "_PreViewMatrix"; 7 private const string _CurViewInserseMatrix = "_CurViewInserseMatrix"; 8 9 [Range(0.0f, 1.0f)] 10 public a float blurSize = .5f; . 11 12 is // previous frame VP matrix 13 is Private MATRIX4X4 preViewMatrix; 14 15 Private Camera myCamera; 16 public Camera MyCamera . 17 { 18 is GET . 19 { 20 is IF ( null == myCamera) 21 is { 22 is = GetComponent myCamera <Camera> (); 23 is } 24 return myCamera; 25 } 26 } 27 28 // turn this camera depth mode, and initializes the previous frame VP matrix 29 Private void OnEnable () 30 { 31 is MyCamera.depthTextureMode | = DepthTextureMode.Depth; 32 33 is // principle by the right, the front matrix is P , is behind the V matrix 34 is preViewMatrix = MyCamera.projectionMatrix * MyCamera.worldToCameraMatrix; 35 } 36 37 [ // not resume 38 is Private void OnDisable () 39 { 40 MyCamera.depthTextureMode & = ~ DepthTextureMode.Depth; 41 is } 42 is 43 is Private void OnRenderImage (the RenderTexture Source, the RenderTexture Where do you want) 44 is { 45 IF (Material's) 46 is { 47 Material.SetFloat (_BlurSize, blurSize); 48 // disposed before a matrix of VP 49 Material.SetMatrix (_PreViewMatrix, preViewMatrix ); 50 // compute the current frame VP matrix, and right by 51 is MATRIX4X4 curViewMatrix = MyCamera.projectionMatrix * MyCamera.worldToCameraMatrix; 52 is // save up, as computed before the next one 53 is preViewMatrix = curViewMatrix; 54 // Set VP matrix inverse matrix of the current frame 55 Material.SetMatrix (_CurViewInserseMatrix, curViewMatrix.inverse); 56 is 57 is Graphics.Blit (Source, Where do you want, Material's); 58 } 59 the else 60 Graphics.Blit (Source, Where do you want) ; 61 is 62 is } 63 }
2.Shader script:
1 Shader "MyUnlit/MotionBlurWithDepthTex" 2 { 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 SubShader 8 { 9 Pass 10 { 11 ZTest Always Cull Off ZWrite Off 12 13 CGPROGRAM 14 #pragma vertex vert 15 #pragma fragment frag 16 . 17 #include " UnityCG.cginc " 18 is . 19 sampler2D _MainTex; 20 is half4 _MainTex_TexelSize; 21 is Fixed _BlurSize; 22 is // declaration texture and depth corresponding to the matrix 23 is sampler2D _CameraDepthTexture; 24 a float4x4 _PreViewMatrix; 25 a float4x4 _CurViewInserseMatrix; 26 is 27 struct AppData 28 { 29 float4 Vertex: the POSITION; 30 float2 UV: TEXCOORD0; 31 is }; 32 33 is struct V2f 34 is { 35 // uv herein while the main memory and the texture uv depth texture uv, xy-based texture, zw is the depth of the texture 36 half4 uv: TEXCOORD0; 37 [ float4 Vertex: SV_POSITION; 38 is }; 39 40 V2f Vert (AppData V) 41 is { 42 is V2f O; 43 is o.vertex = UnityObjectToClipPos (v.vertex); 44 is o.uv.xy = v.uv; 45 o.uv.zw = v.uv; 46 is 47 / /Texture texture to be outside of the main differences in treatment platform 48 #if UNITY_UV_STARTS_AT_TOP 49 IF (_MainTex_TexelSize.y < 0 ) 50 o.uv.w = . 1 - o.uv.w; 51 is #endif 52 is 53 is return O; 54 is } 55 56 is fixed4 the frag (V2f I): SV_Target 57 is { 58 // with depth and texture to obtain a depth value zw 59 a float D = SAMPLE_DEPTH_TEXTURE (_CameraDepthTexture, i.uv.zw); 60 // reflect retroreflected NDC coordinates from [0, 1] to [-1,1] mapping, z is the depth value of the component itself 61 H = float4 float4 (i.uv.x * 2 - . 1 , i.uv.y * 2 - . 1 , D * 2 - . 1 , . 1 ); 62 is // inverse conversion and inverse matrix VP divided component w by the world coordinate position, divided by the w why the detailed mathematical derivation see previous link to the article 63 float4 D = MUL (_CurViewInserseMatrix, H); 64- float4 worldPos = D / Dw; 65 66 // respectively the previous frame and the current frame of NDC taking the difference coordinate calculation speed direction 67 float4 curViewPos = H; 68 float4 preViewPos = MUL (_PreViewMatrix, worldPos); 69 preViewPos / =preViewPos.w; 70 71 is // coefficients divided can be adjusted according to their needs 72 float2 Velocity = (curViewPos.xy-preViewPos.xy) / 10.0f ; 73 is 74 float2 UV = i.uv.xy; 75 // Texture sampling speed weighting, there was calculated the first two frames, a current frame including a total of three values, values in descending order, and to ensure and 1, is not a need for additional divider 76 // purpose is to allow prior Yue frame look more light effect gradually disappeared track 77 a float velColRate [ . 3 ] = { 0.6 , 0.3 , 0.1 }; 78 // current sampling result with the largest weight value of 0.6 79 fixed4 tex2D COL = (_MainTex, UV) * velColRate [ 0 ]; 80 + = Velocity * UV _BlurSize; 81 82 for ( int IT = . 1 ; IT < . 3 ; IT ++ ) 83 { 84 // before two sampling results in descending order, 0.3, 0.1 85 fixed4 curCol = tex2D (_MainTex, uv.xy) * velColRate [IT]; 86 // all the results together, to ensure that the weight is. 1 87 COL + = curCol; 88 // convenient texture offset by the speed, and make fuzzy coefficient control 89 UV + = velocity * _BlurSize; 90 } 91 is 92 return fixed4(col.rgb,1.0); 93 } 94 ENDCG 95 } 96 } 97 FallBack Off 98 }
Results are as follows: