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

123 lines
3.0 KiB
HLSL

#include "shared/point.hlsl"
#include "shared/quat-functions.hlsl"
#include "shared/bias-functions.hlsl"
#include "shared/hash-functions.hlsl"
cbuffer Params : register(b0)
{
float4x4 transformSampleSpace;
float4x4 TransformMatrix;
float Strength;
float3 Translate;
float3 Scale;
float ScaleUniform;
float3 Rotate;
float Scatter;
float ScaleFx1;
float ScaleFx2;
float2 GainAndBias;
float3 Center;
float StrengthOffset;
}
cbuffer Params : register(b1)
{
int StrengthFactor;
int Channel;
int TranslationSpace;
}
StructuredBuffer<Point> Points : register(t0);
Texture2D<float4> inputTexture : register(t1);
RWStructuredBuffer<Point> ResultPoints : register(u0); // output
sampler texSampler : register(s0);
float3 ExtractScale(float4x4 TransformMatrix)
{
float3 scale;
scale.x = length(TransformMatrix._m00_m01_m02);
scale.y = length(TransformMatrix._m10_m11_m12);
scale.z = length(TransformMatrix._m20_m21_m22);
return scale;
}
[numthreads(256, 4, 1)] void main(uint3 i
: SV_DispatchThreadID)
{
uint pointCount, stride;
ResultPoints.GetDimensions(pointCount, stride);
if (i.x >= pointCount)
return;
uint index = i.x;
Point p = Points[index];
float3 pos = p.Position;
pos -= Center;
float3 posInObject = mul(float4(pos.xyz, 0), transformSampleSpace).xyz;
float4 c = inputTexture.SampleLevel(texSampler, posInObject.xy * float2(0.5, -0.5) + float2(0.5, 0.5), 0.0);
float gray = (c.r + c.g + c.b) / 3;
float f = gray + (hash11u(index) - 0.5) * Scatter;
f = ApplyGainAndBias(f, GainAndBias);
float strength = Strength * (f + StrengthOffset) * (StrengthFactor == 0 ? 1 : (StrengthFactor == 1) ? p.FX1
: p.FX2);
float4 orgRot = p.Rotation;
float4 rotation = orgRot;
if (TranslationSpace < 0.5)
{
pos.xyz = 0;
rotation = float4(0, 0, 0, 1);
}
float3 pLocal = pos;
pos = mul(float4(pos, 1), TransformMatrix).xyz;
float4 newRotation = rotation;
float3 scale = ExtractScale(TransformMatrix);
// Remove scale from the matrix to get pure rotation
float3x3 rotationMatrix = float3x3(
TransformMatrix._m00_m01_m02 / scale.x,
TransformMatrix._m10_m11_m12 / scale.y,
TransformMatrix._m20_m21_m22 / scale.z);
newRotation = normalize(qFromMatrix3Precise(transpose(rotationMatrix)));
// Adjust rotation in point space
if (TranslationSpace < 0.5)
{
newRotation = qMul(orgRot, newRotation);
}
else
{
newRotation = qMul(newRotation, orgRot);
}
if (TranslationSpace == 0)
{
pos.xyz = qRotateVec3(pos.xyz, orgRot).xyz;
pos += p.Position;
// Apply scale to Stretch
p.Scale *= lerp(1, scale, strength);
}
p.Position = lerp(p.Position, pos.xyz, strength);
p.Rotation = qSlerp(p.Rotation, newRotation, strength);
ResultPoints[index] = p;
}