forked from LeenkxTeam/LNXSDK
HaxeJolt
This commit is contained in:
@ -0,0 +1,42 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairApplyDeltaTransformBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x + cNumStrands; // Skip the root of each strand, it's fixed
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
if (IsVertexFixed(gVerticesFixed, vtx))
|
||||
return;
|
||||
|
||||
// Load the material
|
||||
uint strand_idx = vtx % cNumStrands;
|
||||
JPH_HairMaterial material = gMaterials[GetStrandMaterialIndex(gStrandMaterialIndex, strand_idx)];
|
||||
|
||||
// Load the vertex
|
||||
float strand_fraction = GetVertexStrandFraction(gStrandFractions, vtx);
|
||||
JPH_HairPosition pos = gPositions[vtx];
|
||||
JPH_HairVelocity vel = gVelocities[vtx];
|
||||
|
||||
// Transform the position so that it stays in the same place in world space (if influence is 1)
|
||||
float influence = GradientSamplerSample(material.mWorldTransformInfluence, strand_fraction);
|
||||
pos.mPosition += influence * (JPH_Mat44Mul3x4Vec3(cDeltaTransform, pos.mPosition) - pos.mPosition);
|
||||
|
||||
// Linear interpolate the rotation based on the influence
|
||||
pos.mRotation = normalize(JPH_QuatMulQuat(influence * cDeltaTransformQuat + float4(0, 0, 0, 1.0f - influence), pos.mRotation));
|
||||
|
||||
// Transform velocities
|
||||
vel.mVelocity = JPH_Mat44Mul3x3Vec3(cDeltaTransform, vel.mVelocity);
|
||||
vel.mAngularVelocity = JPH_Mat44Mul3x3Vec3(cDeltaTransform, vel.mAngularVelocity);
|
||||
|
||||
// Write back vertex
|
||||
gPositions[vtx] = pos;
|
||||
gVelocities[vtx] = vel;
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairApplyDeltaTransform)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gVerticesFixed)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandFractions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandMaterialIndex)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairMaterial, gMaterials)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairVelocity, gVelocities)
|
||||
JPH_SHADER_BIND_END(JPH_HairApplyDeltaTransform)
|
||||
19
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairApplyGlobalPose.h
Normal file
19
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairApplyGlobalPose.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
void ApplyGlobalPose(JPH_IN_OUT(JPH_HairPosition) ioPos, float3 inRestPosition, JPH_Quat inRestOrientation, JPH_IN(JPH_HairGlobalPoseTransform) inGlobalPoseTransform, JPH_IN(JPH_HairMaterial) inMaterial, float inStrandFraction)
|
||||
{
|
||||
// LERP between stored global pose and global pose skinned to the scalp
|
||||
float skin_factor = GradientSamplerSample(inMaterial.mSkinGlobalPose, inStrandFraction);
|
||||
float3 in_position = inRestPosition;
|
||||
in_position += skin_factor * (inGlobalPoseTransform.mPosition + JPH_QuatMulVec3(inGlobalPoseTransform.mRotation, in_position) - in_position);
|
||||
JPH_Quat in_rotation = inRestOrientation;
|
||||
in_rotation += skin_factor * (JPH_QuatMulQuat(inGlobalPoseTransform.mRotation, in_rotation) - in_rotation);
|
||||
|
||||
// LERP between simulated position and skinned position
|
||||
float pose_factor = GradientSamplerSample(inMaterial.mGlobalPose, inStrandFraction);
|
||||
ioPos.mPosition += pose_factor * (in_position - ioPos.mPosition);
|
||||
ioPos.mRotation += pose_factor * (in_rotation - ioPos.mRotation);
|
||||
ioPos.mRotation = normalize(ioPos.mRotation);
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairApplyGlobalPoseBindings.h"
|
||||
#include "HairCommon.h"
|
||||
#include "HairApplyGlobalPose.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x + cNumStrands; // Skip the root of each strand, it's fixed
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
if (IsVertexFixed(gVerticesFixed, vtx))
|
||||
return;
|
||||
|
||||
// Load the material
|
||||
uint strand_idx = vtx % cNumStrands;
|
||||
JPH_HairMaterial material = gMaterials[GetStrandMaterialIndex(gStrandMaterialIndex, strand_idx)];
|
||||
|
||||
// Load the vertex
|
||||
float strand_fraction = GetVertexStrandFraction(gStrandFractions, vtx);
|
||||
float3 initial_pos = gInitialPositions[vtx];
|
||||
float4 initial_bishop = JPH_QuatDecompress(gInitialBishops[vtx]);
|
||||
JPH_HairGlobalPoseTransform global_pose_transform = gGlobalPoseTransforms[strand_idx];
|
||||
|
||||
// Only apply global pose
|
||||
JPH_HairPosition pos;
|
||||
pos.mPosition = float3(0, 0, 0);
|
||||
pos.mRotation = float4(0, 0, 0, 0);
|
||||
ApplyGlobalPose(pos, initial_pos, initial_bishop, global_pose_transform, material, strand_fraction);
|
||||
|
||||
// Write back vertex
|
||||
gPositions[vtx] = pos;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairApplyGlobalPose)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gVerticesFixed)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandFractions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gInitialPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gInitialBishops)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandMaterialIndex)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairMaterial, gMaterials)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairGlobalPoseTransform, gGlobalPoseTransforms)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_END(JPH_HairApplyGlobalPose)
|
||||
@ -0,0 +1,114 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairCalculateCollisionPlanesBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x + cNumStrands; // Skip the root of each strand, it's fixed
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
|
||||
// Load the vertex
|
||||
float3 pos = gPositions[vtx].mPosition;
|
||||
|
||||
// Start with a plane that is far away (i.e. no collision)
|
||||
JPH_HairCollisionPlane collision_plane;
|
||||
collision_plane.mPlane = float4(1, 0, 0, 1.0e6f);
|
||||
collision_plane.mShapeIndex = 0;
|
||||
float largest_penetration = -1.0e6f;
|
||||
|
||||
// Loop over all shapes
|
||||
uint current_idx = 0;
|
||||
uint current_plane = 0;
|
||||
for (uint current_shape_idx = 0;; ++current_shape_idx)
|
||||
{
|
||||
// Find most facing plane
|
||||
float max_distance = -1.0e6f;
|
||||
float3 max_plane_normal = float3(0, 0, 0);
|
||||
uint max_plane_face_info = 0;
|
||||
|
||||
// Get number of faces in this shape
|
||||
uint nf = gShapeIndices[current_idx++];
|
||||
if (nf == 0)
|
||||
break;
|
||||
|
||||
for (uint f = 0; f < nf; ++f)
|
||||
{
|
||||
// Get the plane
|
||||
JPH_Plane plane = gShapePlanes[current_plane++];
|
||||
float distance = JPH_PlaneSignedDistance(plane, pos);
|
||||
if (distance > max_distance)
|
||||
{
|
||||
max_distance = distance;
|
||||
max_plane_normal = JPH_PlaneGetNormal(plane);
|
||||
max_plane_face_info = current_idx;
|
||||
}
|
||||
|
||||
// Skip over vertex start and end
|
||||
current_idx += 2;
|
||||
}
|
||||
|
||||
// Project point onto that plane, in local space to the vertex
|
||||
float3 closest_point = -max_distance * max_plane_normal;
|
||||
|
||||
// Check edges if we're outside the hull (when inside we know the closest face is also the closest point to the surface)
|
||||
bool is_outside = max_distance > 0.0f;
|
||||
if (is_outside)
|
||||
{
|
||||
// Loop over edges
|
||||
float closest_point_dist_sq = 1.0e12f;
|
||||
uint vi = gShapeIndices[max_plane_face_info];
|
||||
uint vi_end = gShapeIndices[max_plane_face_info + 1];
|
||||
float3 p1 = gShapeVertices[gShapeIndices[vi_end - 1]];
|
||||
for (; vi < vi_end; ++vi)
|
||||
{
|
||||
// Get edge points
|
||||
float3 p2 = gShapeVertices[gShapeIndices[vi]];
|
||||
|
||||
// Check if the position is outside the edge (if not, the face will be closer)
|
||||
float3 p1_p2 = p2 - p1;
|
||||
float3 p1_pos = p1 - pos;
|
||||
float3 edge_normal = cross(p1_p2, max_plane_normal);
|
||||
if (dot(edge_normal, p1_pos) <= 0.0f)
|
||||
{
|
||||
// Get closest point on edge
|
||||
float3 closest = JPH_GetClosestPointOnLine(p1_pos, p1_p2);
|
||||
float distance_sq = dot(closest, closest);
|
||||
if (distance_sq < closest_point_dist_sq)
|
||||
{
|
||||
closest_point_dist_sq = distance_sq;
|
||||
closest_point = closest;
|
||||
}
|
||||
}
|
||||
|
||||
// Cycle vertex
|
||||
p1 = p2;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this is the largest penetration
|
||||
float3 normal = -closest_point;
|
||||
float normal_length = length(normal);
|
||||
float penetration = normal_length;
|
||||
if (is_outside)
|
||||
penetration = -penetration;
|
||||
else
|
||||
normal = -normal;
|
||||
if (penetration > largest_penetration)
|
||||
{
|
||||
// Calculate contact plane
|
||||
normal = normal_length > 0.0f? normal / normal_length : max_plane_normal;
|
||||
collision_plane.mPlane = JPH_PlaneFromPointAndNormal(pos + closest_point, normal);
|
||||
collision_plane.mShapeIndex = current_shape_idx;
|
||||
largest_penetration = penetration;
|
||||
}
|
||||
}
|
||||
|
||||
gCollisionPlanes[vtx] = collision_plane;
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairCalculateCollisionPlanes)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_Plane, gShapePlanes)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gShapeVertices)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gShapeIndices)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairCollisionPlane, gCollisionPlanes)
|
||||
JPH_SHADER_BIND_END(JPH_HairCalculateCollisionPlanes)
|
||||
@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
float3 SkinRenderVertex(uint inVertexIndex)
|
||||
{
|
||||
// Calculating resulting render position
|
||||
float3 out_position = float3(0, 0, 0);
|
||||
for (uint idx = inVertexIndex * cHairNumSVertexInfluences, idx_end = idx + cHairNumSVertexInfluences; idx < idx_end; ++idx)
|
||||
{
|
||||
JPH_HairSVertexInfluence inf = gSVertexInfluences[idx];
|
||||
JPH_HairPosition sim_vtx = gPositions[inf.mVertexIndex];
|
||||
out_position += inf.mWeight * (sim_vtx.mPosition + JPH_QuatMulVec3(sim_vtx.mRotation, inf.mRelativePosition));
|
||||
}
|
||||
return out_position;
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairCalculateRenderPositionsBindings.h"
|
||||
#include "HairCommon.h"
|
||||
#include "HairCalculateRenderPositions.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerRenderVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x;
|
||||
if (vtx >= cNumRenderVertices)
|
||||
return;
|
||||
|
||||
float3 out_position = SkinRenderVertex(vtx);
|
||||
|
||||
// Copy the vertex position to the output buffer
|
||||
gRenderPositions[vtx] = out_position;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
// Overridable output type
|
||||
#ifndef JPH_SHADER_BIND_RENDER_POSITIONS
|
||||
#define JPH_SHADER_BIND_RENDER_POSITIONS(name) JPH_SHADER_BIND_RW_BUFFER(JPH_float3, name)
|
||||
#endif
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairCalculateRenderPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairSVertexInfluence, gSVertexInfluences)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_RENDER_POSITIONS(gRenderPositions)
|
||||
JPH_SHADER_BIND_END(JPH_HairCalculateRenderPositions)
|
||||
56
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairCommon.h
Normal file
56
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairCommon.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "ShaderMath.h"
|
||||
#include "ShaderMat44.h"
|
||||
#include "ShaderQuat.h"
|
||||
#include "ShaderPlane.h"
|
||||
#include "ShaderVec3.h"
|
||||
|
||||
// The density and velocity fields are stored in fixed point while accumulating, this constant converts from float to fixed point.
|
||||
JPH_SHADER_CONSTANT(int, cFloatToFixed, 1 << 10)
|
||||
JPH_SHADER_CONSTANT(float, cFixedToFloat, 1.0f / float(cFloatToFixed))
|
||||
|
||||
bool IsVertexFixed(JPH_SHADER_BUFFER(JPH_uint) inVertexFixed, uint inVertexIndex)
|
||||
{
|
||||
return (inVertexFixed[inVertexIndex >> 5] & (1u << (inVertexIndex & 31))) != 0;
|
||||
}
|
||||
|
||||
float GetVertexInvMass(JPH_SHADER_BUFFER(JPH_uint) inVertexFixed, uint inVertexIndex)
|
||||
{
|
||||
return IsVertexFixed(inVertexFixed, inVertexIndex)? 0.0f : 1.0f;
|
||||
}
|
||||
|
||||
float GetVertexStrandFraction(JPH_SHADER_BUFFER(JPH_uint) inStrandFractions, uint inVertexIndex)
|
||||
{
|
||||
return ((inStrandFractions[inVertexIndex >> 2] >> ((inVertexIndex & 3) << 3)) & 0xff) * (1.0f / 255.0f);
|
||||
}
|
||||
|
||||
uint GetStrandVertexCount(JPH_SHADER_BUFFER(JPH_uint) inStrandVertexCounts, uint inStrandIndex)
|
||||
{
|
||||
return (inStrandVertexCounts[inStrandIndex >> 2] >> ((inStrandIndex & 3) << 3)) & 0xff;
|
||||
}
|
||||
|
||||
uint GetStrandMaterialIndex(JPH_SHADER_BUFFER(JPH_uint) inStrandMaterialIndex, uint inStrandIndex)
|
||||
{
|
||||
return (inStrandMaterialIndex[inStrandIndex >> 2] >> ((inStrandIndex & 3) << 3)) & 0xff;
|
||||
}
|
||||
|
||||
float GradientSamplerSample(float4 inSampler, float inStrandFraction)
|
||||
{
|
||||
return min(inSampler.w, max(inSampler.z, inSampler.y + inStrandFraction * inSampler.x));
|
||||
}
|
||||
|
||||
void GridPositionToIndexAndFraction(float3 inPosition, JPH_OUT(uint3) outIndex, JPH_OUT(float3) outFraction)
|
||||
{
|
||||
// Get position in grid space
|
||||
float3 grid_pos = min(max(inPosition - cGridOffset, float3(0, 0, 0)) * cGridScale, cGridSizeMin1);
|
||||
outIndex = min(uint3(grid_pos), cGridSizeMin2);
|
||||
outFraction = grid_pos - float3(outIndex);
|
||||
}
|
||||
|
||||
uint GridIndexToBufferIndex(uint3 inIndex)
|
||||
{
|
||||
return inIndex.x + inIndex.y * cGridStride.y + inIndex.z * cGridStride.z;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairGridAccumulateBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
void AtomicAddVelocityAndDensity(uint inIndex, int4 inValue)
|
||||
{
|
||||
JPH_AtomicAdd(gVelocityAndDensity[inIndex].x, inValue.x);
|
||||
JPH_AtomicAdd(gVelocityAndDensity[inIndex].y, inValue.y);
|
||||
JPH_AtomicAdd(gVelocityAndDensity[inIndex].z, inValue.z);
|
||||
JPH_AtomicAdd(gVelocityAndDensity[inIndex].w, inValue.w);
|
||||
}
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check that we are processing a valid vertex
|
||||
uint vtx = tid.x + cNumStrands; // Skip the root of each strand, it's fixed
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
if (IsVertexFixed(gVerticesFixed, vtx))
|
||||
return;
|
||||
|
||||
// Convert position to grid index and fraction
|
||||
uint3 index;
|
||||
float3 ma;
|
||||
GridPositionToIndexAndFraction(gPositions[vtx].mPosition, index, ma);
|
||||
float3 a = float3(1, 1, 1) - ma;
|
||||
|
||||
// Get velocity
|
||||
float4 velocity_and_density = float4(gVelocities[vtx].mVelocity, 1) * cFloatToFixed;
|
||||
|
||||
// Calculate contribution of density and velocity for each cell
|
||||
uint3 stride = cGridStride;
|
||||
uint adr_000 = GridIndexToBufferIndex(index);
|
||||
uint adr_100 = adr_000 + 1;
|
||||
uint adr_010 = adr_000 + stride.y;
|
||||
uint adr_110 = adr_010 + 1;
|
||||
AtomicAddVelocityAndDensity(adr_000, (int4)round( a.x * a.y * a.z * velocity_and_density));
|
||||
AtomicAddVelocityAndDensity(adr_100, (int4)round(ma.x * a.y * a.z * velocity_and_density));
|
||||
AtomicAddVelocityAndDensity(adr_010, (int4)round( a.x * ma.y * a.z * velocity_and_density));
|
||||
AtomicAddVelocityAndDensity(adr_110, (int4)round(ma.x * ma.y * a.z * velocity_and_density));
|
||||
AtomicAddVelocityAndDensity(adr_000 + stride.z, (int4)round( a.x * a.y * ma.z * velocity_and_density));
|
||||
AtomicAddVelocityAndDensity(adr_100 + stride.z, (int4)round(ma.x * a.y * ma.z * velocity_and_density));
|
||||
AtomicAddVelocityAndDensity(adr_010 + stride.z, (int4)round( a.x * ma.y * ma.z * velocity_and_density));
|
||||
AtomicAddVelocityAndDensity(adr_110 + stride.z, (int4)round(ma.x * ma.y * ma.z * velocity_and_density));
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairGridAccumulate)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gVerticesFixed)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairVelocity, gVelocities)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_int4, gVelocityAndDensity)
|
||||
JPH_SHADER_BIND_END(JPH_HairGridAccumulate)
|
||||
17
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairGridClear.hlsl
Normal file
17
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairGridClear.hlsl
Normal file
@ -0,0 +1,17 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairGridClearBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerGridCellBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
uint index = tid.x;
|
||||
if (index >= cNumGridPoints)
|
||||
return;
|
||||
|
||||
gVelocityAndDensity[index] = int4(0, 0, 0, 0);
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairGridClear)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_int4, gVelocityAndDensity)
|
||||
JPH_SHADER_BIND_END(JPH_HairGridClear)
|
||||
26
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairGridNormalize.hlsl
Normal file
26
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairGridNormalize.hlsl
Normal file
@ -0,0 +1,26 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairGridNormalizeBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerGridCellBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
uint index = tid.x;
|
||||
if (index >= cNumGridPoints)
|
||||
return;
|
||||
|
||||
// Convert from fixed point back to float and divide velocity by density to get average velocity
|
||||
float4 v = (float4)gVelocityAndDensity[index] * cFixedToFloat;
|
||||
float density = v.w;
|
||||
if (density > 1.0e-12f)
|
||||
{
|
||||
v.x /= density;
|
||||
v.y /= density;
|
||||
v.z /= density;
|
||||
}
|
||||
gVelocityAndDensity[index] = asint(v);
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairGridNormalize)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_int4, gVelocityAndDensity)
|
||||
JPH_SHADER_BIND_END(JPH_HairGridNormalize)
|
||||
88
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairIntegrate.h
Normal file
88
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairIntegrate.h
Normal file
@ -0,0 +1,88 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
float DeltaDensity(uint inIndex)
|
||||
{
|
||||
return gVelocityAndDensity[inIndex].w - gNeutralDensity[inIndex];
|
||||
}
|
||||
|
||||
void ApplyGrid(JPH_IN(JPH_HairPosition) inPos, JPH_IN_OUT(JPH_HairVelocity) ioVel, JPH_IN(JPH_HairMaterial) inMaterial, float inStrandFraction)
|
||||
{
|
||||
if (!inMaterial.mEnableGrid)
|
||||
return;
|
||||
|
||||
// Convert position to grid index and fraction
|
||||
uint3 index;
|
||||
float3 ma;
|
||||
GridPositionToIndexAndFraction(inPos.mPosition, index, ma);
|
||||
float3 a = float3(1, 1, 1) - ma;
|
||||
|
||||
// Get average velocity at the vertex position (trilinear sample)
|
||||
float3 velocity;
|
||||
uint3 stride = cGridStride;
|
||||
uint adr_000 = GridIndexToBufferIndex(index);
|
||||
uint adr_100 = adr_000 + 1;
|
||||
uint adr_010 = adr_000 + stride.y;
|
||||
uint adr_110 = adr_010 + 1;
|
||||
velocity = gVelocityAndDensity[adr_000].xyz * ( a.x * a.y * a.z);
|
||||
velocity += gVelocityAndDensity[adr_100].xyz * (ma.x * a.y * a.z);
|
||||
velocity += gVelocityAndDensity[adr_010].xyz * ( a.x * ma.y * a.z);
|
||||
velocity += gVelocityAndDensity[adr_110].xyz * (ma.x * ma.y * a.z);
|
||||
velocity += gVelocityAndDensity[adr_000 + stride.z].xyz * ( a.x * a.y * ma.z);
|
||||
velocity += gVelocityAndDensity[adr_100 + stride.z].xyz * (ma.x * a.y * ma.z);
|
||||
velocity += gVelocityAndDensity[adr_010 + stride.z].xyz * ( a.x * ma.y * ma.z);
|
||||
velocity += gVelocityAndDensity[adr_110 + stride.z].xyz * (ma.x * ma.y * ma.z);
|
||||
|
||||
// Drive towards the average velocity of the cell
|
||||
ioVel.mVelocity += GradientSamplerSample(inMaterial.mGridVelocityFactor, inStrandFraction) * (velocity - ioVel.mVelocity);
|
||||
|
||||
// Calculate force to go towards neutral density
|
||||
// Based on eq 3 of Volumetric Methods for Simulation and Rendering of Hair - Lena Petrovic, Mark Henne and John Anderson
|
||||
float dd000 = DeltaDensity(adr_000);
|
||||
float dd100 = DeltaDensity(adr_100);
|
||||
float dd010 = DeltaDensity(adr_010);
|
||||
float dd110 = DeltaDensity(adr_110);
|
||||
float dd001 = DeltaDensity(adr_000 + stride.z);
|
||||
float dd101 = DeltaDensity(adr_100 + stride.z);
|
||||
float dd011 = DeltaDensity(adr_010 + stride.z);
|
||||
float dd111 = DeltaDensity(adr_110 + stride.z);
|
||||
|
||||
float3 force = float3(
|
||||
a.y * a.z * (dd000 - dd100)
|
||||
+ ma.y * a.z * (dd010 - dd110)
|
||||
+ a.y * ma.z * (dd001 - dd101)
|
||||
+ ma.y * ma.z * (dd011 - dd111),
|
||||
|
||||
a.x * a.z * (dd000 - dd010)
|
||||
+ ma.x * a.z * (dd100 - dd110)
|
||||
+ a.x * ma.z * (dd001 - dd011)
|
||||
+ ma.x * ma.z * (dd101 - dd111),
|
||||
|
||||
a.x * a.y * (dd000 - dd001)
|
||||
+ ma.x * a.y * (dd100 - dd101)
|
||||
+ a.x * ma.y * (dd010 - dd011)
|
||||
+ ma.x * ma.y * (dd110 - dd111));
|
||||
|
||||
ioVel.mVelocity += inMaterial.mGridDensityForceFactor * force * cDeltaTime; // / mass, but mass is 1
|
||||
}
|
||||
|
||||
void Integrate(JPH_IN_OUT(JPH_HairPosition) ioPos, JPH_IN(JPH_HairVelocity) inVel, JPH_IN(JPH_HairMaterial) inMaterial, float inStrandFraction)
|
||||
{
|
||||
JPH_HairVelocity vel = inVel;
|
||||
|
||||
// Gravity
|
||||
vel.mVelocity += cSubStepGravity * GradientSamplerSample(inMaterial.mGravityFactor, inStrandFraction);
|
||||
|
||||
// Damping
|
||||
vel.mVelocity *= inMaterial.mExpLinearDampingDeltaTime;
|
||||
vel.mAngularVelocity *= inMaterial.mExpAngularDampingDeltaTime;
|
||||
|
||||
// Integrate position
|
||||
ioPos.mPosition += vel.mVelocity * cDeltaTime;
|
||||
|
||||
// Integrate rotation
|
||||
JPH_Quat rotation = ioPos.mRotation;
|
||||
JPH_Quat delta_rotation = cHalfDeltaTime * JPH_QuatImaginaryMulQuat(vel.mAngularVelocity, rotation);
|
||||
ioPos.mRotation = normalize(rotation + delta_rotation);
|
||||
}
|
||||
35
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairIntegrate.hlsl
Normal file
35
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairIntegrate.hlsl
Normal file
@ -0,0 +1,35 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairIntegrateBindings.h"
|
||||
#include "HairCommon.h"
|
||||
#include "HairIntegrate.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x + cNumStrands; // Skip the root of each strand, it's fixed
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
if (IsVertexFixed(gVerticesFixed, vtx))
|
||||
return;
|
||||
|
||||
// Load the material
|
||||
uint strand_idx = vtx % cNumStrands;
|
||||
JPH_HairMaterial material = gMaterials[GetStrandMaterialIndex(gStrandMaterialIndex, strand_idx)];
|
||||
|
||||
// Load the vertex
|
||||
float strand_fraction = GetVertexStrandFraction(gStrandFractions, vtx);
|
||||
JPH_HairPosition pos = gPositions[vtx];
|
||||
JPH_HairVelocity vel = gVelocities[vtx];
|
||||
|
||||
// Update previous position
|
||||
gPreviousPositions[vtx] = pos;
|
||||
|
||||
ApplyGrid(pos, vel, material, strand_fraction);
|
||||
Integrate(pos, vel, material, strand_fraction);
|
||||
gPositions[vtx] = pos;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairIntegrate)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gVerticesFixed)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandFractions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float, gNeutralDensity)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float4, gVelocityAndDensity)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandMaterialIndex)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairMaterial, gMaterials)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairVelocity, gVelocities)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPreviousPositions)
|
||||
JPH_SHADER_BIND_END(JPH_HairIntegrate)
|
||||
50
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairSkinRoots.hlsl
Normal file
50
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairSkinRoots.hlsl
Normal file
@ -0,0 +1,50 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairSkinRootsBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerStrandBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid strand
|
||||
uint strand_idx = tid.x;
|
||||
if (strand_idx >= cNumStrands)
|
||||
return;
|
||||
|
||||
JPH_HairSkinPoint sp = gSkinPoints[strand_idx];
|
||||
|
||||
// Get the vertices of the attached triangle
|
||||
uint tri_idx = sp.mTriangleIndex * 3;
|
||||
float3 v0 = JPH_Mat44Mul3x3Vec3(cScalpToHead, gScalpVertices[gScalpTriangles[tri_idx + 0]]);
|
||||
float3 v1 = JPH_Mat44Mul3x3Vec3(cScalpToHead, gScalpVertices[gScalpTriangles[tri_idx + 1]]);
|
||||
float3 v2 = JPH_Mat44Mul3x3Vec3(cScalpToHead, gScalpVertices[gScalpTriangles[tri_idx + 2]]);
|
||||
|
||||
JPH_HairPosition root;
|
||||
|
||||
// Set the position of the root
|
||||
root.mPosition = sp.mU * v0 + sp.mV * v1 + (1.0f - sp.mU - sp.mV) * v2 + cScalpToHead[3].xyz;
|
||||
|
||||
// Get tangent vector
|
||||
float3 tangent = normalize(v1 - v0);
|
||||
|
||||
// Get normal of the triangle
|
||||
float3 normal = normalize(cross(tangent, v2 - v0));
|
||||
|
||||
// Calculate basis for the triangle
|
||||
float3 binormal = cross(tangent, normal);
|
||||
JPH_Quat triangle_basis = JPH_QuatFromMat33(normal, binormal, tangent);
|
||||
|
||||
// Calculate the new Bishop frame of the root
|
||||
root.mRotation = JPH_QuatMulQuat(triangle_basis, JPH_QuatDecompress(sp.mToBishop));
|
||||
|
||||
gPositions[strand_idx] = root;
|
||||
|
||||
// Calculate the transform that transforms the stored global pose to the space of the skinned root of the strand
|
||||
JPH_HairGlobalPoseTransform transform;
|
||||
transform.mRotation = JPH_QuatMulQuat(root.mRotation, JPH_QuatConjugate(JPH_QuatDecompress(gInitialBishops[strand_idx])));
|
||||
transform.mPosition = root.mPosition - JPH_QuatMulVec3(transform.mRotation, gInitialPositions[strand_idx]);
|
||||
gGlobalPoseTransforms[strand_idx] = transform;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
// Overridable input types
|
||||
#ifndef JPH_SHADER_BIND_SCALP_VERTICES
|
||||
#define JPH_SHADER_BIND_SCALP_VERTICES(name) JPH_SHADER_BIND_BUFFER(JPH_float3, name)
|
||||
#endif
|
||||
#ifndef JPH_SHADER_BIND_SCALP_TRIANGLES
|
||||
#define JPH_SHADER_BIND_SCALP_TRIANGLES(name) JPH_SHADER_BIND_BUFFER(JPH_uint, name)
|
||||
#endif
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairSkinRoots)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairSkinPoint, gSkinPoints)
|
||||
JPH_SHADER_BIND_SCALP_VERTICES(gScalpVertices)
|
||||
JPH_SHADER_BIND_SCALP_TRIANGLES(gScalpTriangles)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gInitialPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gInitialBishops)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairGlobalPoseTransform, gGlobalPoseTransforms)
|
||||
JPH_SHADER_BIND_END(JPH_HairSkinRoots)
|
||||
26
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairSkinVertices.hlsl
Normal file
26
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairSkinVertices.hlsl
Normal file
@ -0,0 +1,26 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairSkinVerticesBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x;
|
||||
if (vtx >= cNumSkinVertices)
|
||||
return;
|
||||
|
||||
// Skin the vertex
|
||||
float3 v = float3(0, 0, 0);
|
||||
for (uint w = vtx * cNumSkinWeightsPerVertex, w_end = w + cNumSkinWeightsPerVertex; w < w_end; ++w)
|
||||
{
|
||||
JPH_HairSkinWeight sw = gScalpSkinWeights[w];
|
||||
if (sw.mWeight > 0.0f)
|
||||
v += sw.mWeight * JPH_Mat44Mul3x4Vec3(gScalpJointMatrices[sw.mJointIdx], gScalpVertices[vtx]);
|
||||
}
|
||||
gScalpVerticesOut[vtx] = v;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairSkinVertices)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gScalpVertices)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairSkinWeight, gScalpSkinWeights)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_Mat44, gScalpJointMatrices)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_float3, gScalpVerticesOut)
|
||||
JPH_SHADER_BIND_END(JPH_HairSkinVertices)
|
||||
120
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairStructs.h
Normal file
120
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairStructs.h
Normal file
@ -0,0 +1,120 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "ShaderCore.h"
|
||||
|
||||
// Prevent including this file multiple times unless we're generating bindings
|
||||
#if !defined(HAIR_STRUCTS_H) || defined(JPH_SHADER_GENERATE_WRAPPER)
|
||||
#ifndef JPH_SHADER_GENERATE_WRAPPER
|
||||
#define HAIR_STRUCTS_H
|
||||
#endif
|
||||
|
||||
JPH_SUPPRESS_WARNING_PUSH
|
||||
JPH_SUPPRESS_WARNINGS
|
||||
|
||||
JPH_SHADER_CONSTANT(int, cHairPerVertexBatch, 64)
|
||||
JPH_SHADER_CONSTANT(int, cHairPerGridCellBatch, 32)
|
||||
JPH_SHADER_CONSTANT(int, cHairPerStrandBatch, 32)
|
||||
JPH_SHADER_CONSTANT(int, cHairPerRenderVertexBatch, 128)
|
||||
|
||||
JPH_SHADER_CONSTANT(int, cHairNumSVertexInfluences, 3)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairSkinWeight)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, JointIdx)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, Weight)
|
||||
JPH_SHADER_STRUCT_END(JPH_HairSkinWeight)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairSkinPoint)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, TriangleIndex) ///< Index of triangle in mScalpVertices to which this skin point is attached
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, U) ///< Barycentric u coordinate of skin point
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, V) ///< Barycentric v coordinate of skin point
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, ToBishop) ///< Compressed quaternion to rotate the frame defined by the triangle normal and the first edge to the Bishop frame of the first vertex of the strand
|
||||
JPH_SHADER_STRUCT_END(JPH_HairSkinPoint)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairGlobalPoseTransform)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, Position)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_Quat, Rotation)
|
||||
JPH_SHADER_STRUCT_END(JPH_HairGlobalPoseTransform)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairSVertexInfluence)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, VertexIndex) ///< Index in mSimVertices that indicates to which simulated vertex this vertex is attached.
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, RelativePosition) ///< Position in local space from the simulated vertex to the render vertex
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, Weight) ///< Influence weight, 0 = not attached, 1 = fully attached
|
||||
JPH_SHADER_STRUCT_END(JPH_HairSVertexInfluence)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairPosition)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, Position)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_Quat, Rotation)
|
||||
JPH_SHADER_STRUCT_END(JPH_HairPosition)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairVelocity)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, Velocity)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, AngularVelocity)
|
||||
JPH_SHADER_STRUCT_END(JPH_HairVelocity)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairMaterial)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float4, WorldTransformInfluence)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float4, GlobalPose)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float4, SkinGlobalPose)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float4, GravityFactor)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float4, HairRadius)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float4, BendComplianceMultiplier)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float4, GridVelocityFactor)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, EnableCollision)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, EnableLRA)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, EnableGrid)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, Friction)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, ExpLinearDampingDeltaTime)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, ExpAngularDampingDeltaTime)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, BendComplianceInvDeltaTimeSq)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, StretchComplianceInvDeltaTimeSq)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, GridDensityForceFactor)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, InertiaMultiplier)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, MaxLinearVelocitySq)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float, MaxAngularVelocitySq)
|
||||
JPH_SHADER_STRUCT_END(JPH_HairMaterial)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairCollisionPlane)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_Plane, Plane)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, ShapeIndex)
|
||||
JPH_SHADER_STRUCT_END(JPH_HairCollisionPlane)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(JPH_HairCollisionShape)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, CenterOfMass)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, LinearVelocity)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, AngularVelocity)
|
||||
JPH_SHADER_STRUCT_END(JPH_HairCollisionShape)
|
||||
|
||||
// Note: The order was chosen to match the struct between C++ and HLSL.
|
||||
JPH_SHADER_CONSTANTS_BEGIN(JPH_HairUpdateContext, gContext)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, NumStrands)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, NumVertices)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, NumGridPoints)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, NumRenderVertices)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint3, GridSizeMin2)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float, TwoDivDeltaTime)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float3, GridSizeMin1)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float, DeltaTime)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float3, GridOffset)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float, HalfDeltaTime)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float3, GridScale)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float, InvDeltaTimeSq)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float3, SubStepGravity)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, NumSkinVertices)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint3, GridStride)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, NumSkinWeightsPerVertex)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_Mat44, DeltaTransform)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_Mat44, ScalpToHead)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_Quat, DeltaTransformQuat)
|
||||
JPH_SHADER_CONSTANTS_END(JPH_HairUpdateContext)
|
||||
|
||||
// Note: The order was chosen to match the struct between C++ and HLSL.
|
||||
JPH_SHADER_CONSTANTS_BEGIN(JPH_HairIterationContext, gIterationContext)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float, AccumulatedDeltaTime) ///< = Iteration * DeltaTime
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float, IterationFraction) ///< = 1 / (NumIterations - Iteration) or the fraction to apply to get from current to target for this iteration step
|
||||
JPH_SHADER_CONSTANTS_END(JPH_HairIterationContext)
|
||||
|
||||
JPH_SUPPRESS_WARNING_POP
|
||||
|
||||
#endif // !defined(HAIR_STRUCTS_H) || defined(JPH_SHADER_GENERATE_WRAPPER)
|
||||
28
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairTeleport.hlsl
Normal file
28
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairTeleport.hlsl
Normal file
@ -0,0 +1,28 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairTeleportBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x;
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
|
||||
// Initialize position based on the initial vertex data
|
||||
JPH_HairPosition pos;
|
||||
pos.mPosition = gInitialPositions[vtx];
|
||||
pos.mRotation = JPH_QuatDecompress(gInitialBishops[vtx]);
|
||||
gPositions[vtx] = pos;
|
||||
|
||||
// Initialize velocity to zero
|
||||
JPH_HairVelocity vel;
|
||||
vel.mVelocity = float3(0, 0, 0);
|
||||
vel.mAngularVelocity = float3(0, 0, 0);
|
||||
gVelocities[vtx] = vel;
|
||||
}
|
||||
12
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairTeleportBindings.h
Normal file
12
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairTeleportBindings.h
Normal file
@ -0,0 +1,12 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairTeleport)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gInitialPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gInitialBishops)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairVelocity, gVelocities)
|
||||
JPH_SHADER_BIND_END(JPH_HairTeleport)
|
||||
30
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairUpdateRoots.hlsl
Normal file
30
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairUpdateRoots.hlsl
Normal file
@ -0,0 +1,30 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairUpdateRootsBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerStrandBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid strand
|
||||
uint strand_idx = tid.x;
|
||||
if (strand_idx >= cNumStrands)
|
||||
return;
|
||||
|
||||
float inv_fraction = 1.0f - cIterationFraction;
|
||||
|
||||
JPH_HairPosition pos = gPositions[strand_idx];
|
||||
JPH_HairPosition target_pos = gTargetPositions[strand_idx];
|
||||
pos.mPosition = pos.mPosition * inv_fraction + target_pos.mPosition * cIterationFraction;
|
||||
pos.mRotation = normalize(pos.mRotation * inv_fraction + target_pos.mRotation * cIterationFraction);
|
||||
gPositions[strand_idx] = pos;
|
||||
|
||||
JPH_HairGlobalPoseTransform transf = gGlobalPoseTransforms[strand_idx];
|
||||
JPH_HairGlobalPoseTransform target_transf = gTargetGlobalPoseTransforms[strand_idx];
|
||||
transf.mPosition = transf.mPosition * inv_fraction + target_transf.mPosition * cIterationFraction;
|
||||
transf.mRotation = normalize(transf.mRotation * inv_fraction + target_transf.mRotation * cIterationFraction);
|
||||
gGlobalPoseTransforms[strand_idx] = transf;
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairUpdateRoots)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairPosition, gTargetPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairGlobalPoseTransform, gTargetGlobalPoseTransforms)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairGlobalPoseTransform, gGlobalPoseTransforms)
|
||||
JPH_SHADER_BIND_END(JPH_HairUpdateRoots)
|
||||
154
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairUpdateStrands.hlsl
Normal file
154
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairUpdateStrands.hlsl
Normal file
@ -0,0 +1,154 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairUpdateStrandsBindings.h"
|
||||
#include "HairCommon.h"
|
||||
|
||||
void ApplyLRA(float3 inX0, float inMaxDist, JPH_IN_OUT(JPH_HairPosition) ioV0)
|
||||
{
|
||||
float3 delta = ioV0.mPosition - inX0;
|
||||
float delta_len_sq = dot(delta, delta);
|
||||
if (delta_len_sq > JPH_Square(inMaxDist))
|
||||
ioV0.mPosition = inX0 + delta * inMaxDist / sqrt(delta_len_sq);
|
||||
}
|
||||
|
||||
void ApplyStretchShear(JPH_IN_OUT(JPH_HairPosition) ioV0, JPH_IN_OUT(JPH_HairPosition) ioV1, float inLength01, float inInvMass0, float inInvMass1, JPH_IN(JPH_HairMaterial) inMaterial)
|
||||
{
|
||||
// Inertia of a thin rod of length L ~ m * L^2, we take the maximum mass of the two vertices
|
||||
float rod_inv_mass = min(inInvMass0, inInvMass1) / inMaterial.mInertiaMultiplier; // / L^2, which we'll apply later
|
||||
|
||||
// Equation 37 from "Position and Orientation Based Cosserat Rods" - Kugelstadt and Schoemer - SIGGRAPH 2016
|
||||
float denom = inInvMass0 + inInvMass1 + 4.0f * rod_inv_mass /* / L^2 * L^2 cancels */ + inMaterial.mStretchComplianceInvDeltaTimeSq;
|
||||
if (denom >= 1.0e-12f)
|
||||
{
|
||||
float3 x0 = ioV0.mPosition;
|
||||
float3 x1 = ioV1.mPosition;
|
||||
JPH_Quat rotation1 = ioV0.mRotation;
|
||||
float3 d3 = JPH_QuatRotateAxisZ(rotation1);
|
||||
float3 delta = (x1 - x0 - d3 * inLength01) / denom;
|
||||
ioV0.mPosition = x0 + inInvMass0 * delta;
|
||||
ioV1.mPosition = x1 - inInvMass1 * delta;
|
||||
// q * e3_bar = q * (0, 0, -1, 0) = [-qy, qx, -qw, qz]
|
||||
JPH_Quat q_e3_bar = JPH_Quat(-rotation1.y, rotation1.x, -rotation1.w, rotation1.z);
|
||||
rotation1 += (2.0f * rod_inv_mass / inLength01 /* / L^2 * L => / L */) * JPH_QuatImaginaryMulQuat(delta, q_e3_bar);
|
||||
ioV0.mRotation = normalize(rotation1);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyBendTwist(JPH_IN_OUT(JPH_HairPosition) ioV0, JPH_IN_OUT(JPH_HairPosition) ioV1, JPH_Quat inOmega0, float inLength01, float inLength12, float inStrandFraction1, float inInvMass0, float inInvMass1, float inInvMass2, JPH_IN(JPH_HairMaterial) inMaterial)
|
||||
{
|
||||
// Inertia of a thin rod of length L ~ m * L^2, we take the maximum mass of the two vertices
|
||||
float rod_inv_mass = min(inInvMass0, inInvMass1) / (inMaterial.mInertiaMultiplier * JPH_Square(inLength01));
|
||||
float rod2_inv_mass = min(inInvMass1, inInvMass2) / (inMaterial.mInertiaMultiplier * JPH_Square(inLength12));
|
||||
|
||||
// Calculate multiplier for the bend compliance based on strand fraction
|
||||
float fraction = inStrandFraction1 * 3.0f;
|
||||
uint idx = uint(fraction);
|
||||
fraction = fraction - float(idx);
|
||||
float multiplier = inMaterial.mBendComplianceMultiplier[idx] * (1.0f - fraction) + inMaterial.mBendComplianceMultiplier[idx + 1] * fraction;
|
||||
|
||||
// Equation 40 from "Position and Orientation Based Cosserat Rods" - Kugelstadt and Schoemer - SIGGRAPH 2016
|
||||
float denom = rod_inv_mass + rod2_inv_mass + inMaterial.mBendComplianceInvDeltaTimeSq * multiplier;
|
||||
if (denom >= 1.0e-12f)
|
||||
{
|
||||
JPH_Quat rotation1 = ioV0.mRotation;
|
||||
JPH_Quat rotation2 = ioV1.mRotation;
|
||||
JPH_Quat omega = JPH_QuatMulQuat(JPH_QuatConjugate(rotation1), rotation2);
|
||||
JPH_Quat omega_min_omega0 = omega - inOmega0;
|
||||
JPH_Quat omega_plus_omega0 = omega + inOmega0;
|
||||
// Take the shortest of the two rotations
|
||||
JPH_Quat delta_omega = dot(omega_plus_omega0, omega_plus_omega0) < dot(omega_min_omega0, omega_min_omega0) ? omega_plus_omega0 : omega_min_omega0;
|
||||
delta_omega /= denom;
|
||||
delta_omega.w = 0; // Scalar part needs to be zero because the real part of the Darboux vector doesn't vanish, see text between eq. 39 and 40.
|
||||
JPH_Quat delta_rod2 = rod2_inv_mass * JPH_QuatMulQuat(rotation1, delta_omega);
|
||||
rotation1 += rod_inv_mass * JPH_QuatMulQuat(rotation2, delta_omega);
|
||||
rotation2 -= delta_rod2;
|
||||
ioV0.mRotation = normalize(rotation1);
|
||||
ioV1.mRotation = normalize(rotation2);
|
||||
}
|
||||
}
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerStrandBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid strand
|
||||
uint strand_idx = tid.x;
|
||||
if (strand_idx >= cNumStrands)
|
||||
return;
|
||||
uint strand_vtx_count = GetStrandVertexCount(gStrandVertexCounts, strand_idx);
|
||||
|
||||
// Load the material
|
||||
JPH_HairMaterial material = gMaterials[GetStrandMaterialIndex(gStrandMaterialIndex, strand_idx)];
|
||||
|
||||
// Load the first two vertices
|
||||
uint vtx_idx_to_load = strand_idx;
|
||||
float inv_mass0 = GetVertexInvMass(gVerticesFixed, vtx_idx_to_load);
|
||||
float length0 = gInitialLengths[vtx_idx_to_load];
|
||||
JPH_HairPosition v0 = gPositions[vtx_idx_to_load];
|
||||
|
||||
// LRA: Vertex everything is attached to
|
||||
float3 x0 = gInitialPositions[vtx_idx_to_load];
|
||||
|
||||
// LRA: Tracks the distance from the first vertex
|
||||
float max_dist = length0;
|
||||
|
||||
vtx_idx_to_load += cNumStrands;
|
||||
float inv_mass1 = GetVertexInvMass(gVerticesFixed, vtx_idx_to_load);
|
||||
float strand_fraction1 = GetVertexStrandFraction(gStrandFractions, vtx_idx_to_load);
|
||||
float length1 = gInitialLengths[vtx_idx_to_load];
|
||||
JPH_HairPosition v1 = gPositions[vtx_idx_to_load];
|
||||
|
||||
// Process 2nd vertex
|
||||
if (material.mEnableLRA && inv_mass1 > 0.0f)
|
||||
ApplyLRA(x0, max_dist, v1);
|
||||
max_dist += length1;
|
||||
|
||||
uint vtx_idx_to_retire = strand_idx;
|
||||
for (uint vtx = 2; vtx < strand_vtx_count; ++vtx)
|
||||
{
|
||||
// Get the initial rotation difference from the middle vertex
|
||||
JPH_Quat omega0 = JPH_QuatDecompress(gOmega0s[vtx_idx_to_load]);
|
||||
|
||||
// Load the next vertex
|
||||
vtx_idx_to_load += cNumStrands;
|
||||
float inv_mass2 = GetVertexInvMass(gVerticesFixed, vtx_idx_to_load);
|
||||
float strand_fraction2 = GetVertexStrandFraction(gStrandFractions, vtx_idx_to_load);
|
||||
float length2 = gInitialLengths[vtx_idx_to_load];
|
||||
JPH_HairPosition v2 = gPositions[vtx_idx_to_load];
|
||||
|
||||
// Process newly added vertex
|
||||
if (material.mEnableLRA && inv_mass2 > 0.0f)
|
||||
ApplyLRA(x0, max_dist, v2);
|
||||
max_dist += length2;
|
||||
|
||||
// Stitched mode as per Strand-based Hair System - Pedersen - SIGGRAPH 2022
|
||||
ApplyStretchShear(v1, v2, length1, inv_mass1, inv_mass2, material);
|
||||
ApplyStretchShear(v0, v1, length0, inv_mass0, inv_mass1, material);
|
||||
ApplyBendTwist(v0, v1, omega0, length0, length1, strand_fraction1, inv_mass0, inv_mass1, inv_mass2, material);
|
||||
|
||||
// Retire vertex
|
||||
gPositions[vtx_idx_to_retire] = v0;
|
||||
vtx_idx_to_retire += cNumStrands;
|
||||
|
||||
// Shift the vertices
|
||||
inv_mass0 = inv_mass1;
|
||||
inv_mass1 = inv_mass2;
|
||||
strand_fraction1 = strand_fraction2;
|
||||
length0 = length1;
|
||||
length1 = length2;
|
||||
v0 = v1;
|
||||
v1 = v2;
|
||||
}
|
||||
|
||||
// Retire 2nd to last vertex
|
||||
gPositions[vtx_idx_to_retire] = v0;
|
||||
vtx_idx_to_retire += cNumStrands;
|
||||
|
||||
// Cannot calculate rotation for last vertex, take the 2nd last
|
||||
v1.mRotation = v0.mRotation;
|
||||
|
||||
// Retire last vertex
|
||||
gPositions[vtx_idx_to_retire] = v1;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairUpdateStrands)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gVerticesFixed)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandFractions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gInitialPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gOmega0s)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float, gInitialLengths)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandVertexCounts)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandMaterialIndex)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairMaterial, gMaterials)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_END(JPH_HairUpdateStrands)
|
||||
64
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairUpdateVelocity.h
Normal file
64
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairUpdateVelocity.h
Normal file
@ -0,0 +1,64 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairApplyGlobalPose.h"
|
||||
|
||||
void ApplyCollisionAndUpdateVelocity(uint inVtx, JPH_IN_OUT(JPH_HairPosition) ioPos, JPH_IN(JPH_HairPosition) inPreviousPos, JPH_IN(JPH_HairMaterial) inMaterial, float inStrandFraction, JPH_OUT(JPH_HairVelocity) outVel)
|
||||
{
|
||||
// Update velocities
|
||||
outVel.mVelocity = (ioPos.mPosition - inPreviousPos.mPosition) / cDeltaTime;
|
||||
outVel.mAngularVelocity = cTwoDivDeltaTime * JPH_QuatMulQuat(ioPos.mRotation, JPH_QuatConjugate(inPreviousPos.mRotation)).xyz;
|
||||
|
||||
if (inMaterial.mEnableCollision)
|
||||
{
|
||||
// Calculate closest point on the collision plane
|
||||
JPH_HairCollisionPlane plane = gCollisionPlanes[inVtx];
|
||||
float distance_to_plane = JPH_PlaneSignedDistance(plane.mPlane, ioPos.mPosition);
|
||||
float3 contact_normal = JPH_PlaneGetNormal(plane.mPlane);
|
||||
float3 point_on_plane = ioPos.mPosition - distance_to_plane * contact_normal;
|
||||
|
||||
// Calculate how much the plane moved in this time step
|
||||
JPH_HairCollisionShape shape = gCollisionShapes[plane.mShapeIndex];
|
||||
float3 plane_velocity = shape.mLinearVelocity + cross(shape.mAngularVelocity, point_on_plane - shape.mCenterOfMass);
|
||||
float plane_movement = dot(plane_velocity, contact_normal) * cAccumulatedDeltaTime;
|
||||
|
||||
float projected_distance = -distance_to_plane + plane_movement + GradientSamplerSample(inMaterial.mHairRadius, inStrandFraction);
|
||||
if (projected_distance > 0.0f)
|
||||
{
|
||||
// Resolve penetration
|
||||
ioPos.mPosition += contact_normal * projected_distance;
|
||||
|
||||
// Only update velocity when moving towards each other
|
||||
float3 v_relative = outVel.mVelocity - plane_velocity;
|
||||
float v_relative_dot_normal = dot(contact_normal, v_relative);
|
||||
if (v_relative_dot_normal < 0.0f)
|
||||
{
|
||||
// Calculate normal and tangential velocity (equation 30)
|
||||
float3 v_normal = contact_normal * v_relative_dot_normal;
|
||||
float3 v_tangential = v_relative - v_normal;
|
||||
float v_tangential_length = length(v_tangential);
|
||||
|
||||
// Apply friction as described in Detailed Rigid Body Simulation with Extended Position Based Dynamics - Matthias Muller et al. (modified equation 31)
|
||||
if (v_tangential_length > 0.0f)
|
||||
outVel.mVelocity -= v_tangential * min(inMaterial.mFriction * projected_distance / (v_tangential_length * cDeltaTime), 1.0f);
|
||||
|
||||
// Apply restitution of zero (equation 35)
|
||||
outVel.mVelocity -= v_normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LimitVelocity(JPH_IN_OUT(JPH_HairVelocity) ioVel, JPH_IN(JPH_HairMaterial) inMaterial)
|
||||
{
|
||||
// Limit linear velocity
|
||||
float linear_velocity_sq = dot(ioVel.mVelocity, ioVel.mVelocity);
|
||||
if (linear_velocity_sq > inMaterial.mMaxLinearVelocitySq)
|
||||
ioVel.mVelocity *= sqrt(inMaterial.mMaxLinearVelocitySq / linear_velocity_sq);
|
||||
|
||||
// Limit angular velocity
|
||||
float angular_velocity_sq = dot(ioVel.mAngularVelocity, ioVel.mAngularVelocity);
|
||||
if (angular_velocity_sq > inMaterial.mMaxAngularVelocitySq)
|
||||
ioVel.mAngularVelocity *= sqrt(inMaterial.mMaxAngularVelocitySq / angular_velocity_sq);
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairUpdateVelocityBindings.h"
|
||||
#include "HairCommon.h"
|
||||
#include "HairUpdateVelocity.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x + cNumStrands; // Skip the root of each strand, it's fixed
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
if (IsVertexFixed(gVerticesFixed, vtx))
|
||||
return;
|
||||
|
||||
// Load the material
|
||||
uint strand_idx = vtx % cNumStrands;
|
||||
JPH_HairMaterial material = gMaterials[GetStrandMaterialIndex(gStrandMaterialIndex, strand_idx)];
|
||||
|
||||
// Load the vertex
|
||||
float strand_fraction = GetVertexStrandFraction(gStrandFractions, vtx);
|
||||
float3 initial_pos = gInitialPositions[vtx];
|
||||
float4 initial_bishop = JPH_QuatDecompress(gInitialBishops[vtx]);
|
||||
JPH_HairGlobalPoseTransform global_pose_transform = gGlobalPoseTransforms[strand_idx];
|
||||
JPH_HairPosition pos = gPositions[vtx];
|
||||
JPH_HairPosition prev_pos = gPreviousPositions[vtx];
|
||||
|
||||
JPH_HairVelocity vel;
|
||||
ApplyGlobalPose(pos, initial_pos, initial_bishop, global_pose_transform, material, strand_fraction);
|
||||
ApplyCollisionAndUpdateVelocity(vtx, pos, prev_pos, material, strand_fraction, vel);
|
||||
LimitVelocity(vel, material);
|
||||
|
||||
// Write back vertex
|
||||
gPositions[vtx] = pos;
|
||||
gVelocities[vtx] = vel;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairUpdateVelocity)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gVerticesFixed)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandFractions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gInitialPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gInitialBishops)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandMaterialIndex)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairMaterial, gMaterials)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairPosition, gPreviousPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairGlobalPoseTransform, gGlobalPoseTransforms)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairCollisionShape, gCollisionShapes)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairCollisionPlane, gCollisionPlanes)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairVelocity, gVelocities)
|
||||
JPH_SHADER_BIND_END(JPH_HairUpdateVelocity)
|
||||
@ -0,0 +1,44 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairUpdateVelocityIntegrateBindings.h"
|
||||
#include "HairCommon.h"
|
||||
#include "HairIntegrate.h"
|
||||
#include "HairUpdateVelocity.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cHairPerVertexBatch, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Check if this is a valid vertex
|
||||
uint vtx = tid.x + cNumStrands; // Skip the root of each strand, it's fixed
|
||||
if (vtx >= cNumVertices)
|
||||
return;
|
||||
if (IsVertexFixed(gVerticesFixed, vtx))
|
||||
return;
|
||||
|
||||
// Load the material
|
||||
uint strand_idx = vtx % cNumStrands;
|
||||
JPH_HairMaterial material = gMaterials[GetStrandMaterialIndex(gStrandMaterialIndex, strand_idx)];
|
||||
|
||||
// Load the vertex
|
||||
float strand_fraction = GetVertexStrandFraction(gStrandFractions, vtx);
|
||||
float3 initial_pos = gInitialPositions[vtx];
|
||||
float4 initial_bishop = JPH_QuatDecompress(gInitialBishops[vtx]);
|
||||
JPH_HairGlobalPoseTransform global_pose_transform = gGlobalPoseTransforms[strand_idx];
|
||||
JPH_HairPosition pos = gPositions[vtx];
|
||||
JPH_HairPosition prev_pos = gPreviousPositions[vtx];
|
||||
|
||||
// HairUpdateVelocity shader
|
||||
JPH_HairVelocity vel; // Keeps velocity as a local variable
|
||||
ApplyGlobalPose(pos, initial_pos, initial_bishop, global_pose_transform, material, strand_fraction);
|
||||
ApplyCollisionAndUpdateVelocity(vtx, pos, prev_pos, material, strand_fraction, vel);
|
||||
LimitVelocity(vel, material);
|
||||
|
||||
// HairIntegrate shader
|
||||
gPreviousPositions[vtx] = pos;
|
||||
ApplyGrid(pos, vel, material, strand_fraction);
|
||||
Integrate(pos, vel, material, strand_fraction);
|
||||
gPositions[vtx] = pos;
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "HairStructs.h"
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_HairUpdateVelocityIntegrate)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gVerticesFixed)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandFractions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float3, gInitialPositions)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gInitialBishops)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float, gNeutralDensity)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_float4, gVelocityAndDensity)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gStrandMaterialIndex)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairMaterial, gMaterials)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairGlobalPoseTransform, gGlobalPoseTransforms)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairCollisionShape, gCollisionShapes)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_HairCollisionPlane, gCollisionPlanes)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPreviousPositions)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_HairPosition, gPositions)
|
||||
JPH_SHADER_BIND_END(JPH_HairUpdateVelocityIntegrate)
|
||||
139
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairWrapper.cpp
Normal file
139
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairWrapper.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#ifdef JPH_USE_CPU_COMPUTE
|
||||
|
||||
#include <Jolt/Shaders/HairWrapper.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairTeleport
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairTeleport.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairTeleportBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairApplyDeltaTransform
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairApplyDeltaTransform.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairApplyDeltaTransformBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairSkinVertices
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairSkinVertices.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairSkinVerticesBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairSkinRoots
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairSkinRoots.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairSkinRootsBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairApplyGlobalPose
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairApplyGlobalPose.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairApplyGlobalPoseBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairCalculateCollisionPlanes
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairCalculateCollisionPlanes.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairCalculateCollisionPlanesBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairGridClear
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairGridClear.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairGridClearBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairGridAccumulate
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairGridAccumulate.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairGridAccumulateBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairGridNormalize
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairGridNormalize.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairGridNormalizeBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairIntegrate
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairIntegrate.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairIntegrateBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairUpdateRoots
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairUpdateRoots.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairUpdateRootsBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairUpdateStrands
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairUpdateStrands.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairUpdateStrandsBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairUpdateVelocity
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairUpdateVelocity.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairUpdateVelocityBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairUpdateVelocityIntegrate
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairUpdateVelocityIntegrate.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairUpdateVelocityIntegrateBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME HairCalculateRenderPositions
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "HairCalculateRenderPositions.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "HairCalculateRenderPositionsBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
void JPH_EXPORT HairRegisterShaders(ComputeSystemCPU *inComputeSystem)
|
||||
{
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairTeleport);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairApplyDeltaTransform);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairSkinVertices);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairSkinRoots);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairApplyGlobalPose);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairCalculateCollisionPlanes);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairGridClear);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairGridAccumulate);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairGridNormalize);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairIntegrate);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairUpdateRoots);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairUpdateStrands);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairUpdateVelocity);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairUpdateVelocityIntegrate);
|
||||
JPH_REGISTER_SHADER(inComputeSystem, HairCalculateRenderPositions);
|
||||
}
|
||||
|
||||
JPH_NAMESPACE_END
|
||||
|
||||
#endif // JPH_USE_CPU_COMPUTE
|
||||
17
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairWrapper.h
Normal file
17
lib/haxejolt/JoltPhysics/Jolt/Shaders/HairWrapper.h
Normal file
@ -0,0 +1,17 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef JPH_USE_CPU_COMPUTE
|
||||
|
||||
JPH_NAMESPACE_BEGIN
|
||||
|
||||
class ComputeSystemCPU;
|
||||
|
||||
void JPH_EXPORT HairRegisterShaders(ComputeSystemCPU *inComputeSystem);
|
||||
|
||||
JPH_NAMESPACE_END
|
||||
|
||||
#endif // JPH_USE_CPU_COMPUTE
|
||||
85
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderCore.h
Normal file
85
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderCore.h
Normal file
@ -0,0 +1,85 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef JPH_SHADER_OVERRIDE_MACROS
|
||||
|
||||
#ifdef __cplusplus
|
||||
JPH_SUPPRESS_WARNING_PUSH
|
||||
JPH_SUPPRESS_WARNINGS
|
||||
|
||||
using JPH_float = float;
|
||||
using JPH_float3 = JPH::Float3;
|
||||
using JPH_float4 = JPH::Float4;
|
||||
using JPH_uint = JPH::uint32;
|
||||
using JPH_uint3 = JPH::uint32[3];
|
||||
using JPH_uint4 = JPH::uint32[4];
|
||||
using JPH_int = int;
|
||||
using JPH_int3 = int[3];
|
||||
using JPH_int4 = int[4];
|
||||
using JPH_Quat = JPH::Float4;
|
||||
using JPH_Plane = JPH::Float4;
|
||||
using JPH_Mat44 = JPH::Float4[4]; // matrix, column major
|
||||
|
||||
#define JPH_SHADER_CONSTANT(type, name, value) constexpr type name = value;
|
||||
|
||||
#define JPH_SHADER_CONSTANTS_BEGIN(type, name) struct type {
|
||||
#define JPH_SHADER_CONSTANTS_MEMBER(type, name) type c##name;
|
||||
#define JPH_SHADER_CONSTANTS_END(type) };
|
||||
|
||||
#define JPH_SHADER_BIND_BEGIN(name)
|
||||
#define JPH_SHADER_BIND_END(name)
|
||||
#define JPH_SHADER_BIND_BUFFER(type, name)
|
||||
#define JPH_SHADER_BIND_RW_BUFFER(type, name)
|
||||
|
||||
JPH_SUPPRESS_WARNING_POP
|
||||
#else
|
||||
#define JPH_SUPPRESS_WARNING_PUSH
|
||||
#define JPH_SUPPRESS_WARNING_POP
|
||||
#define JPH_SUPPRESS_WARNINGS
|
||||
|
||||
typedef float JPH_float;
|
||||
typedef float3 JPH_float3;
|
||||
typedef float4 JPH_float4;
|
||||
typedef uint JPH_uint;
|
||||
typedef uint3 JPH_uint3;
|
||||
typedef uint4 JPH_uint4;
|
||||
typedef int JPH_int;
|
||||
typedef int3 JPH_int3;
|
||||
typedef int4 JPH_int4;
|
||||
typedef float4 JPH_Quat; // xyz = imaginary part, w = real part
|
||||
typedef float4 JPH_Plane; // xyz = normal, w = constant
|
||||
typedef float4 JPH_Mat44[4]; // matrix, column major
|
||||
|
||||
#define JPH_SHADER_CONSTANT(type, name, value) static const type name = value;
|
||||
|
||||
#define JPH_SHADER_CONSTANTS_BEGIN(type, name) cbuffer name {
|
||||
#define JPH_SHADER_CONSTANTS_MEMBER(type, name) type c##name;
|
||||
#define JPH_SHADER_CONSTANTS_END(type) };
|
||||
|
||||
#define JPH_SHADER_FUNCTION_BEGIN(return_type, name, group_size_x, group_size_y, group_size_z) \
|
||||
[numthreads(group_size_x, group_size_y, group_size_z)] \
|
||||
return_type name(
|
||||
#define JPH_SHADER_PARAM_THREAD_ID(name) uint3 name : SV_DispatchThreadID
|
||||
#define JPH_SHADER_FUNCTION_END )
|
||||
|
||||
#define JPH_SHADER_BUFFER(type) StructuredBuffer<type>
|
||||
#define JPH_SHADER_RW_BUFFER(type) RWStructuredBuffer<type>
|
||||
|
||||
#define JPH_SHADER_BIND_BEGIN(name)
|
||||
#define JPH_SHADER_BIND_END(name)
|
||||
#define JPH_SHADER_BIND_BUFFER(type, name) JPH_SHADER_BUFFER(type) name;
|
||||
#define JPH_SHADER_BIND_RW_BUFFER(type, name) JPH_SHADER_RW_BUFFER(type) name;
|
||||
|
||||
#define JPH_AtomicAdd InterlockedAdd
|
||||
#endif
|
||||
|
||||
#define JPH_SHADER_STRUCT_BEGIN(name) struct name {
|
||||
#define JPH_SHADER_STRUCT_MEMBER(type, name) type m##name;
|
||||
#define JPH_SHADER_STRUCT_END(name) };
|
||||
|
||||
#define JPH_IN(type) in type
|
||||
#define JPH_OUT(type) out type
|
||||
#define JPH_IN_OUT(type) in out type
|
||||
|
||||
#endif // JPH_OVERRIDE_SHADER_MACROS
|
||||
13
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderMat44.h
Normal file
13
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderMat44.h
Normal file
@ -0,0 +1,13 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
inline float3 JPH_Mat44Mul3x4Vec3(JPH_Mat44 inLHS, float3 inRHS)
|
||||
{
|
||||
return inLHS[0].xyz * inRHS.x + inLHS[1].xyz * inRHS.y + inLHS[2].xyz * inRHS.z + inLHS[3].xyz;
|
||||
}
|
||||
|
||||
inline float3 JPH_Mat44Mul3x3Vec3(JPH_Mat44 inLHS, float3 inRHS)
|
||||
{
|
||||
return inLHS[0].xyz * inRHS.x + inLHS[1].xyz * inRHS.y + inLHS[2].xyz * inRHS.z;
|
||||
}
|
||||
16
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderMath.h
Normal file
16
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderMath.h
Normal file
@ -0,0 +1,16 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Calculate inValue^2
|
||||
inline float JPH_Square(float inValue)
|
||||
{
|
||||
return inValue * inValue;
|
||||
}
|
||||
|
||||
// Get the closest point on a line segment defined by inA + x * inAB for x e [0, 1] to the origin
|
||||
inline float3 JPH_GetClosestPointOnLine(float3 inA, float3 inAB)
|
||||
{
|
||||
float v = clamp(-dot(inA, inAB) / dot(inAB, inAB), 0.0f, 1.0f);
|
||||
return inA + v * inAB;
|
||||
}
|
||||
18
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderPlane.h
Normal file
18
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderPlane.h
Normal file
@ -0,0 +1,18 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
JPH_Plane JPH_PlaneFromPointAndNormal(float3 inPoint, float3 inNormal)
|
||||
{
|
||||
return JPH_Plane(inNormal, -dot(inNormal, inPoint));
|
||||
}
|
||||
|
||||
float3 JPH_PlaneGetNormal(JPH_Plane inPlane)
|
||||
{
|
||||
return inPlane.xyz;
|
||||
}
|
||||
|
||||
float JPH_PlaneSignedDistance(JPH_Plane inPlane, float3 inPoint)
|
||||
{
|
||||
return dot(inPoint, inPlane.xyz) + inPlane.w;
|
||||
}
|
||||
114
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderQuat.h
Normal file
114
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderQuat.h
Normal file
@ -0,0 +1,114 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
inline float3 JPH_QuatMulVec3(JPH_Quat inLHS, float3 inRHS)
|
||||
{
|
||||
float3 v_xyz = inLHS.xyz;
|
||||
float3 v_yzx = inLHS.yzx;
|
||||
float3 q_cross_p = (inRHS.yzx * v_xyz - v_yzx * inRHS).yzx;
|
||||
float3 q_cross_q_cross_p = (q_cross_p.yzx * v_xyz - v_yzx * q_cross_p).yzx;
|
||||
float3 v = inLHS.w * q_cross_p + q_cross_q_cross_p;
|
||||
return inRHS + (v + v);
|
||||
}
|
||||
|
||||
inline JPH_Quat JPH_QuatMulQuat(JPH_Quat inLHS, JPH_Quat inRHS)
|
||||
{
|
||||
float x = inLHS.w * inRHS.x + inLHS.x * inRHS.w + inLHS.y * inRHS.z - inLHS.z * inRHS.y;
|
||||
float y = inLHS.w * inRHS.y - inLHS.x * inRHS.z + inLHS.y * inRHS.w + inLHS.z * inRHS.x;
|
||||
float z = inLHS.w * inRHS.z + inLHS.x * inRHS.y - inLHS.y * inRHS.x + inLHS.z * inRHS.w;
|
||||
float w = inLHS.w * inRHS.w - inLHS.x * inRHS.x - inLHS.y * inRHS.y - inLHS.z * inRHS.z;
|
||||
return JPH_Quat(x, y, z, w);
|
||||
}
|
||||
|
||||
inline JPH_Quat JPH_QuatImaginaryMulQuat(float3 inLHS, JPH_Quat inRHS)
|
||||
{
|
||||
float x = +inLHS.x * inRHS.w + inLHS.y * inRHS.z - inLHS.z * inRHS.y;
|
||||
float y = -inLHS.x * inRHS.z + inLHS.y * inRHS.w + inLHS.z * inRHS.x;
|
||||
float z = +inLHS.x * inRHS.y - inLHS.y * inRHS.x + inLHS.z * inRHS.w;
|
||||
float w = -inLHS.x * inRHS.x - inLHS.y * inRHS.y - inLHS.z * inRHS.z;
|
||||
return JPH_Quat(x, y, z, w);
|
||||
}
|
||||
|
||||
inline float3 JPH_QuatRotateAxisZ(JPH_Quat inRotation)
|
||||
{
|
||||
return (inRotation.z + inRotation.z) * inRotation.xyz + (inRotation.w + inRotation.w) * float3(inRotation.y, -inRotation.x, inRotation.w) - float3(0, 0, 1);
|
||||
}
|
||||
|
||||
inline JPH_Quat JPH_QuatConjugate(JPH_Quat inRotation)
|
||||
{
|
||||
return JPH_Quat(-inRotation.x, -inRotation.y, -inRotation.z, inRotation.w);
|
||||
}
|
||||
|
||||
inline JPH_Quat JPH_QuatDecompress(uint inValue)
|
||||
{
|
||||
const float cOneOverSqrt2 = 0.70710678f;
|
||||
const uint cNumBits = 9;
|
||||
const uint cMask = (1u << cNumBits) - 1;
|
||||
const uint cMaxValue = cMask - 1; // Need odd number of buckets to quantize to or else we can't encode 0
|
||||
const float cScale = 2.0f * cOneOverSqrt2 / float(cMaxValue);
|
||||
|
||||
// Restore two components
|
||||
float3 v3 = float3(float(inValue & cMask), float((inValue >> cNumBits) & cMask), float((inValue >> (2 * cNumBits)) & cMask)) * cScale - float3(cOneOverSqrt2, cOneOverSqrt2, cOneOverSqrt2);
|
||||
|
||||
// Restore the highest component
|
||||
float4 v = float4(v3, sqrt(max(1.0f - dot(v3, v3), 0.0f)));
|
||||
|
||||
// Extract sign
|
||||
if ((inValue & 0x80000000u) != 0)
|
||||
v = -v;
|
||||
|
||||
// Swizzle the components in place
|
||||
uint max_element = (inValue >> 29) & 3;
|
||||
v = max_element == 0? v.wxyz : (max_element == 1? v.xwyz : (max_element == 2? v.xywz : v));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
inline JPH_Quat JPH_QuatFromMat33(float3 inCol0, float3 inCol1, float3 inCol2)
|
||||
{
|
||||
float tr = inCol0.x + inCol1.y + inCol2.z;
|
||||
if (tr >= 0.0f)
|
||||
{
|
||||
float s = sqrt(tr + 1.0f);
|
||||
float is = 0.5f / s;
|
||||
return JPH_Quat(
|
||||
(inCol1.z - inCol2.y) * is,
|
||||
(inCol2.x - inCol0.z) * is,
|
||||
(inCol0.y - inCol1.x) * is,
|
||||
0.5f * s);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inCol0.x > inCol1.y && inCol0.x > inCol2.z)
|
||||
{
|
||||
float s = sqrt(inCol0.x - (inCol1.y + inCol2.z) + 1);
|
||||
float is = 0.5f / s;
|
||||
return JPH_Quat(
|
||||
0.5f * s,
|
||||
(inCol1.x + inCol0.y) * is,
|
||||
(inCol0.z + inCol2.x) * is,
|
||||
(inCol1.z - inCol2.y) * is);
|
||||
}
|
||||
else if (inCol1.y > inCol2.z)
|
||||
{
|
||||
float s = sqrt(inCol1.y - (inCol2.z + inCol0.x) + 1);
|
||||
float is = 0.5f / s;
|
||||
return JPH_Quat(
|
||||
(inCol1.x + inCol0.y) * is,
|
||||
0.5f * s,
|
||||
(inCol2.y + inCol1.z) * is,
|
||||
(inCol2.x - inCol0.z) * is);
|
||||
}
|
||||
else
|
||||
{
|
||||
float s = sqrt(inCol2.z - (inCol0.x + inCol1.y) + 1);
|
||||
float is = 0.5f / s;
|
||||
return JPH_Quat(
|
||||
(inCol0.z + inCol2.x) * is,
|
||||
(inCol2.y + inCol1.z) * is,
|
||||
0.5f * s,
|
||||
(inCol0.y - inCol1.x) * is);
|
||||
}
|
||||
}
|
||||
}
|
||||
28
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderVec3.h
Normal file
28
lib/haxejolt/JoltPhysics/Jolt/Shaders/ShaderVec3.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
inline float3 JPH_Vec3DecompressUnit(uint inValue)
|
||||
{
|
||||
const float cOneOverSqrt2 = 0.70710678f;
|
||||
const uint cNumBits = 14;
|
||||
const uint cMask = (1u << cNumBits) - 1;
|
||||
const uint cMaxValue = cMask - 1; // Need odd number of buckets to quantize to or else we can't encode 0
|
||||
const float cScale = 2.0f * cOneOverSqrt2 / float(cMaxValue);
|
||||
|
||||
// Restore two components
|
||||
float2 v2 = float2(float(inValue & cMask), float((inValue >> cNumBits) & cMask)) * cScale - float2(cOneOverSqrt2, cOneOverSqrt2);
|
||||
|
||||
// Restore the highest component
|
||||
float3 v = float3(v2, sqrt(max(1.0f - dot(v2, v2), 0.0f)));
|
||||
|
||||
// Extract sign
|
||||
if ((inValue & 0x80000000u) != 0)
|
||||
v = -v;
|
||||
|
||||
// Swizzle the components in place
|
||||
uint max_element = (inValue >> 29) & 3;
|
||||
v = max_element == 0? v.zxy : (max_element == 1? v.xzy : v);
|
||||
|
||||
return v;
|
||||
}
|
||||
25
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestCompute.hlsl
Normal file
25
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestCompute.hlsl
Normal file
@ -0,0 +1,25 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "TestComputeBindings.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cTestComputeGroupSize, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
// Ensure that we do not write out of bounds
|
||||
if (tid.x >= cNumElements)
|
||||
return;
|
||||
|
||||
if (cUIntValue2 == 0)
|
||||
{
|
||||
// First write, uses optional data and tests that the packing of float3/uint3's works
|
||||
gData[tid.x] = gOptionalData[tid.x] + int(cFloat3Value2.y) + gUploadData[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read-modify-write gData
|
||||
gData[tid.x] = (gData[tid.x] + cUIntValue) * cUIntValue2;
|
||||
}
|
||||
}
|
||||
25
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestCompute2.hlsl
Normal file
25
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestCompute2.hlsl
Normal file
@ -0,0 +1,25 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "TestCompute2Bindings.h"
|
||||
#include "ShaderMat44.h"
|
||||
#include "ShaderVec3.h"
|
||||
#include "ShaderQuat.h"
|
||||
|
||||
JPH_SHADER_FUNCTION_BEGIN(void, main, cTestCompute2GroupSize, 1, 1)
|
||||
JPH_SHADER_PARAM_THREAD_ID(tid)
|
||||
JPH_SHADER_FUNCTION_END
|
||||
{
|
||||
TestCompute2Input input = gInput[tid.x];
|
||||
TestCompute2Output output;
|
||||
|
||||
output.mMul3x4Output = JPH_Mat44Mul3x4Vec3(input.mMat44Value, input.mMat44MulValue);
|
||||
output.mMul3x3Output = JPH_Mat44Mul3x3Vec3(input.mMat44Value, input.mMat44MulValue);
|
||||
|
||||
output.mDecompressedVec3 = JPH_Vec3DecompressUnit(input.mCompressedVec3);
|
||||
|
||||
output.mDecompressedQuat = JPH_QuatDecompress(input.mCompressedQuat);
|
||||
|
||||
gOutput[tid.x] = output;
|
||||
}
|
||||
26
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestCompute2Bindings.h
Normal file
26
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestCompute2Bindings.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "ShaderCore.h"
|
||||
|
||||
JPH_SHADER_CONSTANT(int, cTestCompute2GroupSize, 1)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(TestCompute2Input)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_Mat44, Mat44Value)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, Mat44MulValue)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, CompressedVec3)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_uint, CompressedQuat)
|
||||
JPH_SHADER_STRUCT_END(TestComputeContext)
|
||||
|
||||
JPH_SHADER_STRUCT_BEGIN(TestCompute2Output)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, Mul3x4Output)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, Mul3x3Output)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_float3, DecompressedVec3)
|
||||
JPH_SHADER_STRUCT_MEMBER(JPH_Quat, DecompressedQuat)
|
||||
JPH_SHADER_STRUCT_END(TestCompute2Output)
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_TestCompute2)
|
||||
JPH_SHADER_BIND_BUFFER(TestCompute2Input, gInput)
|
||||
JPH_SHADER_BIND_RW_BUFFER(TestCompute2Output, gOutput)
|
||||
JPH_SHADER_BIND_END(JPH_TestCompute2)
|
||||
21
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestComputeBindings.h
Normal file
21
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestComputeBindings.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2025 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "ShaderCore.h"
|
||||
|
||||
JPH_SHADER_CONSTANT(int, cTestComputeGroupSize, 64)
|
||||
|
||||
JPH_SHADER_CONSTANTS_BEGIN(TestComputeContext, gContext)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float3, Float3Value)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, UIntValue) // Test that this value packs correctly with the float3 preceding it
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_float3, Float3Value2)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, UIntValue2)
|
||||
JPH_SHADER_CONSTANTS_MEMBER(JPH_uint, NumElements)
|
||||
JPH_SHADER_CONSTANTS_END(TestComputeContext)
|
||||
|
||||
JPH_SHADER_BIND_BEGIN(JPH_TestCompute)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gUploadData)
|
||||
JPH_SHADER_BIND_BUFFER(JPH_uint, gOptionalData)
|
||||
JPH_SHADER_BIND_RW_BUFFER(JPH_uint, gData)
|
||||
JPH_SHADER_BIND_END(JPH_TestCompute)
|
||||
23
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestComputeWrapper.cpp
Normal file
23
lib/haxejolt/JoltPhysics/Jolt/Shaders/TestComputeWrapper.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
||||
// SPDX-FileCopyrightText: 2026 Jorrit Rouwe
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
#ifdef JPH_USE_CPU_COMPUTE
|
||||
|
||||
#define JPH_SHADER_NAME TestCompute
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "TestCompute.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "TestComputeBindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#define JPH_SHADER_NAME TestCompute2
|
||||
#include <Jolt/Compute/CPU/WrapShaderBegin.h>
|
||||
#include "TestCompute2.hlsl"
|
||||
#include <Jolt/Compute/CPU/WrapShaderBindings.h>
|
||||
#include "TestCompute2Bindings.h"
|
||||
#include <Jolt/Compute/CPU/WrapShaderEnd.h>
|
||||
|
||||
#endif // JPH_USE_CPU_COMPUTE
|
||||
Reference in New Issue
Block a user