199 lines
4.9 KiB
HLSL
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;
|
|
}
|