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

199 lines
4.9 KiB
HLSL

#include "shared/hash-functions.hlsl"
#include "shared/noise-functions.hlsl"
#include "shared/point.hlsl"
#include "shared/quat-functions.hlsl"
#include "shared/pbr.hlsl"
cbuffer Params : register(b0)
{
}
StructuredBuffer<LegacyPoint> Points : t0; // input
StructuredBuffer<PbrVertex> Vertices: t1;
StructuredBuffer<int3> Indices: t2;
RWStructuredBuffer<LegacyPoint> ResultPoints : u0; // output
float dot2( in float3 v ) { return dot(v,v); }
float udTriangle( in float3 v1, in float3 v2, in float3 v3, in float3 p )
{
// prepare data
float3 v21 = v2 - v1; float3 p1 = p - v1;
float3 v32 = v3 - v2; float3 p2 = p - v2;
float3 v13 = v1 - v3; float3 p3 = p - v3;
float3 nor = cross( v21, v13 );
return sqrt( // inside/outside test
(sign(dot(cross(v21,nor),p1)) +
sign(dot(cross(v32,nor),p2)) +
sign(dot(cross(v13,nor),p3))<2.0)
?
// 3 edges
min( min(
dot2(v21*clamp(dot(v21,p1)/dot2(v21),0.0,1.0)-p1),
dot2(v32*clamp(dot(v32,p2)/dot2(v32),0.0,1.0)-p2) ),
dot2(v13*clamp(dot(v13,p3)/dot2(v13),0.0,1.0)-p3) )
:
// 1 face
dot(nor,p1)*dot(nor,p1)/dot2(nor) );
}
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 = edge0.dot( edge0 );
// float b = edge0.dot( edge1 );
// float c = edge1.dot( edge1 );
// float d = edge0.dot( v0 );
// float e = edge1.dot( v0 );
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;
}
[numthreads(64,1,1)]
void main(uint3 i : SV_DispatchThreadID)
{
uint pointCount, pointStride;
Points.GetDimensions(pointCount, pointStride);
if(i.x >= pointCount) {
ResultPoints[i.x].W = 0 ;
return;
}
uint vertexCount, vertexStride;
Vertices.GetDimensions(vertexCount, vertexStride);
uint faceCount, faceStride;
Indices.GetDimensions(faceCount, faceStride);
LegacyPoint p = Points[i.x];
int closestIndex = -1;
float closestDistance = 99999;
float3 pos = p.Position;
float3 closestPoint;
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;
closestIndex = faceIndex;
closestPoint = pointOnFace;
}
}
if(closestIndex>=0)
{
p.Position = closestPoint;
}
ResultPoints[i.x] = p;
}