Files
2026-07-13 13:13:17 +08:00

219 lines
5.1 KiB
HLSL

#include "shared/hash-functions.hlsl"
#include "shared/point.hlsl"
#include "shared/quat-functions.hlsl"
#include "shared/pbr.hlsl"
cbuffer Params : register(b0)
{
float Bounciness;
float Damping;
// float3 Direction;
// float Amount;
// float RandomAmount;
// float Mode;
}
RWStructuredBuffer<Particle> Particles : u0;
StructuredBuffer<PbrVertex> Vertices: t0;
StructuredBuffer<int3> Indices: t1;
float3 closestPointOnTriangle( in float3 p0, in float3 p1, in float3 p2, in float3 sourcePosition )
{
float3 edge0 = p1 - p0;
float3 edge1 = p2 - p0;
float3 v0 = p0 - sourcePosition;
float a = dot(edge0, edge0 );
float b = dot(edge0, edge1 );
float c = dot(edge1, edge1 );
float d = dot(edge0, v0 );
float e = dot(edge1, v0 );
float det = a*c - b*b;
float s = b*e - c*d;
float t = b*d - a*e;
if ( s + t < det )
{
if ( s < 0.f )
{
if ( t < 0.f )
{
if ( d < 0.f )
{
s = clamp( -d/a, 0.f, 1.f );
t = 0.f;
}
else
{
s = 0.f;
t = clamp( -e/c, 0.f, 1.f );
}
}
else
{
s = 0.f;
t = clamp( -e/c, 0.f, 1.f );
}
}
else if ( t < 0.f )
{
s = clamp( -d/a, 0.f, 1.f );
t = 0.f;
}
else
{
float invDet = 1.f / det;
s *= invDet;
t *= invDet;
}
}
else
{
if ( s < 0.f )
{
float tmp0 = b+d;
float tmp1 = c+e;
if ( tmp1 > tmp0 )
{
float numer = tmp1 - tmp0;
float denom = a-2*b+c;
s = clamp( numer/denom, 0.f, 1.f );
t = 1-s;
}
else
{
t = clamp( -e/c, 0.f, 1.f );
s = 0.f;
}
}
else if ( t < 0.f )
{
if ( a+d > b+e )
{
float numer = c+e-b-d;
float denom = a-2*b+c;
s = clamp( numer/denom, 0.f, 1.f );
t = 1-s;
}
else
{
s = clamp( -e/c, 0.f, 1.f );
t = 0.f;
}
}
else
{
float numer = c+e-b-d;
float denom = a-2*b+c;
s = clamp( numer/denom, 0.f, 1.f );
t = 1.f - s;
}
}
return p0 + s * edge0 + t * edge1;
}
void findClosestPointAndDistance(
in uint faceCount,
in float3 pos,
out uint closestFaceIndex,
out float3 closestSurfacePoint)
{
closestFaceIndex = -1;
float closestDistance = 99999;
for(uint faceIndex = 0; faceIndex < faceCount; faceIndex++)
{
int3 f = Indices[faceIndex];
float3 pointOnFace = closestPointOnTriangle(
Vertices[f[0]].Position,
Vertices[f[1]].Position,
Vertices[f[2]].Position,
pos
);
float distance2 = length(pointOnFace - pos);
if(distance2 < closestDistance) {
closestDistance = distance2;
closestFaceIndex = faceIndex;
closestSurfacePoint = pointOnFace;
}
}
}
float4 q_from_tangentAndNormal(float3 dx, float3 dz)
{
dx = normalize(dx);
dz = normalize(dz);
float3 dy = -cross(dx, dz);
float3x3 orientationDest= float3x3(
dx,
dy,
dz
);
return normalize( qFromMatrix3Precise( transpose( orientationDest)));
}
[numthreads(64,1,1)]
void main(uint3 i : SV_DispatchThreadID)
{
uint pointCount, Particlestride;
Particles.GetDimensions(pointCount, Particlestride);
if(i.x >= pointCount)
return;
uint vertexCount, vertexStride;
Vertices.GetDimensions(vertexCount, vertexStride);
uint faceCount, faceStride;
Indices.GetDimensions(faceCount, faceStride);
Particle p = Particles[i.x];
float3 pos = p.Position;
float4 rot = p.Rotation;
float pW = p.Radius;
float3 pos2 = pos; // TODO: Implement // + forward * usedSpeed;
int closestFaceIndex;
float3 closestSurfacePoint;
findClosestPointAndDistance(faceCount, pos2, closestFaceIndex, closestSurfacePoint);
//float4 normalizedRot;
//float v = q_separate_v(rot, normalizedRot);
float3 vToSurface = pos - closestSurfacePoint;
//vToSurface = float3(0,-1,0);
float distance = length(vToSurface);
if(isnan(distance) || distance < 0.001)
{
//Particles[i.x].w = 2;
return;
}
if(distance > pW)
return;
//float3 forward = qRotateVec3(float3(0,0, v * Damping), p.Rotation);
Particles[i.x].Velocity = p.Velocity + normalize(vToSurface) * Bounciness;
// float newV =length(forward);
// float4 newRotation = qLookAt(normalize(forward), float3(0,0,1));
//Particles[i.x].Rotation = q_encode_v(newRotation, newV);
}