Skip to content

Commit 4f6daf0

Browse files
committed
[SpaceWarp] URP Commit to support Unity 2021.2
Full Commit with all of our Oculus App SpaceWarp URP changes, which were previously only on the 2020.3/oculus-app-spacewarp branch, but now on this branch which is on top of Unity's 2021.2/staging branch.
1 parent c68904a commit 4f6daf0

29 files changed

+442
-5
lines changed

com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl

+17
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ float4x4 GetWorldToHClipMatrix()
3939
return UNITY_MATRIX_VP;
4040
}
4141

42+
float4x4 GetPrevWorldToHClipMatrix()
43+
{
44+
return UNITY_MATRIX_PREV_VP;
45+
}
46+
4247
// Transform to homogenous clip space
4348
float4x4 GetViewToHClipMatrix()
4449
{
@@ -80,6 +85,13 @@ float3 TransformObjectToWorld(float3 positionOS)
8085
#endif
8186
}
8287

88+
float3 TransformPreviousObjectToWorld(float3 positionOS)
89+
{
90+
#if !defined(SHADER_STAGE_RAY_TRACING)
91+
return mul(GetPrevObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz;
92+
#endif
93+
}
94+
8395
float3 TransformWorldToObject(float3 positionWS)
8496
{
8597
#if defined(SHADER_STAGE_RAY_TRACING)
@@ -107,6 +119,11 @@ float4 TransformWorldToHClip(float3 positionWS)
107119
return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));
108120
}
109121

122+
float4 TransformWorldToPrevHClip(float3 positionWS)
123+
{
124+
return mul(GetPrevWorldToHClipMatrix(), float4(positionWS, 1.0));
125+
}
126+
110127
// Tranforms position from view space to homogenous space
111128
float4 TransformWViewToHClip(float3 positionVS)
112129
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef SG_MOTION_VECTORS_INCLUDED
2+
#define SG_MOTION_VECTORS_INCLUDED
3+
4+
PackedVaryings vert(Attributes input)
5+
{
6+
Varyings output = (Varyings)0;
7+
output = BuildVaryings(input);
8+
PackedVaryings packedOutput = (PackedVaryings)0;
9+
packedOutput = PackVaryings(output);
10+
return packedOutput;
11+
}
12+
13+
half4 frag(PackedVaryings packedInput) : SV_TARGET
14+
{
15+
Varyings unpacked = UnpackVaryings(packedInput);
16+
UNITY_SETUP_INSTANCE_ID(unpacked);
17+
18+
float3 screenPos = unpacked.curPositionCS.xyz / unpacked.curPositionCS.w;
19+
float3 screenPosPrev = unpacked.prevPositionCS.xyz / unpacked.prevPositionCS.w;
20+
half4 color = (1);
21+
color.xyz = screenPos - screenPosPrev;
22+
23+
return color;
24+
}
25+
#endif

com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/OculusMotionVectors.hlsl.meta

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl

+1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@
2323
#define SHADERPASS_DECAL_GBUFFER_PROJECTOR (19)
2424
#define SHADERPASS_DECAL_GBUFFER_MESH (20)
2525
#define SHADERPASS_DEPTHNORMALS (21)
26+
#define SHADERPASS_MOTIONVECTORS (22)
2627
#endif

com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/Varyings.hlsl

+38
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
float3 _LightPosition;
1111
#endif
1212

13+
#ifdef VARYINGS_NEED_PREVIOUS_POSITION_CS
14+
bool IsSmoothRotation(float3 prevAxis1, float3 prevAxis2, float3 currAxis1, float3 currAxis2)
15+
{
16+
float angleThreshold = 0.984f; // cos(10 degrees)
17+
float2 angleDot = float2(dot(normalize(prevAxis1), normalize(currAxis1)), dot(normalize(prevAxis2), normalize(currAxis2)));
18+
return all(angleDot > angleThreshold);
19+
}
20+
#endif
21+
1322
#if defined(FEATURES_GRAPH_VERTEX)
1423
#if defined(HAVE_VFX_MODIFICATION)
1524
VertexDescription BuildVertexDescription(Attributes input, AttributesElement element)
@@ -189,6 +198,35 @@ Varyings BuildVaryings(Attributes input)
189198
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
190199
#endif
191200

201+
#ifdef VARYINGS_NEED_CURRENT_POSITION_CS
202+
float3 curWS = TransformObjectToWorld(input.positionOS.xyz);
203+
output.curPositionCS = TransformWorldToHClip(curWS);
204+
#endif
205+
206+
#ifdef VARYINGS_NEED_PREVIOUS_POSITION_CS
207+
if (unity_MotionVectorsParams.y == 0.0)
208+
{
209+
output.prevPositionCS = float4(0.0, 0.0, 0.0, 1.0);
210+
}
211+
else
212+
{
213+
bool hasDeformation = unity_MotionVectorsParams.x > 0.0;
214+
float3 effectivePositionOS = (hasDeformation ? input.uv4.xyz : input.positionOS.xyz);
215+
float3 previousWS = TransformPreviousObjectToWorld(effectivePositionOS);
216+
217+
float4x4 previousOTW = GetPrevObjectToWorldMatrix();
218+
float4x4 currentOTW = GetObjectToWorldMatrix();
219+
if (!IsSmoothRotation(previousOTW._11_21_31, previousOTW._12_22_32, currentOTW._11_21_31, currentOTW._12_22_32))
220+
{
221+
output.prevPositionCS = output.curPositionCS;
222+
}
223+
else
224+
{
225+
output.prevPositionCS = TransformWorldToPrevHClip(previousWS);
226+
}
227+
}
228+
#endif
229+
192230
#if defined(VARYINGS_NEED_SHADOW_COORD) && defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
193231
output.shadowCoord = GetShadowCoord(vertexInput);
194232
#endif

com.unity.render-pipelines.universal/Editor/ShaderGraph/Targets/UniversalLitSubTarget.cs

+1
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ public static SubShaderDescriptor LitComputeDotsSubShader(UniversalTarget target
315315
result.passes.Add(PassVariant(CorePasses.ScenePicking(target), CorePragmas.DOTSDefault));
316316

317317
result.passes.Add(PassVariant(LitPasses._2D(target), CorePragmas.DOTSDefault));
318+
result.passes.Add(CorePasses.MotionVectors(target));
318319

319320
return result;
320321
}

com.unity.render-pipelines.universal/Editor/ShaderGraph/Targets/UniversalTarget.cs

+51
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,38 @@ public static PassDescriptor ShadowCaster(UniversalTarget target)
877877
return result;
878878
}
879879

880+
public static PassDescriptor MotionVectors(UniversalTarget target)
881+
{
882+
var result = new PassDescriptor()
883+
{
884+
// Definition
885+
displayName = "MotionVectors",
886+
referenceName = "SHADERPASS_MOTIONVECTORS",
887+
lightMode = "MotionVectors",
888+
889+
// Template
890+
passTemplatePath = GenerationUtils.GetDefaultTemplatePath("PassMesh.template"),
891+
sharedTemplateDirectories = GenerationUtils.GetDefaultSharedTemplateDirectories(),
892+
893+
// Port Mask
894+
validVertexBlocks = CoreBlockMasks.Vertex,
895+
896+
// Fields
897+
structs = CoreStructCollections.Default,
898+
requiredFields = CoreRequiredFields.MotionVectors,
899+
fieldDependencies = CoreFieldDependencies.Default,
900+
901+
// Conditional State
902+
renderStates = CoreRenderStates.Default,
903+
pragmas = CorePragmas.DOTSInstanced,
904+
includes = CoreIncludes.MotionVectors,
905+
};
906+
907+
AddAlphaClipControlToPass(ref result, target);
908+
909+
return result;
910+
}
911+
880912
public static PassDescriptor SceneSelection(UniversalTarget target)
881913
{
882914
var result = new PassDescriptor()
@@ -1092,6 +1124,13 @@ static class CoreRequiredFields
10921124
StructFields.Varyings.normalWS,
10931125
StructFields.Varyings.tangentWS, // needed for vertex lighting
10941126
};
1127+
1128+
public static readonly FieldCollection MotionVectors = new FieldCollection()
1129+
{
1130+
StructFields.Attributes.uv4, // needed for previousPositionOS
1131+
UniversalStructFields.Varyings.curPositionCS,
1132+
UniversalStructFields.Varyings.prevPositionCS,
1133+
};
10951134
}
10961135
#endregion
10971136

@@ -1383,6 +1422,7 @@ static class CoreIncludes
13831422
const string kTextureStack = "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl";
13841423
const string kDBuffer = "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DBuffer.hlsl";
13851424
const string kSelectionPickingPass = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/SelectionPickingPass.hlsl";
1425+
const string kMotionVectors = "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/OculusMotionVectors.hlsl";
13861426

13871427
public static readonly IncludeCollection CorePregraph = new IncludeCollection
13881428
{
@@ -1463,6 +1503,17 @@ static class CoreIncludes
14631503
{ CorePostgraph },
14641504
{ kSelectionPickingPass, IncludeLocation.Postgraph },
14651505
};
1506+
1507+
public static readonly IncludeCollection MotionVectors = new IncludeCollection
1508+
{
1509+
// Pre-graph
1510+
{ CoreIncludes.CorePregraph },
1511+
{ CoreIncludes.ShaderGraphPregraph },
1512+
1513+
// Post-graph
1514+
{ CoreIncludes.CorePostgraph },
1515+
{ kMotionVectors, IncludeLocation.Postgraph },
1516+
};
14661517
}
14671518
#endregion
14681519

com.unity.render-pipelines.universal/Editor/ShaderGraph/Targets/UniversalUnlitSubTarget.cs

+1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public static SubShaderDescriptor Unlit(UniversalTarget target, string renderTyp
161161
result.passes.Add(CorePasses.ScenePicking(target));
162162

163163
result.passes.Add(UnlitPasses.DepthNormalOnly(target));
164+
result.passes.Add(CorePasses.MotionVectors(target));
164165

165166
return result;
166167
}

com.unity.render-pipelines.universal/Editor/ShaderGraph/UniversalStructFields.cs

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ public struct Varyings
2121
"SV_RenderTargetArrayIndex", "(defined(UNITY_STEREO_INSTANCING_ENABLED))", StructFieldOptions.Generated);
2222
public static FieldDescriptor stereoTargetEyeIndexAsBlendIdx0 = new FieldDescriptor(Varyings.name, "stereoTargetEyeIndexAsBlendIdx0", "", ShaderValueType.Uint,
2323
"BLENDINDICES0", "(defined(UNITY_STEREO_MULTIVIEW_ENABLED)) || (defined(UNITY_STEREO_INSTANCING_ENABLED) && (defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE)))");
24+
public static FieldDescriptor curPositionCS = new FieldDescriptor(Varyings.name, "curPositionCS", "VARYINGS_NEED_CURRENT_POSITION_CS", ShaderValueType.Float4,
25+
subscriptOptions: StructFieldOptions.Optional);
26+
public static FieldDescriptor prevPositionCS = new FieldDescriptor(Varyings.name, "prevPositionCS", "VARYINGS_NEED_PREVIOUS_POSITION_CS", ShaderValueType.Float4,
27+
subscriptOptions: StructFieldOptions.Optional);
2428
}
2529
}
2630
}

com.unity.render-pipelines.universal/Editor/ShaderGraph/UniversalStructs.cs

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ static class UniversalStructs
2727
UniversalStructFields.Varyings.sh,
2828
UniversalStructFields.Varyings.fogFactorAndVertexLight,
2929
UniversalStructFields.Varyings.shadowCoord,
30+
UniversalStructFields.Varyings.curPositionCS,
31+
UniversalStructFields.Varyings.prevPositionCS,
3032
StructFields.Varyings.instanceID,
3133
UniversalStructFields.Varyings.stereoTargetEyeIndexAsBlendIdx0,
3234
UniversalStructFields.Varyings.stereoTargetEyeIndexAsRTArrayIdx,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using UnityEngine.Profiling;
4+
5+
namespace UnityEngine.Rendering.Universal.Internal
6+
{
7+
/// <summary>
8+
/// Draw motion vectors into the given color and depth target. Both come from the Oculus runtime.
9+
///
10+
/// This will render objects that have a material and/or shader with the pass name "MotionVectors".
11+
/// </summary>
12+
public class OculusMotionVectorPass : ScriptableRenderPass
13+
{
14+
FilteringSettings m_FilteringSettings;
15+
ProfilingSampler m_ProfilingSampler;
16+
17+
RenderTargetIdentifier motionVectorColorIdentifier;
18+
RenderTargetIdentifier motionVectorDepthIdentifier;
19+
20+
public OculusMotionVectorPass(string profilerTag, bool opaque, RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask, StencilState stencilState, int stencilReference)
21+
{
22+
base.profilingSampler = new ProfilingSampler(nameof(OculusMotionVectorPass));
23+
m_ProfilingSampler = new ProfilingSampler(profilerTag);
24+
renderPassEvent = evt;
25+
m_FilteringSettings = new FilteringSettings(renderQueueRange, layerMask);
26+
}
27+
28+
internal OculusMotionVectorPass(URPProfileId profileId, bool opaque, RenderPassEvent evt, RenderQueueRange renderQueueRange, LayerMask layerMask, StencilState stencilState, int stencilReference)
29+
: this(profileId.GetType().Name, opaque, evt, renderQueueRange, layerMask, stencilState, stencilReference)
30+
{
31+
m_ProfilingSampler = ProfilingSampler.Get(profileId);
32+
}
33+
34+
public void Setup(
35+
RenderTargetIdentifier motionVecColorIdentifier,
36+
RenderTargetIdentifier motionVecDepthIdentifier)
37+
{
38+
this.motionVectorColorIdentifier = motionVecColorIdentifier;
39+
this.motionVectorDepthIdentifier = motionVecDepthIdentifier;
40+
}
41+
42+
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
43+
{
44+
ConfigureTarget(motionVectorColorIdentifier, motionVectorDepthIdentifier);
45+
ConfigureClear(ClearFlag.All, Color.black);
46+
}
47+
48+
/// <inheritdoc/>
49+
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
50+
{
51+
// NOTE: Do NOT mix ProfilingScope with named CommandBuffers i.e. CommandBufferPool.Get("name").
52+
// Currently there's an issue which results in mismatched markers.
53+
CommandBuffer cmd = CommandBufferPool.Get();
54+
using (new ProfilingScope(cmd, m_ProfilingSampler))
55+
{
56+
context.ExecuteCommandBuffer(cmd);
57+
cmd.Clear();
58+
59+
Camera camera = renderingData.cameraData.camera;
60+
var filterSettings = m_FilteringSettings;
61+
62+
var drawSettings = CreateDrawingSettings(new ShaderTagId("MotionVectors"), ref renderingData, renderingData.cameraData.defaultOpaqueSortFlags);
63+
drawSettings.perObjectData = PerObjectData.MotionVectors;
64+
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filterSettings);
65+
}
66+
context.ExecuteCommandBuffer(cmd);
67+
CommandBufferPool.Release(cmd);
68+
}
69+
}
70+
}

com.unity.render-pipelines.universal/Runtime/Passes/OculusMotionVectorPass.cs.meta

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.render-pipelines.universal/Runtime/RenderingUtils.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ public static void SetViewAndProjectionMatrices(CommandBuffer cmd, Matrix4x4 vie
145145
internal static readonly int UNITY_STEREO_MATRIX_P = Shader.PropertyToID("unity_StereoMatrixP");
146146
internal static readonly int UNITY_STEREO_MATRIX_IP = Shader.PropertyToID("unity_StereoMatrixInvP");
147147
internal static readonly int UNITY_STEREO_MATRIX_VP = Shader.PropertyToID("unity_StereoMatrixVP");
148+
internal static readonly int UNITY_STEREO_MATRIX_PREV_VP = Shader.PropertyToID("unity_StereoMatrixPrevVP");
148149
internal static readonly int UNITY_STEREO_MATRIX_IVP = Shader.PropertyToID("unity_StereoMatrixInvVP");
149150
internal static readonly int UNITY_STEREO_CAMERA_PROJECTION = Shader.PropertyToID("unity_StereoCameraProjection");
150151
internal static readonly int UNITY_STEREO_CAMERA_INV_PROJECTION = Shader.PropertyToID("unity_StereoCameraInvProjection");
@@ -154,6 +155,8 @@ public static void SetViewAndProjectionMatrices(CommandBuffer cmd, Matrix4x4 vie
154155
internal class StereoConstants
155156
{
156157
public Matrix4x4[] viewProjMatrix = new Matrix4x4[2];
158+
public Matrix4x4[] mvViewProjMatrix = new Matrix4x4[2];
159+
public Matrix4x4[] prevMVViewProjMatrix = new Matrix4x4[2];
157160
public Matrix4x4[] invViewMatrix = new Matrix4x4[2];
158161
public Matrix4x4[] invProjMatrix = new Matrix4x4[2];
159162
public Matrix4x4[] invViewProjMatrix = new Matrix4x4[2];
@@ -174,11 +177,18 @@ internal class StereoConstants
174177
/// <param name="cameraProjectionMatrix">Camera projection matrix to be set.Array size is 2. Does not include platform specific transformations such as depth-reverse, depth range in post-projective space and y-flip. </param>
175178
/// <param name="setInverseMatrices">Set this to true if you also need to set inverse camera matrices.</param>
176179
/// <returns>Void</c></returns>
177-
internal static void SetStereoViewAndProjectionMatrices(CommandBuffer cmd, Matrix4x4[] viewMatrix, Matrix4x4[] projMatrix, Matrix4x4[] cameraProjMatrix, bool setInverseMatrices)
180+
internal static void SetStereoViewAndProjectionMatrices(CommandBuffer cmd, Matrix4x4[] viewMatrix, Matrix4x4[] projMatrix, Matrix4x4[] cameraProjMatrix, bool setInverseMatrices, bool prevViewValid, Matrix4x4[] prevViewMatrix, bool isOculusMotionVec = false)
178181
{
182+
if (isOculusMotionVec)
183+
stereoConstants.mvViewProjMatrix.CopyTo(stereoConstants.prevMVViewProjMatrix, 0);
184+
179185
for (int i = 0; i < 2; i++)
180186
{
181187
stereoConstants.viewProjMatrix[i] = projMatrix[i] * viewMatrix[i];
188+
if (prevViewValid)
189+
stereoConstants.prevMVViewProjMatrix[i] = projMatrix[i] * prevViewMatrix[i];
190+
if (isOculusMotionVec)
191+
stereoConstants.mvViewProjMatrix[i] = projMatrix[i] * viewMatrix[i];
182192
stereoConstants.invViewMatrix[i] = Matrix4x4.Inverse(viewMatrix[i]);
183193
stereoConstants.invProjMatrix[i] = Matrix4x4.Inverse(projMatrix[i]);
184194
stereoConstants.invViewProjMatrix[i] = Matrix4x4.Inverse(stereoConstants.viewProjMatrix[i]);
@@ -189,6 +199,8 @@ internal static void SetStereoViewAndProjectionMatrices(CommandBuffer cmd, Matri
189199
cmd.SetGlobalMatrixArray(UNITY_STEREO_MATRIX_V, viewMatrix);
190200
cmd.SetGlobalMatrixArray(UNITY_STEREO_MATRIX_P, projMatrix);
191201
cmd.SetGlobalMatrixArray(UNITY_STEREO_MATRIX_VP, stereoConstants.viewProjMatrix);
202+
if (isOculusMotionVec)
203+
cmd.SetGlobalMatrixArray(UNITY_STEREO_MATRIX_PREV_VP, stereoConstants.prevMVViewProjMatrix);
192204

193205
cmd.SetGlobalMatrixArray(UNITY_STEREO_CAMERA_PROJECTION, cameraProjMatrix);
194206

com.unity.render-pipelines.universal/Runtime/ScriptableRenderer.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1204,10 +1204,12 @@ void SetRenderPassAttachments(CommandBuffer cmd, ScriptableRenderPass renderPass
12041204
#if ENABLE_VR && ENABLE_XR_MODULE
12051205
if (cameraData.xr.enabled)
12061206
{
1207+
bool isOculusMotionVec = renderPass is Internal.OculusMotionVectorPass;
12071208
// SetRenderTarget might alter the internal device state(winding order).
12081209
// Non-stereo buffer is already updated internally when switching render target. We update stereo buffers here to keep the consistency.
1209-
bool isRenderToBackBufferTarget = (passColorAttachment == cameraData.xr.renderTarget) && !cameraData.xr.renderTargetIsRenderTexture;
1210-
cameraData.xr.UpdateGPUViewAndProjectionMatrices(cmd, ref cameraData, !isRenderToBackBufferTarget);
1210+
bool isRenderToBackBufferTarget = ((passColorAttachment == cameraData.xr.renderTarget) && !cameraData.xr.renderTargetIsRenderTexture) ||
1211+
((passColorAttachment == cameraData.xr.motionVectorRenderTarget) && !cameraData.xr.motionVectorRenderTargetIsRenderTexture);
1212+
cameraData.xr.UpdateGPUViewAndProjectionMatrices(cmd, ref cameraData, !isRenderToBackBufferTarget, isOculusMotionVec);
12111213
}
12121214
#endif
12131215
}

com.unity.render-pipelines.universal/Runtime/UniversalRenderPipelineCore.cs

+1
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,7 @@ internal enum URPProfileId
880880
// DrawObjectsPass
881881
DrawOpaqueObjects,
882882
DrawTransparentObjects,
883+
DrawMVOpaqueObjects,
883884

884885
// RenderObjectsPass
885886
//RenderObjects,

0 commit comments

Comments
 (0)