mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-22 14:23:20 +02:00
90 lines
3.2 KiB
GLSL
90 lines
3.2 KiB
GLSL
// storage of the particles of the gpu (opengl46_gpu_particles, gl::particle_* in gl/ubo.h) for the compute passes
|
|
|
|
#ifndef PARTICLE_COMMON_GLSL
|
|
#define PARTICLE_COMMON_GLSL
|
|
|
|
// a particle of smoke; it's dead (or its place was never used) when its opacity is 0 or less
|
|
struct smoke_particle_s
|
|
{
|
|
vec4 position; // xyz: metres from the origin of the particles (world axes), w: rotation, radians
|
|
vec4 velocity; // xyz: m/s, w: size of the billboard, metres
|
|
vec4 state; // x: opacity, y: age, seconds
|
|
};
|
|
|
|
// a source of smoke as the last update of the simulation left it (smoke_source::gpu_state)
|
|
struct smoke_source_s
|
|
{
|
|
uvec4 pool; // x: first place of the source in the storage, y: number of its places, z: place of the first particle born in the update, w: particles born
|
|
vec4 location; // xyz: emitter at the update, from the origin
|
|
vec4 previous; // xyz: emitter at the update before, from the origin
|
|
vec4 launch; // xy: inclination, radians, zw: speed, m/s
|
|
vec4 initial; // xy: size, zw: opacity
|
|
vec4 sizechange; // x: per second, y: min, z: max
|
|
vec4 opacitychange; // x: per second, y: min, z: max
|
|
vec4 motion; // x: rise, y: damping (per second, of the vertical velocity), z: least vertical velocity
|
|
vec4 color; // rgb: colour of the smoke, lit by the lights of the pass
|
|
vec4 oldcolor; // rgb: colour lit as the cpu does it, without the lights (gfx.smoke.lighting off)
|
|
};
|
|
|
|
// what a draw of a particle reads, as attributes of an instance
|
|
struct particle_draw_s
|
|
{
|
|
vec4 place; // xyz: metres from the camera (world axes), w: size (smoke) or width (rain, snow)
|
|
vec4 shape; // x: rotation (smoke); xyz: from the head of the streak to its tail (rain, snow)
|
|
vec4 color; // rgb: lit colour, a: opacity
|
|
};
|
|
|
|
// the indirect draw command of the particles; the compute passes count the instances
|
|
layout(std430, binding = PARTICLE_COMMAND_SSBO_BINDING) buffer particle_command_ssbo
|
|
{
|
|
uint particle_draw_vertices;
|
|
uint particle_draw_instances;
|
|
uint particle_draw_first;
|
|
uint particle_draw_base;
|
|
};
|
|
|
|
layout(std430, binding = PARTICLE_OUTPUT_SSBO_BINDING) writeonly buffer particle_output_ssbo
|
|
{
|
|
particle_draw_s particle_draws[];
|
|
};
|
|
|
|
// pcg hash
|
|
uint particle_hash(uint value)
|
|
{
|
|
uint state = value * 747796405U + 2891336453U;
|
|
uint word = ((state >> ((state >> 28U) + 4U)) ^ state) * 277803737U;
|
|
return (word >> 22U) ^ word;
|
|
}
|
|
|
|
// next of a sequence of random numbers 0-1
|
|
float particle_random(inout uint state)
|
|
{
|
|
state = particle_hash(state);
|
|
return float(state >> 8U) * (1.0 / 16777216.0);
|
|
}
|
|
|
|
// whether a sphere (centre from the camera along the world axes) is within the planes of the view
|
|
bool particle_visible(vec4 planes[5], vec3 centre, float radius)
|
|
{
|
|
for (int i = 0; i < 5; i++)
|
|
if (dot(planes[i].xyz, centre) + planes[i].w < -radius)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// adds a particle to the draw; Capacity: the places of the storage of the draws
|
|
void particle_emit(vec3 place, float size, vec3 shape, vec3 color, float opacity, uint capacity)
|
|
{
|
|
uint index = atomicAdd(particle_draw_instances, 1U);
|
|
if (index >= capacity)
|
|
{
|
|
atomicAdd(particle_draw_instances, 0xFFFFFFFFU);
|
|
return;
|
|
}
|
|
particle_draws[index].place = vec4(place, size);
|
|
particle_draws[index].shape = vec4(shape, 0.0);
|
|
particle_draws[index].color = vec4(color, opacity);
|
|
}
|
|
|
|
#endif
|