-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #150 from edunad/features/particle-engine
[FEATURE] GPU Particle System
- Loading branch information
Showing
86 changed files
with
1,387 additions
and
457 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
rawrbox.render/assets/shaders/materials/model/unlit/unlit.psh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
#include "defines.fxh" | ||
#include "math.fxh" | ||
|
||
#include "pixel_bindless_uniforms.fxh" | ||
|
||
#ifdef CLUSTER_PLUGIN | ||
|
34 changes: 34 additions & 0 deletions
34
rawrbox.render/assets/shaders/particles/include/particles.fxh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#ifndef INCLUDED_PARTICLES | ||
#define INCLUDED_PARTICLES | ||
#include "math.fxh" | ||
|
||
struct Particle { | ||
float3 position; | ||
float lifeTime; | ||
|
||
float3 velocity; | ||
float atlasIndex; | ||
|
||
float2 size; | ||
float2 _padding; | ||
|
||
float3 rotation; | ||
float _padding_2; | ||
|
||
float4 color; | ||
}; | ||
|
||
#if defined(WRITE_PARTICLES) | ||
RWStructuredBuffer<Particle> Particles; // Read-Write | ||
#define PARTICLES | ||
#elif defined(READ_PARTICLES) | ||
StructuredBuffer<Particle> Particles; // Read-only | ||
#define PARTICLES | ||
#endif | ||
|
||
#ifdef PARTICLES | ||
Particle GetParticle(uint index) { | ||
return Particles[NonUniformResourceIndex(index)]; | ||
} | ||
#endif | ||
#endif |
32 changes: 32 additions & 0 deletions
32
rawrbox.render/assets/shaders/particles/include/particles_uniforms.fxh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#ifndef INCLUDED_PARTICLES_UNIFORMS | ||
#define INCLUDED_PARTICLES_UNIFORMS | ||
|
||
struct EmitterConstantsStruct { | ||
float3 position; | ||
float time; | ||
|
||
float3 velocityMin; | ||
float lifeMin; | ||
|
||
float3 velocityMax; | ||
float lifeMax; | ||
|
||
float3 rotationMin; | ||
float spawnRate; | ||
|
||
float3 rotationMax; | ||
float gravity; | ||
|
||
float4 color[4]; | ||
float4 size; | ||
|
||
// ------------ | ||
uint billboard; | ||
uint atlasMin; | ||
uint atlasMax; | ||
uint textureID; | ||
// ------------ | ||
}; | ||
|
||
ConstantBuffer<EmitterConstantsStruct> EmitterConstants; | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#include "camera.fxh" | ||
#include "particles_uniforms.fxh" | ||
#include "hash.fxh" | ||
#include "math.fxh" | ||
|
||
#define WRITE_PARTICLES | ||
#include "particles.fxh" | ||
|
||
float3 CalculateVelocity(uint hash) { | ||
float3 randomVelocity; | ||
randomVelocity.x = lerp(EmitterConstants.velocityMin.x, EmitterConstants.velocityMax.x, (float)(hash & 0xFF) * (1.0f / 255.0f)); | ||
randomVelocity.y = lerp(EmitterConstants.velocityMin.y, EmitterConstants.velocityMax.y, (float)((hash >> 8) & 0xFF) * (1.0f / 255.0f)); | ||
randomVelocity.z = lerp(EmitterConstants.velocityMin.z, EmitterConstants.velocityMax.z, (float)((hash >> 16) & 0xFF) * (1.0f / 255.0f)); | ||
return randomVelocity; | ||
} | ||
|
||
float3 CalculateRotation(uint hash) { | ||
float3 randomRotation; | ||
randomRotation.x = lerp(EmitterConstants.rotationMin.x, EmitterConstants.rotationMax.x, (float)(hash & 0xFF) * (1.0f / 255.0f)); | ||
randomRotation.y = lerp(EmitterConstants.rotationMin.y, EmitterConstants.rotationMax.y, (float)((hash >> 8) & 0xFF) * (1.0f / 255.0f)); | ||
randomRotation.z = lerp(EmitterConstants.rotationMin.z, EmitterConstants.rotationMax.z, (float)((hash >> 8) & 0xFF) * (1.0f / 255.0f)); | ||
|
||
return randomRotation; | ||
} | ||
|
||
float2 CalculateSize(uint hash) { | ||
float2 randomSize; | ||
randomSize.x = lerp(EmitterConstants.size.x, EmitterConstants.size.z, (float)(hash & 0xFFFF) * (1.0f / 65535.0f)); | ||
randomSize.y = lerp(EmitterConstants.size.y, EmitterConstants.size.w, (float)((hash >> 16) & 0xFFFF) * (1.0f / 65535.0f)); | ||
return randomSize; | ||
} | ||
|
||
uint CalculateAtlas(uint hash) { | ||
return (uint)lerp(EmitterConstants.atlasMin, EmitterConstants.atlasMax, (float)(hash & 0xFFFF) * (1.0f / 65535.0f)); | ||
} | ||
|
||
float CalculateLife(uint hash) { | ||
return lerp(EmitterConstants.lifeMin, EmitterConstants.lifeMax, (float)(hash & 0xFFFF) * (1.0f / 65535.0f)); | ||
} | ||
|
||
float4 ParticleColor(float lifetimeRatio) { | ||
const float transitionPoints[3] = {0.33, 0.66, 0.99}; | ||
lifetimeRatio = saturate(1.0 - lifetimeRatio); | ||
|
||
// Determine color based on lifetimeRatio | ||
if (lifetimeRatio < transitionPoints[0]) { | ||
float factor = lifetimeRatio / transitionPoints[0]; | ||
return lerp(EmitterConstants.color[0], EmitterConstants.color[1], factor); | ||
} else if (lifetimeRatio < transitionPoints[1]) { | ||
float factor = (lifetimeRatio - transitionPoints[0]) / (transitionPoints[1] - transitionPoints[0]); | ||
return lerp(EmitterConstants.color[1], EmitterConstants.color[2], factor); | ||
} else if (lifetimeRatio < transitionPoints[2]) { | ||
float factor = (lifetimeRatio - transitionPoints[1]) / (transitionPoints[2] - transitionPoints[1]); | ||
return lerp(EmitterConstants.color[2], EmitterConstants.color[3], factor); | ||
} else { | ||
return EmitterConstants.color[3]; | ||
} | ||
} | ||
// Use groupshared memory to reduce bandwidth | ||
groupshared Particle localParticles[256]; | ||
|
||
[numthreads(256, 1, 1)] | ||
void main(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) { | ||
uint particleIndex = dispatchThreadID.x; | ||
|
||
uint maxParticles, stride; | ||
Particles.GetDimensions(maxParticles, stride); | ||
|
||
if (particleIndex >= maxParticles) return; | ||
|
||
// Load particle data into groupshared memory | ||
localParticles[groupIndex] = GetParticle(particleIndex); | ||
GroupMemoryBarrierWithGroupSync(); | ||
|
||
Particle particle = localParticles[groupIndex]; | ||
uint hash = pcg(EmitterConstants.time + particleIndex * 1009); | ||
|
||
// Calculate the spawn interval based on the spawn rate | ||
float spawnInterval = 1.0f / EmitterConstants.spawnRate; | ||
float particleSpawnTime = particleIndex * spawnInterval; | ||
|
||
if (particle.lifeTime <= 0.0F && EmitterConstants.time >= particleSpawnTime) { | ||
// Spawn / reset a particle | ||
particle.position = EmitterConstants.position; | ||
particle.color = EmitterConstants.color[0]; | ||
|
||
particle.velocity = CalculateVelocity(hash); | ||
particle.size = CalculateSize(hash); | ||
particle.lifeTime = CalculateLife(hash); | ||
particle.atlasIndex = CalculateAtlas(hash); | ||
particle.rotation = CalculateRotation(hash); | ||
} else { | ||
// Apply gravity to the particle velocity | ||
float3 gravity = float3(0, GRAVITY, 0) * EmitterConstants.gravity; | ||
|
||
particle.rotation += 0.5F * Camera.deltaTime; | ||
particle.velocity += gravity * Camera.deltaTime; | ||
particle.position += particle.velocity * Camera.deltaTime; | ||
particle.lifeTime -= Camera.deltaTime; | ||
particle.color = ParticleColor(particle.lifeTime); | ||
} | ||
|
||
localParticles[groupIndex] = particle; | ||
|
||
// Ensure all threads have completed their work before writing back | ||
GroupMemoryBarrierWithGroupSync(); | ||
Particles[particleIndex] = localParticles[groupIndex]; | ||
} |
Oops, something went wrong.