-
Notifications
You must be signed in to change notification settings - Fork 855
[Feature] Skinned motion vectors for HDRP Hybrid #3224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f5d9db1
58cbddd
48b1ecf
a60bccc
b6a4805
b7dd69d
81d0788
0d6a8dd
860362d
4e921d8
82ffcd8
028e908
80c2dcd
19846d9
8ee28d1
0145e4b
cf88c73
ce95d4c
fe9468e
80199e9
34db42a
2b8ea7d
ee68b60
2825bd2
69e7eae
98d986e
690298f
8716688
b84ffcf
6f3cbf1
aa24bcf
7ac5ee9
3c2a52c
808bf70
a3c3a8e
b70a82a
5d3abda
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
#if defined(DOTS_INSTANCING_ON) | ||
struct DeformedVertexData | ||
{ | ||
float3 Position; | ||
float3 Normal; | ||
float3 Tangent; | ||
}; | ||
|
||
int _HybridDeformedVertexStreamIndex; | ||
uniform StructuredBuffer<DeformedVertexData> _DeformedMeshData; | ||
uniform StructuredBuffer<DeformedVertexData> _PreviousFrameDeformedMeshData; | ||
|
||
// Reads vertex data for compute skinned meshes in Hybdrid Renderer | ||
void FetchComputeVertexData(inout float3 pos, inout float3 nrm, inout float4 tan, in uint vertexID) | ||
{ | ||
// x,y = current and previous frame indices | ||
// z = deformation check (0 = no deformation, 1 = has deformation) | ||
// w = skinned motion vectors | ||
const int4 deformProperty = asint(unity_DOTSDeformationParams); | ||
const int doSkinning = deformProperty.z; | ||
if (doSkinning == 1) | ||
{ | ||
const int streamIndex = _HybridDeformedVertexStreamIndex; | ||
const int startIndex = deformProperty[streamIndex]; | ||
const DeformedVertexData vertexData = _DeformedMeshData[startIndex + vertexID]; | ||
|
||
pos = vertexData.Position; | ||
nrm = vertexData.Normal; | ||
tan = float4(vertexData.Tangent, 0); | ||
} | ||
} | ||
|
||
void FetchComputeVertexPosNrm(inout float3 pos, inout float3 nrm, in uint vertexID) | ||
{ | ||
// x,y = current and previous frame indices | ||
// z = deformation check (0 = no deformation, 1 = has deformation) | ||
// w = skinned motion vectors | ||
const int4 deformProperty = asint(unity_DOTSDeformationParams); | ||
const int doSkinning = deformProperty.z; | ||
if (doSkinning == 1) | ||
{ | ||
const int streamIndex = _HybridDeformedVertexStreamIndex; | ||
const int startIndex = deformProperty[streamIndex]; | ||
const DeformedVertexData vertexData = _DeformedMeshData[startIndex + vertexID]; | ||
|
||
pos = vertexData.Position; | ||
nrm = vertexData.Normal; | ||
} | ||
} | ||
|
||
void FetchComputeVertexNormal(inout float3 normal, in uint vertexID) | ||
{ | ||
const int4 deformProperty = asint(unity_DOTSDeformationParams); | ||
const int doSkinning = deformProperty.z; | ||
if (doSkinning == 1) | ||
{ | ||
const int streamIndex = _HybridDeformedVertexStreamIndex; | ||
const int startIndex = deformProperty[streamIndex]; | ||
|
||
normal = _DeformedMeshData[startIndex + vertexID].Normal; | ||
} | ||
} | ||
|
||
void FetchComputeVertexPosition(inout float3 position, in uint vertexID) | ||
{ | ||
const int4 deformProperty = asint(unity_DOTSDeformationParams); | ||
const int doSkinning = deformProperty.z; | ||
if (doSkinning == 1) | ||
{ | ||
const int streamIndex = _HybridDeformedVertexStreamIndex; | ||
const int startIndex = deformProperty[streamIndex]; | ||
|
||
position = _DeformedMeshData[startIndex + vertexID].Position; | ||
} | ||
} | ||
|
||
void FetchComputeVertexPosition(inout float4 position, in uint vertexID) | ||
{ | ||
FetchComputeVertexPosition(position.xyz, vertexID); | ||
} | ||
#endif |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1339,6 +1339,8 @@ void UpdateShaderVariablesGlobalCB(HDCamera hdCamera, CommandBuffer cmd) | |
m_ShaderVariablesGlobalCB._EnableRecursiveRayTracing = 0; | ||
m_ShaderVariablesGlobalCB._SpecularOcclusionBlend = 1.0f; | ||
} | ||
|
||
m_ShaderVariablesGlobalCB._HybridDeformedVertexStreamIndex = UnityEngine.Time.frameCount & 1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we want to use We have a FrameCount per Camera. So I guess here we should use camera.GetCameraFrameCount(); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, UnityEngine.Time.frameCount is not always incremented in the editor |
||
|
||
ConstantBuffer.PushGlobal(cmd, m_ShaderVariablesGlobalCB, HDShaderIDs._ShaderVariablesGlobal); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#if defined(DOTS_INSTANCING_ON) | ||
struct DeformedVertexData | ||
{ | ||
float3 Position; | ||
float3 Normal; | ||
float3 Tangent; | ||
}; | ||
|
||
uniform StructuredBuffer<DeformedVertexData> _DeformedMeshData; | ||
uniform StructuredBuffer<DeformedVertexData> _PreviousFrameDeformedMeshData; | ||
|
||
// Reads vertex data for compute skinned meshes in Hybdrid Renderer | ||
void FetchComputeVertexData(inout AttributesMesh input) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isn't this almost a duplication of this: https://github.com/Unity-Technologies/Graphics/pull/3224/files#diff-a6dc0267c305f8c7397a906b7ccdb070d168bd45350cac9b7b75ceaef24f2e44R14 ? Can't we share more code there? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same below FetchComputeVertexPosition. Or maybe the question is more, why do we have code in Core package if it need to be rewrite per pipeline anyway? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah now I read more code I udnerstand that the Core version is the URP version. Core shouldn't be use as URP code, Core is also use for custom SRP. So the code specific to pipeline must in in pipeline. |
||
{ | ||
// x,y = current and previous frame indices | ||
// z = deformation check (0 = no deformation, 1 = has deformation) | ||
// w = skinned motion vectors | ||
const int4 deformProperty = asint(unity_DOTSDeformationParams); | ||
const int doSkinning = deformProperty.z; | ||
if (doSkinning == 1) | ||
{ | ||
const uint streamIndex = _HybridDeformedVertexStreamIndex; | ||
const uint startIndex = deformProperty[streamIndex]; | ||
const DeformedVertexData vertexData = _DeformedMeshData[startIndex + input.vertexID]; | ||
|
||
input.positionOS = vertexData.Position; | ||
#ifdef ATTRIBUTES_NEED_NORMAL | ||
input.normalOS = vertexData.Normal; | ||
#endif | ||
#ifdef ATTRIBUTES_NEED_TANGENT | ||
input.tangentOS = float4(vertexData.Tangent, 0); | ||
#endif | ||
} | ||
} | ||
|
||
// Reads vertex position for compute skinned meshes in Hybdrid Renderer | ||
// and also previous frame position if skinned motion vectors are used | ||
void FetchComputeVertexPosition(inout float3 currPos, inout float3 prevPos, uint vertexID) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why inout float3 currPos, inout float3 prevPos are currently inout? they should be out only no ? |
||
{ | ||
// x,y = current and previous frame indices | ||
// z = deformation check (0 = no deformation, 1 = has deformation) | ||
// w = skinned motion vectors | ||
const int4 deformProperty = asint(unity_DOTSDeformationParams); | ||
const int computeSkin = deformProperty.z; | ||
const uint streamIndex = _HybridDeformedVertexStreamIndex; | ||
if (computeSkin == 1) | ||
{ | ||
const uint currMeshStart = deformProperty[streamIndex]; | ||
const uint currStreamIndex = _HybridDeformedVertexStreamIndex; | ||
currPos = _DeformedMeshData[currMeshStart + vertexID].Position; | ||
} | ||
|
||
const int skinMotionVec = deformProperty.w; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't deformProperty.w; be dependent on deformProperty.z; ? i.e we can have skinMotionVector only if computeSkin is true. Right now the code allow to have skin motion vector without skin which seems weird. |
||
if (skinMotionVec == 1) | ||
{ | ||
const uint prevStreamIndex = streamIndex ^ 1; | ||
const int prevMeshStart = deformProperty[prevStreamIndex]; | ||
he-ax marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if(prevMeshStart == -1) | ||
prevPos = _DeformedMeshData[prevMeshStart + vertexID].Position; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggetsion / Remark. It could be more efficient to have a single StructuredBuffer with both the previous and current position and dealing with and offset instead of branching on buffer read like this which waste VGPR. i.e StructuredBuffer _FrameDeformedMeshData int offset = (prevMeshStart == -1) ? 0 : nextStart; => no branch, less sgpr/vgpr use to store the two uniform structureBuffer. thought? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm currently I am confuse by the code, it looks like you alrady do that. with prevMeshStart and currMeshStart , so why is there a different _PreviousFrameDeformedMeshData structure buffer? sorry if my question is stupid I don't know the underlaying of DOTS skinning |
||
else | ||
prevPos = _PreviousFrameDeformedMeshData[prevMeshStart + vertexID].Position; | ||
|
||
} | ||
} | ||
#endif |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,7 +87,6 @@ void MotionVectorPositionZBias(VaryingsToPS input) | |
|
||
PackedVaryingsType MotionVectorVS(inout VaryingsType varyingsType, AttributesMesh inputMesh, AttributesPass inputPass) | ||
{ | ||
|
||
#if !defined(TESSELLATION_ON) | ||
MotionVectorPositionZBias(varyingsType); | ||
#endif | ||
|
@@ -107,15 +106,21 @@ PackedVaryingsType MotionVectorVS(inout VaryingsType varyingsType, AttributesMes | |
{ | ||
bool hasDeformation = unity_MotionVectorsParams.x > 0.0; // Skin or morph target | ||
|
||
float3 effectivePositionOS = (hasDeformation ? inputPass.previousPositionOS : inputMesh.positionOS); | ||
float3 deformedPrevPos = inputPass.previousPositionOS; | ||
|
||
#if defined(DOTS_INSTANCING_ON) | ||
FetchComputeVertexPosition(inputMesh.positionOS, deformedPrevPos, inputMesh.vertexID); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: is dots skinning cumulative with regular skinning? inputPass.previousPositionOS contain the previous skinned mesh if any otherwise it is empty, so I am curious. Also not all DOTS instancing object have skin right? And in this case there is no need to call FetchComputeVertexPosition? I have the feeling that we should rather have a code like this: #if defined(DOTS_INSTANCING_ON) float3 effectivePositionOS = (hasDeformation ? inputPass.previousPositionOS: inputMesh.positionOS); Thought? |
||
#endif | ||
float3 effectivePositionOS = (hasDeformation) ? deformedPrevPos : inputMesh.positionOS; | ||
|
||
#if defined(_ADD_PRECOMPUTED_VELOCITY) | ||
effectivePositionOS -= inputPass.precomputedVelocity; | ||
#endif | ||
|
||
// Need to apply any vertex animation to the previous worldspace position, if we want it to show up in the motion vector buffer | ||
#if defined(HAVE_MESH_MODIFICATION) | ||
AttributesMesh previousMesh = inputMesh; | ||
previousMesh.positionOS = effectivePositionOS ; | ||
previousMesh.positionOS = effectivePositionOS; | ||
|
||
previousMesh = ApplyMeshModification(previousMesh, _LastTimeParameters.xyz); | ||
float3 previousPositionRWS = TransformPreviousObjectToWorld(previousMesh.positionOS); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,9 @@ struct AttributesMesh | |
#ifdef ATTRIBUTES_NEED_COLOR | ||
float4 color : COLOR; | ||
#endif | ||
|
||
#ifdef DOTS_INSTANCING_ON | ||
uint vertexID : SV_VertexID; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: be sure this compile on DX12 / PS4 / Xbox. We have get various surprise with system sematic ordering on those platform (with double sided, instance id etc...) also we need to use VERTEXID_SEMANTIC and not SV_VertexID There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: Guess for now Vertex_ID is only used with skinned mesh right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok reading more code it seems that we can only know dynamically if we use skinning or not, so fine. |
||
#endif | ||
UNITY_VERTEX_INPUT_INSTANCE_ID | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -126,6 +126,8 @@ VaryingsToDS InterpolateWithBaryCoordsToDS(VaryingsToDS input0, VaryingsToDS inp | |
#define PackVaryingsType PackVaryingsToPS | ||
#endif | ||
|
||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/DotsDeformation.hlsl" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. surround with dots instancing on define? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes |
||
|
||
// TODO: Here we will also have all the vertex deformation (GPU skinning, vertex animation, morph target...) or we will need to generate a compute shaders instead (better! but require work to deal with unpacking like fp16) | ||
// Make it inout so that MotionVectorPass can get the modified input values later. | ||
VaryingsMeshType VertMesh(AttributesMesh input, float3 worldSpaceOffset) | ||
|
@@ -135,6 +137,10 @@ VaryingsMeshType VertMesh(AttributesMesh input, float3 worldSpaceOffset) | |
UNITY_SETUP_INSTANCE_ID(input); | ||
UNITY_TRANSFER_INSTANCE_ID(input, output); | ||
|
||
#if defined(DOTS_INSTANCING_ON) | ||
FetchComputeVertexData(input); | ||
#endif | ||
|
||
#if defined(HAVE_MESH_MODIFICATION) | ||
input = ApplyMeshModification(input, _TimeParameters.xyz); | ||
#endif | ||
|
Uh oh!
There was an error while loading. Please reload this page.