Files
QuaternionEngine/shaders/particles.vert
2025-12-18 17:32:30 +09:00

75 lines
1.9 KiB
GLSL

#version 450
layout(set = 0, binding = 0) uniform SceneData
{
mat4 view;
mat4 proj;
mat4 viewproj;
} sceneData;
struct Particle
{
vec4 pos_age;
vec4 vel_life;
vec4 color;
vec4 misc;
};
layout(std430, set = 1, binding = 0) readonly buffer ParticlePool
{
Particle particles[];
} pool;
layout(std430, set = 1, binding = 1) readonly buffer DrawIndices
{
uint indices[];
} drawIndices;
layout(location = 0) out vec4 v_color;
layout(location = 1) out vec2 v_uv;
layout(location = 2) out float v_view_depth;
layout(location = 3) out float v_seed;
vec2 quad_corner(uint vidx)
{
// Two triangles (6 verts) in a unit quad centered at origin.
const vec2 corners[6] = vec2[6](
vec2(-0.5, -0.5),
vec2( 0.5, -0.5),
vec2( 0.5, 0.5),
vec2(-0.5, -0.5),
vec2( 0.5, 0.5),
vec2(-0.5, 0.5)
);
return corners[vidx % 6u];
}
void main()
{
uint particle_index = drawIndices.indices[uint(gl_InstanceIndex)];
Particle p = pool.particles[particle_index];
float life = max(p.vel_life.w, 1e-6);
float remaining = clamp(p.pos_age.w, 0.0, life);
float t = remaining / life; // remaining fraction
float fade_out = smoothstep(0.0, 0.15, t);
float fade_in = smoothstep(0.0, 0.05, 1.0 - t);
float fade = fade_in * fade_out;
vec2 corner = quad_corner(uint(gl_VertexIndex));
v_uv = corner + vec2(0.5);
// Camera right/up in world-local space from view matrix rows.
vec3 cam_right = vec3(sceneData.view[0][0], sceneData.view[1][0], sceneData.view[2][0]);
vec3 cam_up = vec3(sceneData.view[0][1], sceneData.view[1][1], sceneData.view[2][1]);
float size = max(p.misc.x, 0.0);
vec3 pos = p.pos_age.xyz + (cam_right * corner.x + cam_up * corner.y) * size;
v_color = vec4(p.color.rgb * fade, p.color.a * fade);
v_view_depth = -(sceneData.view * vec4(pos, 1.0)).z;
v_seed = p.misc.y;
gl_Position = sceneData.viewproj * vec4(pos, 1.0);
}