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

143 lines
3.6 KiB
HLSL

#include "shared/hash-functions.hlsl"
#include "shared/noise-functions.hlsl"
#include "shared/point.hlsl"
#include "shared/quat-functions.hlsl"
cbuffer Params : register(b0)
{
float4x4 TransformMatrix;
float UpdateRotation; // 16
float ScaleW;
float OffsetW;
float CoordinateSpace;
float WIsWeight; // 20
float RangeStart;
float RangeLength;
float Take;
float Skip; // 24
float Scatter;
float OnlyKeepTakes;
}
StructuredBuffer<LegacyPoint> SourcePoints : t0;
RWStructuredBuffer<LegacyPoint> ResultPoints : u0;
static const float PointSpace = 0;
static const float ObjectSpace = 1;
static const float WorldSpace = 2;
uint imod(uint x, uint y) {
return (x - y * floor(x / y));
}
[numthreads(64,1,1)]
void main(uint3 i : SV_DispatchThreadID)
{
uint sourceCount, resultCount, stride;
SourcePoints.GetDimensions(sourceCount, stride);
ResultPoints.GetDimensions(resultCount, stride);
if(i.x >= resultCount) {
return;
}
uint segmentCount = sourceCount ; // Number of lines between points
uint iTake = (int)Take;
uint iSkip = (int)Skip;
uint iGroupSize = iTake + iSkip;
uint sourceIndex=i.x;
uint resultIndex = i.x;
float theta = 0.0001;
if(OnlyKeepTakes > 0.5)
{
int sourceStartIndex = RangeStart * sourceCount + 1 - theta;
int iGroupIndex = i.x / iTake;
int indexInGroup = i.x % iTake;
int offset = (iGroupIndex * (iTake+iSkip) + indexInGroup + sourceStartIndex);
sourceIndex = (offset + sourceCount * 1000000) % sourceCount;
}
else
{
float f= mod((float)i.x / segmentCount - RangeStart ,1 + theta);
uint indexInRange = f * segmentCount;
uint groupIndex = (indexInRange) / iGroupSize;
uint indexInGroup = indexInRange % iGroupSize;
ResultPoints[resultIndex] = SourcePoints[sourceIndex];
// Copy points outside of range
if(indexInRange < 0 || indexInRange > (uint)(RangeLength * segmentCount) || indexInGroup >= iTake)
{
return;
}
ResultPoints[resultIndex].W = indexInGroup;
}
LegacyPoint p = SourcePoints[sourceIndex];
float w = p.W;
float3 pOrg = p.Position;
float3 pos = pOrg;
float4 orgRot = p.Rotation;
float4 rotation = orgRot;
if(CoordinateSpace < 0.5) {
pos.xyz = 0;
rotation = float4(0,0,0,1);
}
float3 pLocal = pos;
pos = mul(float4(pos, 1), TransformMatrix).xyz;
float4 newRotation = rotation;
// Transform rotation is kind of tricky. There might be more efficient ways to do this.
if(UpdateRotation > 0.5)
{
float3x3 orientationDest = float3x3(
TransformMatrix._m00_m01_m02,
TransformMatrix._m10_m11_m12,
TransformMatrix._m20_m21_m22);
newRotation = normalize(qFromMatrix3Precise(transpose(orientationDest)));
// Adjust rotation in point space
if(CoordinateSpace < 0.5) {
newRotation = qMul(orgRot, newRotation);
}
else {
newRotation = qMul(newRotation, orgRot);
}
}
if(WIsWeight >= 0.5) {
float3 weightedOffset = (pos - pLocal) * w;
pos = pLocal + weightedOffset;
newRotation = qSlerp(orgRot, newRotation, w);
}
if(CoordinateSpace < 0.5) {
pos.xyz = qRotateVec3(pos.xyz, orgRot).xyz;
pos += pOrg;
}
p.Position = pos.xyz;
p.Rotation = newRotation;
p.W = w * ScaleW + OffsetW;
ResultPoints[resultIndex] = p;
}