Netcode Bootstrap

This commit is contained in:
Luis Gonzalez
2026-05-31 14:27:52 -07:00
parent 99d8d2d2a9
commit 7fa77ce821
1813 changed files with 2921554 additions and 84 deletions
@@ -0,0 +1,49 @@
#ifndef DEBUG_HLSL_
#define DEBUG_HLSL_
///////////////////////////////////////////////////////////////////////////////////////////
#include "Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/DebugMarkers.cs.hlsl"
///////////////////////////////////////////////////////////////////////////////////////////
#ifdef RUKHANKA_SHADER_DEBUG
#define CHECK_MIN_MAX_RANGE(debugMarker, v, minValue, maxValue) if ((v) < (minValue) || (v) >= (maxValue)) InterlockedAdd(debugLoggerCB[debugMarker], 1);
// Vulkan reports size in elements (ints) rather then bytes as in D3D11/12
#ifdef SHADER_API_VULKAN
#define CHECK_RAW_BUFFER_OUT_OF_BOUNDS(debugMarker, index, count, buffer) \
{ \
uint bufferSize = 0; \
buffer.GetDimensions(bufferSize); \
bufferSize *= 4; \
if ((int)(index) < 0 || (int)((index) + (count)) > (int)bufferSize) InterlockedAdd(debugLoggerCB[debugMarker], 1); \
}
#else
#define CHECK_RAW_BUFFER_OUT_OF_BOUNDS(debugMarker, index, count, buffer) \
{ \
uint bufferSize = 0; \
buffer.GetDimensions(bufferSize); \
if ((int)(index) < 0 || (int)((index) + (count)) > (int)bufferSize) InterlockedAdd(debugLoggerCB[debugMarker], 1); \
}
#endif
#define CHECK_STRUCTURED_BUFFER_OUT_OF_BOUNDS(debugMarker, index, buffer) \
{ \
uint numStructs = 0; \
uint stride = 0; \
buffer.GetDimensions(numStructs, stride); \
if ((int)(index) < 0 || (int)(index) >= (int)numStructs) InterlockedAdd(debugLoggerCB[debugMarker], 1); \
}
RWStructuredBuffer<uint> debugLoggerCB;
#else
#define CHECK_MIN_MAX_RANGE(debugMarker, v, minValue, maxValue)
#define CHECK_RAW_BUFFER_OUT_OF_BOUNDS(debugMarker, index, count, buffer)
#define CHECK_STRUCTURED_BUFFER_OUT_OF_BOUNDS(debugMarker, index, buffer)
#endif
///////////////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: ba72f5fdfaa93d349a06294d14840691
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/Debug.hlsl
uploadId: 897522
@@ -0,0 +1,48 @@
using UnityEngine.Rendering;
/////////////////////////////////////////////////////////////////////////////////
namespace Rukhanka
{
[GenerateHLSL]
public enum RukhankaDebugMarkers
{
Deformation_CopyMeshData,
Deformation_CopyBlendShapes,
Deformation_CreatePerVertexDeformationWorkload,
Deformation_SkinnedMeshVertex_Write,
Deformation_SkinnedMeshVertex_Read,
Deformation_DeformedVertex_Read,
Deformation_BoneInfluence_Read,
Deformation_DeformedVertex_Write,
Deformation_FrameSkinMatrices_Read,
Deformation_PerVertexWorkload_Read,
Deformation_FrameDeformedVertex_Read,
GPUAnimator_MakeRigSpaceBoneTransforms_AnimatedBoneWorkload_Read,
GPUAnimator_MakeRigSpaceBoneTransforms_AnimationJobs_Read,
GPUAnimator_MakeRigSpaceBoneTransforms_BoneLocalTransforms_Read0,
GPUAnimator_MakeRigSpaceBoneTransforms_BoneLocalTransforms_Read1,
GPUAnimator_MakeRigSpaceBoneTransforms_OutBoneTransforms_Write,
GPUAnimator_ComputeSkinMatrices_SkinMatrixWorkload_Read,
GPUAnimator_ComputeSkinMatrices_RigSpaceBoneTransforms_Read,
GPUAnimator_ComputeSkinMatrices_OutSkinMatrices_Write,
GPUAnimator_ProcessAnimations_AnimatedBoneWorkload_Read,
GPUAnimator_ProcessAnimations_AnimationJobs_Read,
GPUAnimator_ProcessAnimations_OutAnimatedBones_Write,
GPUAnimator_GenericAvatar_AvatarMaskBuffer_Read,
GPUAnimator_HumanoidAvatar_AvatarMaskBuffer_Read,
GPUAnimator_HumanRotationData_Read,
GPUAnimator_QueryPerfectHashTable_AnimationClips_Read0,
GPUAnimator_QueryPerfectHashTable_AnimationClips_Read1,
GPUAnimator_KeyFrame_Read,
GPUAnimator_Track_Read,
GPUAnimator_TrackSet_Read,
GPUAnimator_AnimationClip_Read,
GPUAnimator_SkinnedMeshBone_Read,
GPUAnimator_RigDefinition_Read,
GPUAnimator_RigBone_Read,
GPUAnimator_GPUAttachment_RigSpaceBoneTransforms_Read,
Total
}
}
@@ -0,0 +1,48 @@
//
// This file was automatically generated. Please don't edit by hand. Execute Editor command [ Edit > Rendering > Generate Shader Includes ] instead
//
#ifndef DEBUGMARKERS_CS_HLSL
#define DEBUGMARKERS_CS_HLSL
//
// Rukhanka.RukhankaDebugMarkers: static fields
//
#define RUKHANKADEBUGMARKERS_DEFORMATION_COPY_MESH_DATA (0)
#define RUKHANKADEBUGMARKERS_DEFORMATION_COPY_BLEND_SHAPES (1)
#define RUKHANKADEBUGMARKERS_DEFORMATION_CREATE_PER_VERTEX_DEFORMATION_WORKLOAD (2)
#define RUKHANKADEBUGMARKERS_DEFORMATION_SKINNED_MESH_VERTEX_WRITE (3)
#define RUKHANKADEBUGMARKERS_DEFORMATION_SKINNED_MESH_VERTEX_READ (4)
#define RUKHANKADEBUGMARKERS_DEFORMATION_DEFORMED_VERTEX_READ (5)
#define RUKHANKADEBUGMARKERS_DEFORMATION_BONE_INFLUENCE_READ (6)
#define RUKHANKADEBUGMARKERS_DEFORMATION_DEFORMED_VERTEX_WRITE (7)
#define RUKHANKADEBUGMARKERS_DEFORMATION_FRAME_SKIN_MATRICES_READ (8)
#define RUKHANKADEBUGMARKERS_DEFORMATION_PER_VERTEX_WORKLOAD_READ (9)
#define RUKHANKADEBUGMARKERS_DEFORMATION_FRAME_DEFORMED_VERTEX_READ (10)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_MAKE_RIG_SPACE_BONE_TRANSFORMS_ANIMATED_BONE_WORKLOAD_READ (11)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_MAKE_RIG_SPACE_BONE_TRANSFORMS_ANIMATION_JOBS_READ (12)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_MAKE_RIG_SPACE_BONE_TRANSFORMS_BONE_LOCAL_TRANSFORMS_READ0 (13)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_MAKE_RIG_SPACE_BONE_TRANSFORMS_BONE_LOCAL_TRANSFORMS_READ1 (14)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_MAKE_RIG_SPACE_BONE_TRANSFORMS_OUT_BONE_TRANSFORMS_WRITE (15)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_COMPUTE_SKIN_MATRICES_SKIN_MATRIX_WORKLOAD_READ (16)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_COMPUTE_SKIN_MATRICES_RIG_SPACE_BONE_TRANSFORMS_READ (17)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_COMPUTE_SKIN_MATRICES_OUT_SKIN_MATRICES_WRITE (18)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_PROCESS_ANIMATIONS_ANIMATED_BONE_WORKLOAD_READ (19)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_PROCESS_ANIMATIONS_ANIMATION_JOBS_READ (20)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_PROCESS_ANIMATIONS_OUT_ANIMATED_BONES_WRITE (21)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_GENERIC_AVATAR_AVATAR_MASK_BUFFER_READ (22)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_HUMANOID_AVATAR_AVATAR_MASK_BUFFER_READ (23)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_HUMAN_ROTATION_DATA_READ (24)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_QUERY_PERFECT_HASH_TABLE_ANIMATION_CLIPS_READ0 (25)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_QUERY_PERFECT_HASH_TABLE_ANIMATION_CLIPS_READ1 (26)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_KEY_FRAME_READ (27)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_TRACK_READ (28)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_TRACK_SET_READ (29)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_ANIMATION_CLIP_READ (30)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_SKINNED_MESH_BONE_READ (31)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_RIG_DEFINITION_READ (32)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_RIG_BONE_READ (33)
#define RUKHANKADEBUGMARKERS_GPUANIMATOR_GPUATTACHMENT_RIG_SPACE_BONE_TRANSFORMS_READ (34)
#define RUKHANKADEBUGMARKERS_TOTAL (35)
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 8835b540c29a9e24780f45cd69428b92
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/DebugMarkers.cs.hlsl
uploadId: 897522
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: cdbd14dcc81008542b7c6fca79ba7111
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/DebugMarkers.cs
uploadId: 897522
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5b2404e6da098614aa9939f5120e09eb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,54 @@
#ifndef ANIMATION_CLIP_HLSL_
#define ANIMATION_CLIP_HLSL_
/////////////////////////////////////////////////////////////////////////////////
#include "TrackSet.hlsl"
/////////////////////////////////////////////////////////////////////////////////
struct AnimationClip
{
uint4 hash;
TrackSet clipTracks;
TrackSet additiveReferencePoseTracks;
uint flags;
float cycleOffset;
float length;
static const uint size = (4 + 1 + 1 + 1) * 4 + TrackSet::size * 2;
/////////////////////////////////////////////////////////////////////////////////
bool IsLooped() { return GetFlag(1); }
bool LoopPoseBlend() { return GetFlag(2); }
/////////////////////////////////////////////////////////////////////////////////
bool GetFlag(int index)
{
uint v = 1u << index;
return (flags & v) != 0;
}
/////////////////////////////////////////////////////////////////////////////////
static AnimationClip ReadFromRawBuffer(ByteAddressBuffer b, int byteAddress)
{
AnimationClip rv = (AnimationClip)0;
rv.hash = b.Load4(byteAddress);
rv.clipTracks = TrackSet::ReadFromRawBuffer(b, byteAddress + 16);
rv.additiveReferencePoseTracks = TrackSet::ReadFromRawBuffer(b, byteAddress + 16 + TrackSet::size);
rv.flags = b.Load(byteAddress + 16 + TrackSet::size * 2);
rv.cycleOffset = asfloat(b.Load(byteAddress + 20 + TrackSet::size * 2));
rv.length = asfloat(b.Load(byteAddress + 24 + TrackSet::size * 2));
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_ANIMATION_CLIP_READ, byteAddress, size, b);
return rv;
}
};
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 73e65cfe5708b1346962e42ce655aad5
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/AnimationClip.hlsl
uploadId: 897522
@@ -0,0 +1,24 @@
#ifndef ANIMATION_TO_PROCESS_HLSL_
#define ANIMATION_TO_PROCESS_HLSL_
/////////////////////////////////////////////////////////////////////////////////
#define BLEND_MODE_OVERRIDE 0
#define BLEND_MODE_ADDITIVE 1
/////////////////////////////////////////////////////////////////////////////////
struct AnimationToProcess
{
int animationClipAddress;
float weight;
float time;
int blendMode;
float layerWeight;
int layerIndex;
int avatarMaskDataOffset;
};
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: ff3f32e2710712542bbe95b14f0535c3
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/AnimationToProcess.hlsl
uploadId: 897522
@@ -0,0 +1,53 @@
#ifndef AVATAR_MASK_HLSL_
#define AVATAR_MASK_HLSL_
/////////////////////////////////////////////////////////////////////////////////
// uint
ByteAddressBuffer avatarMasksBuffer;
/////////////////////////////////////////////////////////////////////////////////
bool IsBoneInGenericAvatarMask(int avatarMaskDataOffset, int boneIndex)
{
int uintIndex = boneIndex >> 5; // boneIndex / 32
int byteOffsetInUint = boneIndex & 0x1f; // boneIndex % 32
uint boneMask = 1u << byteOffsetInUint;
// First uint in mask is human body parts mask, skip it
uint absMaskDataIndex = avatarMaskDataOffset + 1 + uintIndex;
uint avatarMask = avatarMasksBuffer.Load(absMaskDataIndex * 4);
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_GENERIC_AVATAR_AVATAR_MASK_BUFFER_READ, absMaskDataIndex * 4, 4, avatarMasksBuffer);
return (avatarMask & boneMask) != 0;
}
/////////////////////////////////////////////////////////////////////////////////
bool IsBoneInHumanAvatarMask(int avatarMaskDataOffset, int humanAvatarMaskBodyPart)
{
uint absMaskDataIndex = avatarMaskDataOffset;
uint humanAvatarMask = avatarMasksBuffer.Load(absMaskDataIndex * 4);
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_HUMANOID_AVATAR_AVATAR_MASK_BUFFER_READ, absMaskDataIndex * 4, 4, avatarMasksBuffer);
return (humanAvatarMask & 1 << humanAvatarMaskBodyPart) != 0;
}
/////////////////////////////////////////////////////////////////////////////////
bool IsBoneInAvatarMask(int avatarMaskDataOffset, int humanAvatarMaskBodyPart, int boneIndex)
{
if (avatarMaskDataOffset < 0)
return true;
bool rv = humanAvatarMaskBodyPart < 0 ?
IsBoneInGenericAvatarMask(avatarMaskDataOffset, boneIndex) :
IsBoneInHumanAvatarMask(avatarMaskDataOffset, humanAvatarMaskBodyPart);
return rv;
}
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 6c18bdd7b329d1b40889497acd238107
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/AvatarMask.hlsl
uploadId: 897522
@@ -0,0 +1,119 @@
#ifndef BONE_TRANFORM_HLSL_
#define BONE_TRANFORM_HLSL_
/////////////////////////////////////////////////////////////////////////////////
#include "Quaternion.hlsl"
/////////////////////////////////////////////////////////////////////////////////
struct BoneTransform
{
float3 pos;
Quaternion rot;
float3 scale;
static const uint size = (3 + 4 + 3) * 4;
/////////////////////////////////////////////////////////////////////////////////
static BoneTransform Identity()
{
BoneTransform rv;
rv.pos = 0;
rv.rot.value = float4(0, 0, 0, 1);
rv.scale = 1;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static BoneTransform Zero()
{
BoneTransform rv = (BoneTransform)0;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static BoneTransform FromMatrix(float3x4 m)
{
BoneTransform rv;
rv.rot = Quaternion::FromMatrix((float3x3)m);
rv.pos = m._m03_m13_m23;
float3 u = m._m00_m10_m20;
float3 v = m._m01_m11_m21;
float3 w = m._m02_m12_m22;
rv.scale = float3(length(u), length(v), length(w));
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static BoneTransform Multiply(BoneTransform parent, BoneTransform child)
{
BoneTransform rv;
rv.pos = Quaternion::Rotate(parent.rot, child.pos * parent.scale) + parent.pos;
rv.rot = Quaternion::Multiply(parent.rot, child.rot);
rv.scale = parent.scale * child.scale;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static BoneTransform Scale(BoneTransform v, float3 scale)
{
v.pos *= scale.x;
v.rot.value *= scale.y;
v.scale *= scale.z;
return v;
}
/////////////////////////////////////////////////////////////////////////////////
float4x4 ToFloat4x4()
{
float3x3 rotMat = rot.ToRotationMatrix();
float4 c0 = float4(rotMat._11_21_31 * scale, pos.x);
float4 c1 = float4(rotMat._12_22_32 * scale, pos.y);
float4 c2 = float4(rotMat._13_23_33 * scale, pos.z);
float4 c3 = float4(0, 0, 0, 1);
float4x4 rv = float4x4(c0, c1, c2, c3);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static BoneTransform Inverse(BoneTransform v)
{
BoneTransform rv;
rv.rot = Quaternion::Inverse(v.rot);
rv.scale = rcp(v.scale);
rv.pos = Quaternion::Rotate(rv.rot, -v.pos * rv.scale);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static float3 TransformPoint(BoneTransform bt, float3 v)
{
float3 rv = Quaternion::Rotate(bt.rot, v * bt.scale) + bt.pos;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static float3 TransformDirection(BoneTransform bt, float3 v)
{
float3 rv = Quaternion::Rotate(bt.rot, v);
return rv;
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 3d24b7cf754800d4f80fd374dc9639ac
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/BoneTransform.hlsl
uploadId: 897522
@@ -0,0 +1,150 @@
#ifndef DUAL_QUATERNION_HLSL_
#define DUAL_QUATERBION_HLSL_
/////////////////////////////////////////////////////////////////////////////////
#include "Quaternion.hlsl"
/////////////////////////////////////////////////////////////////////////////////
struct DualQuaternion
{
Quaternion qReal, qDual;
/////////////////////////////////////////////////////////////////////////////////
static DualQuaternion Identity()
{
DualQuaternion rv;
rv.qReal.value = float4(0, 0, 0, 1);
rv.qDual.value = float4(0, 0, 0, 0);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static DualQuaternion Construct(Quaternion r, Quaternion d)
{
DualQuaternion rv;
rv.qReal = Quaternion::Normalize(r);
rv.qDual = d;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static DualQuaternion Construct(float3 t, Quaternion r)
{
DualQuaternion rv;
rv.qReal = Quaternion::Normalize(r);
Quaternion qt;
qt.value = float4(t, 0);
rv.qDual = Quaternion::Scale(Quaternion::Multiply(qt, rv.qReal), 0.5f);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static DualQuaternion Normalize(DualQuaternion q)
{
DualQuaternion rv = q;
float m = length(q.qReal.value);
float rcpM = rcp(m);
rv.qReal = Quaternion::Scale(q.qReal, rcpM);
rv.qDual = Quaternion::Scale(q.qDual, rcpM);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static DualQuaternion Multiply(DualQuaternion l, DualQuaternion r)
{
DualQuaternion rv;
rv.qReal = Quaternion::Multiply(l.qReal, r.qReal);
Quaternion qDual0 = Quaternion::Multiply(l.qDual, r.qReal);
Quaternion qDual1 = Quaternion::Multiply(l.qReal, r.qDual);
rv.qDual.value = qDual0.value + qDual1.value;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static DualQuaternion Add(DualQuaternion l, DualQuaternion r)
{
DualQuaternion rv;
rv.qReal.value = l.qReal.value + r.qReal.value;
rv.qDual.value = l.qDual.value + r.qDual.value;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static DualQuaternion Scale(DualQuaternion q, float s)
{
DualQuaternion rv;
rv.qReal = Quaternion::Scale(q.qReal, s);
rv.qDual = Quaternion::Scale(q.qDual, s);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
BoneTransform GetBoneTransform()
{
BoneTransform rv;
Quaternion t0 = Quaternion::Scale(qDual, 2);
Quaternion t1 = Quaternion::Conjugate(qReal);
Quaternion t = Quaternion::Multiply(t0, t1);
rv.pos = t.value.xyz;
rv.rot = qReal;
rv.scale = 1;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
float4x4 ToTransformMatrix()
{
DualQuaternion q = DualQuaternion::Normalize(this);
float4x4 m = float4x4
(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
float4 r = q.qReal.value;
// Extract rotation
m._11 = r.w * r.w + r.x * r.x - r.y * r.y - r.z * r.z;
m._12 = 2 * r.x * r.y + 2 * r.w * r.z;
m._13 = 2 * r.x * r.z - 2 * r.w * r.y;
m._21 = 2 * r.x * r.y - 2 * r.w * r.z;
m._22 = r.w * r.w + r.y * r.y - r.x * r.x - r.z * r.z;
m._23 = 2 * r.y * r.z + 2 * r.w * r.x;
m._31 = 2 * r.x * r.z + 2 * r.w * r.y;
m._32 = 2 * r.y * r.z - 2 * r.w * r.x;
m._33 = r.w * r.w + r.z * r.z - r.x * r.x - r.y * r.y;
// Extract translation
Quaternion t0 = Quaternion::Scale(q.qDual, 2);
Quaternion t = Quaternion::Multiply(t0, Quaternion::Conjugate(q.qReal));
m._41 = t.value.x;
m._42 = t.value.y;
m._43 = t.value.z;
return m;
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 8edf7d0e28b62ca4094ee053fe36a5b0
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/DualQuaternion.hlsl
uploadId: 897522
@@ -0,0 +1,35 @@
#ifndef HUMAN_ROTATION_DATA_HLSL_
#define HUMAN_ROTATION_DATA_HLSL_
/////////////////////////////////////////////////////////////////////////////////
struct HumanRotationData
{
float3 minMuscleAngles, maxMuscleAngles;
Quaternion preRot, postRot;
float3 sign;
static const uint size = (3 + 3 + 4 + 4 + 3) * 4;
static HumanRotationData ReadFromRawBuffer(ByteAddressBuffer b, int index)
{
int byteAddress = index * size;
HumanRotationData rv = (HumanRotationData)0;
rv.minMuscleAngles = asfloat(b.Load3(byteAddress + 0));
rv.maxMuscleAngles = asfloat(b.Load3(byteAddress + 12));
rv.preRot.value = asfloat(b.Load4(byteAddress + 24));
rv.postRot.value = asfloat(b.Load4(byteAddress + 40));
rv.sign = asfloat(b.Load3(byteAddress + 56));
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_HUMAN_ROTATION_DATA_READ, byteAddress, size, b);
return rv;
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 9d46c9cd9b4c75d4188bf5e6914efc46
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/HumanRotationData.hlsl
uploadId: 897522
@@ -0,0 +1,36 @@
#ifndef KEYFRAME_HLSL_
#define KEYFRAME_HLSL_
/////////////////////////////////////////////////////////////////////////////////
struct KeyFrame
{
float v;
float inTan;
float outTan;
float time;
static const uint size = 4 * 4;
static KeyFrame ReadFromRawBuffer(ByteAddressBuffer b, int baseAddress, int index)
{
int addr = baseAddress + index * size;
float4 v = asfloat(b.Load4(addr));
KeyFrame rv = (KeyFrame)0;
rv.v = v.x;
rv.inTan = v.y;
rv.outTan = v.z;
rv.time = v.w;
//CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_KEY_FRAME_READ, addr, size, b);
return rv;
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: ecfd91f2fbf55b847880b642d5da4cc8
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/KeyFrame.hlsl
uploadId: 897522
@@ -0,0 +1,64 @@
#ifndef PERFECT_HASH_TABLE_HLSL_
#define PERFECT_HASH_TABLE_HLSL_
/////////////////////////////////////////////////////////////////////////////////
// High-Order Half of 64-Bit Product
// Ref "Hackers Delight" 8-2
uint MultiplyHighUnsigned(uint u, uint v)
{
uint u0 = u & 0xffff;
uint u1 = u >> 16;
uint v0 = v & 0xffff;
uint v1 = v >> 16;
uint w0 = u0 * v0;
uint t = u1 * v0 + (w0 >> 16);
uint w1 = t & 0xFFFF;
uint w2 = t >> 16;
w1 = u0 * v1 + w1;
return u1 * v1 + w2 + (w1 >> 16);
}
/////////////////////////////////////////////////////////////////////////////////
uint HashLemer(uint v, uint seed)
{
seed = v ^ seed;
uint tmpH = MultiplyHighUnsigned(seed, 0x4a39b70d);
uint tmpL = seed * 0x4a39b70d;
uint m1 = tmpH ^ tmpL;
tmpH = MultiplyHighUnsigned(m1, 0x12fad5c9);
tmpL = m1 * 0x12fad5c9;
uint m2 = tmpH ^ tmpL;
return m2;
}
/////////////////////////////////////////////////////////////////////////////////
uint GetValueIndex(uint v, uint seed, uint modMask)
{
uint hv = HashLemer(v, seed);
uint rv = hv & modMask;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
int QueryPerfectHashTable(uint v, uint seed, uint phtAddress, uint sizeMask)
{
uint index = GetValueIndex(v, seed, sizeMask);
uint byteAddress = phtAddress + index * 4 * 2;
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_QUERY_PERFECT_HASH_TABLE_ANIMATION_CLIPS_READ0, byteAddress, 8, animationClips);
uint2 phtv = animationClips.Load2(byteAddress);
if (phtv.x == v)
return (int)(phtv.y & 0xffff);
uint nextIndex = phtv.y >> 16;
uint byteAddress2 = phtAddress + nextIndex * 4 * 2;
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_QUERY_PERFECT_HASH_TABLE_ANIMATION_CLIPS_READ1, byteAddress2, 8, animationClips);
uint2 phtv2 = animationClips.Load2(byteAddress2);
if (phtv2.x == v)
return (int)(phtv2.y & 0xffff);
return -1;
}
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: cd4cb6713dc57034da2b5a2cda9cf73f
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/PerfectHashTable.hlsl
uploadId: 897522
@@ -0,0 +1,216 @@
#ifndef QUATERNION_HLSL_
#define QUATERNION_HLSL_
/////////////////////////////////////////////////////////////////////////////////
struct Quaternion
{
float4 value;
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Identity()
{
Quaternion rv;
rv.value = float4(0, 0, 0, 1);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static float3 Rotate(Quaternion q, float3 v)
{
float3 t = 2 * cross(q.value.xyz, v);
float3 rv = v + q.value.w * t + cross(q.value.xyz, t);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Multiply(Quaternion a, Quaternion b)
{
Quaternion rv;
rv.value = float4(a.value.wwww * b.value + (a.value.xyzx * b.value.wwwx + a.value.yzxy * b.value.zxyy) * float4(1.0f, 1.0f, 1.0f, -1.0f) - a.value.zxyz * b.value.yzxz);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion ShortestRotation(Quaternion from, Quaternion to)
{
Quaternion rv;
uint4 sign = asuint(dot(from.value, to.value)) & 0x80000000;
rv.value = asfloat(sign ^ asuint(to.value));
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion AxisAngle(float3 axis, float angle)
{
float sina, cosa;
sincos(0.5f * angle, sina, cosa);
Quaternion rv;
rv.value = float4(axis * sina, cosa);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Normalize(Quaternion q)
{
float4 x = q.value;
Quaternion rv;
rv.value = rsqrt(dot(x, x)) * x;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Inverse(Quaternion q)
{
float4 a = q.value;
Quaternion rv;
rv.value = rcp(dot(a, a)) * a * float4(-1.0f, -1.0f, -1.0f, 1.0f);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Conjugate(Quaternion q)
{
Quaternion rv;
rv.value = q.value * float4(-1, -1, -1, 1);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion NormalizeSafe(Quaternion q)
{
float FLT_MIN_NORMAL = 1.175494351e-38F;
float len = dot(q.value, q.value);
Quaternion rv;
rv.value = float4(0, 0, 0, 1);
if (len > FLT_MIN_NORMAL)
{
rv.value = q.value * rsqrt(len);
}
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion FromMatrix(float3x3 m)
{
Quaternion rv;
float3 u = m._m00_m10_m20;
float3 v = m._m01_m11_m21;
float3 w = m._m02_m12_m22;
uint u_sign = asuint(u.x) & 0x80000000;
float t = v.y + asfloat(asuint(w.z) ^ u_sign);
uint1 u_mask1 = (int)u_sign >> 31;
uint1 t_mask1 = asint(t) >> 31;
uint4 u_mask = u_mask1.xxxx;
uint4 t_mask = t_mask1.xxxx;
uint4 u_mask_inv = uint4(~u_mask1.x, ~u_mask1.x, ~u_mask1.x, ~u_mask1.x);
uint4 t_mask_inv = uint4(~t_mask1.x, ~t_mask1.x, ~t_mask1.x, ~t_mask1.x);
float tr = 1.0f + abs(u.x);
uint4 sign_flips = uint4(0x00000000, 0x80000000, 0x80000000, 0x80000000) ^ (u_mask & uint4(0x00000000, 0x80000000, 0x00000000, 0x80000000)) ^ (t_mask & uint4(0x80000000, 0x80000000, 0x80000000, 0x00000000));
rv.value = float4(tr, u.y, w.x, v.z) + asfloat(asuint(float4(t, v.x, u.z, w.y)) ^ sign_flips); // +---, +++-, ++-+, +-++
rv.value = asfloat((asuint(rv.value) & u_mask_inv) | (asuint(rv.value.zwxy) & u_mask));
rv.value = asfloat((asuint(rv.value.wzyx) & t_mask_inv) | (asuint(rv.value) & t_mask));
rv.value = normalize(rv.value);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
float3x3 ToRotationMatrix()
{
float4 value2 = value * 2;
uint3 npn = uint3(0x80000000, 0x00000000, 0x80000000);
uint3 nnp = uint3(0x80000000, 0x80000000, 0x00000000);
uint3 pnn = uint3(0x00000000, 0x80000000, 0x80000000);
float3 c0 = value2.y * asfloat(asuint(value.yxw) ^ npn) - value2.z * asfloat(asuint(value.zwx) ^ pnn) + float3(1, 0, 0);
float3 c1 = value2.z * asfloat(asuint(value.wzy) ^ nnp) - value2.x * asfloat(asuint(value.yxw) ^ npn) + float3(0, 1, 0);
float3 c2 = value2.x * asfloat(asuint(value.zwx) ^ pnn) - value2.y * asfloat(asuint(value.wzy) ^ nnp) + float3(0, 0, 1);
float3x3 rv = float3x3(c0, c1, c2);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion EulerXYZ(float3 eulerAngles)
{
float3 sinV, cosV;
sincos(0.5f * eulerAngles, sinV, cosV);
Quaternion rv;
rv.value = float4(sinV.xyz, cosV.x) * cosV.yxxy * cosV.zzyz + sinV.yxxy * sinV.zzyz * float4(cosV.xyz, sinV.x) * float4(-1.0f, 1.0f, -1.0f, 1.0f);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static float4 ChangeSign(float4 a, float4 b)
{
return asfloat(asuint(a) ^ asuint(b) & 0x80000000);
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Scale(Quaternion q, float s)
{
Quaternion rv;
rv.value = q.value * s;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Nlerp(Quaternion a, Quaternion b, float t)
{
Quaternion rv;
rv.value = normalize(a.value + t * (ChangeSign(b.value, dot(a.value, b.value)) - a.value));
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Quaternion Slerp(Quaternion a, Quaternion b, float t)
{
float dt = dot(a.value, b.value);
if (dt < 0)
{
dt = -dt;
b.value = -b.value;
}
if (dt < 0.9995f)
{
float angle = acos(dt);
float s = rsqrt(1 - dt * dt);
float w1 = sin(angle * (1 - t)) * s;
float w2 = sin(angle * t) * s;
Quaternion rv;
rv.value = a.value * w1 + b.value * w2;
return rv;
}
return Nlerp(a, b, t);
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 4e63b0f0c621a4b47ab8c2ddfa5439b5
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/Quaternion.hlsl
uploadId: 897522
@@ -0,0 +1,37 @@
#ifndef RIG_BONE_HLSL_
#define RIG_BONE_HLSL_
/////////////////////////////////////////////////////////////////////////////////
struct RigBone
{
uint hash;
int parentBoneIndex;
BoneTransform refPose;
int humanBodyPart;
static const uint size = (1 + 1 + 1) * 4 + BoneTransform::size;
static RigBone ReadFromRawBuffer(ByteAddressBuffer b, int index)
{
int byteAddress = index * size;
RigBone rv = (RigBone)0;
rv.hash = b.Load(byteAddress);
rv.parentBoneIndex = b.Load(byteAddress + 4);
rv.refPose.pos = asfloat(b.Load3(byteAddress + 8));
rv.refPose.rot.value = asfloat(b.Load4(byteAddress + 20));
rv.refPose.scale = asfloat(b.Load3(byteAddress + 36));
rv.humanBodyPart = b.Load(byteAddress + 48);
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_RIG_BONE_READ, byteAddress, size, b);
return rv;
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: a4b682d628d7a5f4ab07b948d0360648
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/RigBone.hlsl
uploadId: 897522
@@ -0,0 +1,35 @@
#ifndef RIG_DEFINITION_HLSL_
#define RIG_DEFINITION_HLSL_
/////////////////////////////////////////////////////////////////////////////////
struct RigDefinition
{
uint4 hash;
int2 rigBonesRange;
int rootBoneIndex;
int humanRotationDataRange;
static const uint size = (4 + 2 + 1 + 1) * 4;
static RigDefinition ReadFromRawBuffer(ByteAddressBuffer b, int index)
{
int byteAddress = index * size;
RigDefinition rv = (RigDefinition)0;
rv.hash = b.Load4(byteAddress);
rv.rigBonesRange = b.Load2(byteAddress + 16);
rv.rootBoneIndex = b.Load(byteAddress + 24);
rv.humanRotationDataRange = b.Load(byteAddress + 28);
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_RIG_DEFINITION_READ, byteAddress, size, b);
return rv;
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 1d489a2e472267c46a5d755dd5e44aaf
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/RigDefinition.hlsl
uploadId: 897522
@@ -0,0 +1,59 @@
#ifndef SKIN_MATRIX_HLSL_
#define SKIN_MATRIX_HLSL_
/////////////////////////////////////////////////////////////////////////////////
struct SkinMatrix
{
static const uint size = 4 * 3 * 4;
/////////////////////////////////////////////////////////////////////////////////
static float3x4 Identity()
{
float3x4 rv = float3x4
(
float3(1, 0, 0),
float3(0, 1, 0),
float3(0, 0, 1),
float3(0, 0, 0)
);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static float3x4 ReadFromRawBuffer(ByteAddressBuffer b, int index)
{
uint byteAddress = index * size;
float3x4 rv;
rv._11_21_31_12 = asfloat(b.Load4(byteAddress + 00));
rv._22_32_13_23 = asfloat(b.Load4(byteAddress + 16));
rv._33_14_24_34 = asfloat(b.Load4(byteAddress + 32));
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_DEFORMATION_FRAME_SKIN_MATRICES_READ, byteAddress, size, b);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static void WriteToRawBuffer(RWByteAddressBuffer b, float3x4 v, int index)
{
uint byteAddress = index * size;
b.Store4(byteAddress + 00, asuint(v._11_21_31_12));
b.Store4(byteAddress + 16, asuint(v._22_32_13_23));
b.Store4(byteAddress + 32, asuint(v._33_14_24_34));
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_COMPUTE_SKIN_MATRICES_OUT_SKIN_MATRICES_WRITE, byteAddress, size, b);
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 73fb6e635eb45d14f89514aac00e453d
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/SkinMatrix.hlsl
uploadId: 897522
@@ -0,0 +1,35 @@
#ifndef SKINNED_MESH_BONE_HLSL_
#define SKINNED_MESH_BONE_HLSL_
/////////////////////////////////////////////////////////////////////////////////
struct SkinnedMeshBone
{
int boneRemapIndex;
float4x4 bindPose;
static const uint size = (1 + 12) * 4;
static SkinnedMeshBone ReadFromRawBuffer(ByteAddressBuffer b, int index)
{
int byteAddress = index * size;
SkinnedMeshBone rv = (SkinnedMeshBone)0;
rv.boneRemapIndex = b.Load(byteAddress);
rv.bindPose._11_21_31 = asfloat(b.Load3(byteAddress + 4 + 00));
rv.bindPose._12_22_32 = asfloat(b.Load3(byteAddress + 4 + 12));
rv.bindPose._13_23_33 = asfloat(b.Load3(byteAddress + 4 + 24));
rv.bindPose._14_24_34 = asfloat(b.Load3(byteAddress + 4 + 36));
rv.bindPose._41_42_43_44 = float4(0, 0, 0, 1);
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_SKINNED_MESH_BONE_READ, byteAddress, size, b);
return rv;
}
};
/////////////////////////////////////////////////////////////////////////////////
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: e6899be4c158ecd49bcc3d777ed47968
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/SkinnedMeshBone.hlsl
uploadId: 897522
@@ -0,0 +1,153 @@
#ifndef TRACK_HLSL_
#define TRACK_HLSL_
// Use of potentially uninitialized variable
#pragma warning (disable: 4000)
/////////////////////////////////////////////////////////////////////////////////
#include "KeyFrame.hlsl"
/////////////////////////////////////////////////////////////////////////////////
#define BINDING_TYPE_UNKNOWN 0
#define BINDING_TYPE_TRANSLATION 1
#define BINDING_TYPE_QUATERNION 2
#define BINDING_TYPE_EULER_ANGLES 3
#define BINDING_TYPE_HUMAN_MUSCLE 4
#define BINDING_TYPE_SCALE 5
/////////////////////////////////////////////////////////////////////////////////
struct Track
{
uint props;
uint2 keyFrameRange;
static const uint size = 3 * 4;
/////////////////////////////////////////////////////////////////////////////////
int GetBindingType()
{
return props & 0xf;
}
/////////////////////////////////////////////////////////////////////////////////
int GetChannelIndex()
{
return props >> 4 & 3;
}
/////////////////////////////////////////////////////////////////////////////////
float SampleByBinarySearch(float time, int keyFrameBaseAddress)
{
uint startIndex = keyFrameRange.x;
uint endIndex = keyFrameRange.x + keyFrameRange.y;
bool less = true;
bool greater = true;
KeyFrame frame0 = (KeyFrame)0, frame1 = (KeyFrame)0;
if (keyFrameRange.y < 3)
return SampleByLinearSearch(time, keyFrameBaseAddress);
while (endIndex - startIndex >= 1 && (less || greater) && endIndex > 1)
{
int middleIndex = (endIndex + startIndex) / 2;
frame1 = KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, middleIndex);
frame0 = KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, middleIndex - 1);
less = time < frame0.time;
greater = time > frame1.time;
startIndex = greater ? middleIndex + 1 : startIndex;
endIndex = less ? middleIndex : endIndex;
}
if (less)
return KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, startIndex).v;
if (greater)
return KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, endIndex - 1).v;
float f = (time - frame0.time) / (frame1.time - frame0.time);
return EvaluateBezierCurve(frame0, frame1, f);
}
/////////////////////////////////////////////////////////////////////////////////
float SampleByLinearSearch(float time, int keyFrameBaseAddress)
{
uint keyFrameRangeEnd = keyFrameRange.x + keyFrameRange.y;
for (uint i = keyFrameRange.x; i < keyFrameRangeEnd; ++i)
{
KeyFrame frame1 = KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, i);
if (frame1.time >= time)
{
if (i == keyFrameRange.x)
return frame1.v;
KeyFrame frame0 = KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, i - 1);
float f = (time - frame0.time) / (frame1.time - frame0.time);
return EvaluateBezierCurve(frame0, frame1, f);
}
}
return KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, keyFrameRangeEnd - 1).v;
}
/////////////////////////////////////////////////////////////////////////////////
float GetFirstFrameValue(int keyFrameBaseAddress)
{
KeyFrame f = KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, keyFrameRange.x);
return f.v;
}
/////////////////////////////////////////////////////////////////////////////////
float GetLastFrameValue(int keyFrameBaseAddress)
{
KeyFrame f = KeyFrame::ReadFromRawBuffer(animationClips, keyFrameBaseAddress, keyFrameRange.x + keyFrameRange.y - 1);
return f.v;
}
/////////////////////////////////////////////////////////////////////////////////
float EvaluateBezierCurve(KeyFrame f0, KeyFrame f1, float l)
{
float dt = f1.time - f0.time;
float m0 = f0.outTan * dt;
float m1 = f1.inTan * dt;
float t2 = l * l;
float t3 = t2 * l;
float a = 2 * t3 - 3 * t2 + 1;
float b = t3 - 2 * t2 + l;
float c = t3 - t2;
float d = -2 * t3 + 3 * t2;
float rv = a * f0.v + b * m0 + c * m1 + d * f1.v;
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
static Track ReadFromRawBuffer(ByteAddressBuffer b, uint baseAddress, uint index)
{
uint addr = baseAddress + index * size;
Track rv = (Track)0;
rv.props = b.Load(addr);
rv.keyFrameRange = b.Load2(addr + 4);
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_TRACK_READ, addr, size, b);
return rv;
}
};
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 84bdc8c736dad2d4992d881915d37e73
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/Track.hlsl
uploadId: 897522
@@ -0,0 +1,59 @@
#ifndef TRACK_SET_HLSL_
#define TRACK_SET_HLSL_
/////////////////////////////////////////////////////////////////////////////////
#include "PerfectHashTable.hlsl"
/////////////////////////////////////////////////////////////////////////////////
struct TrackSet
{
int keyFramesOffset;
int tracksOffset;
int trackGroupsOffset;
int trackGroupPHTOffset;
uint trackGroupPHTSeed;
uint trackGroupPHTSizeMask;
static const uint size = 6 * 4;
/////////////////////////////////////////////////////////////////////////////////
void OffsetByAddress(int baseAddress)
{
keyFramesOffset += baseAddress;
tracksOffset += baseAddress;
trackGroupsOffset += baseAddress;
trackGroupPHTOffset += baseAddress;
}
/////////////////////////////////////////////////////////////////////////////////
static TrackSet ReadFromRawBuffer(ByteAddressBuffer b, int byteAddress)
{
TrackSet rv = (TrackSet)0;
rv.keyFramesOffset = b.Load(byteAddress);
rv.tracksOffset = b.Load(byteAddress + 4);
rv.trackGroupsOffset = b.Load(byteAddress + 8);
rv.trackGroupPHTOffset = b.Load(byteAddress + 12);
rv.trackGroupPHTSeed = b.Load(byteAddress + 16);
rv.trackGroupPHTSizeMask = b.Load(byteAddress + 20);
CHECK_RAW_BUFFER_OUT_OF_BOUNDS(RUKHANKADEBUGMARKERS_GPUANIMATOR_TRACK_SET_READ, byteAddress, size, b);
return rv;
}
/////////////////////////////////////////////////////////////////////////////////
int GetTrackGroupIndex(uint boneHash)
{
int rv = QueryPerfectHashTable(boneHash, trackGroupPHTSeed, trackGroupPHTOffset, trackGroupPHTSizeMask);
return rv;
}
};
#endif
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 2e2e6043842193647b19662f3a9823a1
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/GPUStructures/TrackSet.hlsl
uploadId: 897522
@@ -0,0 +1,2 @@
#pragma once
#define RUKHANKA_INPLACE_SKINNING
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: ec276cbeda78fb645aa69dd1008e5618
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 298480
packageName: Rukhanka Animation System 2
packageVersion: 2.9.0
assetPath: Packages/com.rukhanka.animation/Rukhanka.Runtime/Common/Shaders/ShaderConf.hlsl
uploadId: 897522