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

108 lines
3.1 KiB
HLSL

#include "shared/hash-functions.hlsl"
// #include "shared/noise-functions.hlsl"
#include "shared/point.hlsl"
#include "shared/quat-functions.hlsl"
#include "shared/bias-functions.hlsl"
cbuffer Params : register(b0)
{
float2 AmountXY;
float Amount;
float Confinment;
float DepthConcentration;
float CenterDepth;
float SpinAngle;
float SpinVariation;
float AmountVariation;
float2 VariationGainAndBias;
float Twist;
float4 Color;
float Colorize;
float TwistVariation;
}
cbuffer Transforms : register(b1)
{
float4x4 CameraToClipSpace;
float4x4 ClipSpaceToCamera;
float4x4 WorldToCamera;
float4x4 CameraToWorld;
float4x4 WorldToClipSpace;
float4x4 ClipSpaceToWorld;
float4x4 ObjectToWorld;
float4x4 WorldToObject;
float4x4 ObjectToCamera;
float4x4 ObjectToClipSpace;
};
sampler texSampler : register(s0);
Texture2D<float4> FxTexture : register(t0);
RWStructuredBuffer<Particle> Particles : u0;
[numthreads(64, 1, 1)] void main(uint3 i : SV_DispatchThreadID)
{
uint maxParticleCount, _;
Particles.GetDimensions(maxParticleCount, _);
if (i.x >= maxParticleCount)
return;
float randomHash = ApplyGainAndBias(hash11u(i.x), VariationGainAndBias);
float4 posInObject = float4(Particles[i.x].Position, 1);
float4 posInCamera = mul(posInObject, ObjectToCamera);
float4 pos = mul(float4(posInCamera.xyz, 1), CameraToClipSpace);
float depth = pos.z;
pos.xyz /= pos.w;
float4 normalMap = FxTexture.SampleLevel(texSampler, (pos.xy * float2(1, -1) + 1) / 2, 0);
float phaseOffset = 0; //- 3.141578/2;
float twist = Twist + (randomHash - 0.5) * TwistVariation;
float sina = sin(-twist / 180 * PI + phaseOffset);
float cosa = cos(-twist / 180 * PI + phaseOffset);
normalMap.xy = float2(
cosa * normalMap.x - sina * normalMap.y,
cosa * normalMap.y + sina * normalMap.x);
// Should add more twist here...
float randomAmount = (randomHash - 0.5) * AmountVariation;
float3 offset = normalMap.rgb * float3(1, -1, 1) * (Amount + randomAmount) * float3(AmountXY, 0) * normalMap.a;
// Confine particles outside of view
float2 dXYFromCenter = abs(pos.xy);
float distanceFromCenter = max(dXYFromCenter.x, dXYFromCenter.y);
float confineFactor = smoothstep(0.9, 1.2, distanceFromCenter);
if (distanceFromCenter > 0.01)
{
offset.xy -= normalize(pos.xy) * confineFactor * Confinment;
}
float accelerationToDepthCenter = depth - CenterDepth;
offset.z += accelerationToDepthCenter * DepthConcentration;
offset = mul(float4(offset.xyz, 0), CameraToWorld );
float intensity = length(offset);
Particles[i.x].Color = lerp(Particles[i.x].Color, Color, saturate( intensity * Colorize));
float3 v = Particles[i.x].Velocity + offset;
float lengthXY = length(v.xy);
if (lengthXY > 0.0001)
{
float angle = atan2(v.x, v.y) + (SpinAngle + SpinVariation * (randomHash - 0.5)) / 180 * PI;
v.xy = float2(sin(angle), cos(angle)) * lengthXY;
}
Particles[i.x].Velocity = v;
}