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

159 lines
4.6 KiB
HLSL

#include "shared/point.hlsl"
#include "shared/quat-functions.hlsl"
static const float4 Factors[] =
{
// x y z w
float4(0, 0, 0, 0), // 0 nothing
float4(1, 0, 0, 0), // 1 for x
float4(0, 1, 0, 0), // 2 for y
float4(0, 0, 1, 0), // 3 for z
float4(0, 0, 0, 1), // 4 for w
float4(0, 0, 0, 0), // avoid rotation effects
};
cbuffer Transforms : register(b0)
{
float4x4 CameraToClipSpace;
float4x4 ClipSpaceToCamera;
float4x4 WorldToCamera;
float4x4 CameraToWorld;
float4x4 WorldToClipSpace;
float4x4 ClipSpaceToWorld;
float4x4 ObjectToWorld;
float4x4 WorldToObject;
float4x4 ObjectToCamera;
float4x4 ObjectToClipSpace;
};
cbuffer Params : register(b1)
{
float3 Center;
float SampleRadius;
float Smoothness;
float Speed;
float Steps;
float ZoneLevels;
float Curvature;
float ZoneWidth;
float ZoneCenter;
}
RWStructuredBuffer<LegacyPoint> Points : u0;
Texture2D<float4> inputTexture : register(t1);
sampler texSampler : register(s0);
static float2 texSize;
void GetGradient(float2 uv, float radius, out float2 N, out float averageLevel) {
float4 c = inputTexture.SampleLevel(texSampler, uv , 0.0);
float2 d = SampleRadius *radius / texSize;
float4 cx1 = inputTexture.SampleLevel(texSampler, uv + float2(-d.x,0),0);
float4 cx2 = inputTexture.SampleLevel(texSampler, uv + float2(d.x,0),0);
float4 cy1 = inputTexture.SampleLevel(texSampler, uv + float2(0, -d.y),0);
float4 cy2 = inputTexture.SampleLevel(texSampler, uv + float2(0, d.y),0);
float gx1 = (cx1.r + cx1.g + cx1.b)/3;
float gx2 = (cx2.r + cx2.g + cx2.b)/3;
float gy1 = (cy1.r + cy1.g + cy1.b)/3;
float gy2 = (cy2.r + cy2.g + cy2.b)/3;
N = float2 ( gx2 - gx1, gy2 - gy1);
averageLevel = (gx1+gx2+gy1+gy2)/4;
}
[numthreads(256,4,1)]
void main(uint3 i : SV_DispatchThreadID)
{
int lineStepCount = (int)clamp(Steps,1,1000);
uint pointCount, stride;
Points.GetDimensions(pointCount,stride);
if(i.x > pointCount) {
return;
}
uint lineStartIndex = int(i.x / lineStepCount) *lineStepCount;
uint sx,sy;
inputTexture.GetDimensions(sx,sy);
texSize = float2(sx,sy);
LegacyPoint P = Points[lineStartIndex];
float3 pos = P.Position;
float4 rot = P.Rotation;
float w = P.W;
// Asign target Zonelevels to points
int lineCount = pointCount / lineStepCount;
int lineIndex = i.x / lineStepCount;
float levelIndex = lineIndex % ZoneLevels;
w = levelIndex / (ZoneLevels-1);
float targetLevel = (w-0.5) * ZoneWidth + ZoneCenter;
int index = lineStartIndex;
for(int stepIndex = 0; stepIndex < lineStepCount; stepIndex++)
{
if(index > pointCount)
return;
float3 posInObject = mul(float4(pos.xyz - Center,0), WorldToObject).xyz;
float2 uv = posInObject.xy/2 * float2(1,-1) + float2(0.5, 0.5);
float averageLevel;
float2 N;
GetGradient(uv, 1, N, averageLevel);
float averageLevel2;
float2 N2;
GetGradient(uv, 15, N2, averageLevel2);
N = lerp(N, N2, 0.1);
averageLevel = lerp(averageLevel, averageLevel2, 0.1);
if(length(N) > 0.0001)
{
float2 NN = normalize(N);
float gradientAngle = atan2(N.x, N.y) ;// + clamp(correctionAngle * l , -1.6,1.6);
//float2 slope = cross( float3(NN,0), float3(0,0,-1)).xy;
//float slopAngle = atan2(slope.x, slope.y);
// Smooth but strange offset
float dLevel = (targetLevel - averageLevel) * Curvature;
float adjustLevelFactor = smoothstep(0,1,abs(dLevel));
adjustLevelFactor *= dLevel < 0 ? 1:-1;
float adjustAngleOffset = adjustLevelFactor * 3.1415 / 2;
float adjustedAngle = gradientAngle + adjustAngleOffset;
float4 newRot = qFromAngleAxis(adjustedAngle,float3(0,0,1));
rot = qSlerp(newRot, rot, Smoothness);
// Smooth but strange offset
// float dLevel = targetLevel - averageLevel;
// float adjustedAngle = gradientAngle;
// if(abs(dLevel) > 0.001) {
// adjustedAngle += (dLevel < 0 ? 1 : -1) * 3.1415 / 2;
// }
}
Points[index].Rotation = rot;
Points[index].W = w;
if(stepIndex == lineStepCount - 1) {
Points[index].W = sqrt(-1);
}
float3 foreward = qRotateVec3(float3(1,0,0), rot) * Speed / 100 ;
pos += foreward;
Points[index].Position = pos;
index++;
}
}