Files
FlaxEngine/Content/Editor/MaterialTemplates/GPUParticles.shader

179 lines
4.4 KiB
GLSL

// File generated by Flax Editor
// Version: @0
@3
#include "./Flax/Common.hlsl"
#include "./Flax/GBufferCommon.hlsl"
#include "./Flax/Matrix.hlsl"
#include "./Flax/Noise.hlsl"
@7
// Primary constant buffer
META_CB_BEGIN(0, Data)
float4x4 ViewProjectionMatrix;
float4x4 InvViewProjectionMatrix;
float4x4 InvViewMatrix;
float4x4 ViewMatrix;
float4x4 WorldMatrix;
float4x4 InvWorldMatrix;
float3 ViewPos;
float ViewFar;
float3 ViewDir;
float Time;
float4 ViewInfo;
float4 ScreenSize;
float3 EffectPosition;
float DeltaTime;
float4 EffectRotation;
float3 EffectScale;
uint ParticleCounterOffset;
float3 Dummy0;
uint SpawnCount;
@1META_CB_END
// Particles data buffers
ByteAddressBuffer SrcParticlesData : register(t0);
RWByteAddressBuffer DstParticlesData : register(u0);
// The GPU particles simulation context data
struct Context
{
uint ParticleIndex;
uint ParticlesCount;
uint Seed;
};
@6
// Seed generation function
uint WangHash(uint seed)
{
seed = (seed ^ 61) ^ (seed >> 16);
seed += (seed << 3);
seed = seed ^ (seed >> 4);
seed *= 0x27d4eb2d;
seed = seed ^ (seed >> 15);
return seed;
}
// Random number generation function
float Rand(inout uint seed)
{
const uint multiplier = 0x0019660d;
const uint increment = 0x3c6ef35f;
seed = multiplier * seed + increment;
return asfloat((seed >> 9) | 0x3f800000) - 1.0f;
}
// Reprojects the world space position from the given UV and raw device depth
float3 ReprojectPosition(float2 uv, float rawDepth)
{
uv = uv * float2(2.0, -2.0) + float2(-1.0, 1.0);
float4 pos = mul(float4(uv.x, uv.y, rawDepth, 1.0f), InvViewProjectionMatrix);
return pos.xyz / pos.w;
}
// Random values generation wrapper macros
#define RAND Rand(context.Seed)
#define RAND2 float2(RAND, RAND)
#define RAND3 float3(RAND, RAND, RAND)
#define RAND4 float4(RAND, RAND, RAND, RAND)
@2uint GetParticleUint(uint particleIndex, int offset)
{
return SrcParticlesData.Load(particleIndex * PARTICLE_STRIDE + offset);
}
int GetParticleInt(uint particleIndex, int offset)
{
return asint(SrcParticlesData.Load(particleIndex * PARTICLE_STRIDE + offset));
}
float GetParticleFloat(uint particleIndex, int offset)
{
return asfloat(SrcParticlesData.Load(particleIndex * PARTICLE_STRIDE + offset));
}
float2 GetParticleVec2(uint particleIndex, int offset)
{
return asfloat(SrcParticlesData.Load2(particleIndex * PARTICLE_STRIDE + offset));
}
float3 GetParticleVec3(uint particleIndex, int offset)
{
return asfloat(SrcParticlesData.Load3(particleIndex * PARTICLE_STRIDE + offset));
}
float4 GetParticleVec4(uint particleIndex, int offset)
{
return asfloat(SrcParticlesData.Load4(particleIndex * PARTICLE_STRIDE + offset));
}
void SetParticleUint(uint particleIndex, int offset, uint value)
{
DstParticlesData.Store(particleIndex * PARTICLE_STRIDE + offset, value);
}
void SetParticleInt(uint particleIndex, int offset, int value)
{
DstParticlesData.Store(particleIndex * PARTICLE_STRIDE + offset, asuint(value));
}
void SetParticleFloat(uint particleIndex, int offset, float value)
{
DstParticlesData.Store(particleIndex * PARTICLE_STRIDE + offset, asuint(value));
}
void SetParticleVec2(uint particleIndex, int offset, float2 value)
{
DstParticlesData.Store2(particleIndex * PARTICLE_STRIDE + offset, asuint(value));
}
void SetParticleVec3(uint particleIndex, int offset, float3 value)
{
DstParticlesData.Store3(particleIndex * PARTICLE_STRIDE + offset, asuint(value));
}
void SetParticleVec4(uint particleIndex, int offset, float4 value)
{
DstParticlesData.Store4(particleIndex * PARTICLE_STRIDE + offset, asuint(value));
}
bool AddParticle(out uint dstIndex)
{
// Acquire the particle index in the destination buffer
DstParticlesData.InterlockedAdd(ParticleCounterOffset, 1, dstIndex);
// Prevent overflow
return dstIndex >= PARTICLE_CAPACITY;
}
void UpdateParticle(Context context)
{
@5}
void SpawnParticle(Context context)
{
if (AddParticle(context.ParticleIndex))
return;
@4}
// Main entry point for the particles simulation and spawning
META_CS(true, FEATURE_LEVEL_SM5)
[numthreads(THREAD_GROUP_SIZE, 1, 1)]
void CS_Main(uint3 dispatchThreadId : SV_DispatchThreadID)
{
Context context;
context.ParticleIndex = dispatchThreadId.x;
context.ParticlesCount = min(SrcParticlesData.Load(ParticleCounterOffset), PARTICLE_CAPACITY);
context.Seed = WangHash(context.ParticleIndex ^ asuint(Time));
if (context.ParticleIndex < context.ParticlesCount)
{
UpdateParticle(context);
}
else if (context.ParticleIndex < context.ParticlesCount + SpawnCount)
{
SpawnParticle(context);
}
}