#version 450 core #include "common.glsl" layout(location = 0) in vec4 iPosSize; layout(location = 1) in vec4 iColor; // rgb, alpha // x = kind (0 firefly, 1 mote, 2 spark, 3 flame, 4 ember, 5 smoke, 6 glow), // y = age / life, z = per-particle random seed layout(location = 2) in vec4 iParams; out vec2 vUV; out vec4 vColor; flat out int vKind; out vec2 vLifeSeed; void main() { vec2 corner = vec2(float(gl_VertexID & 1), float(gl_VertexID >> 1)) - 0.5; vec3 camRight = vec3(uView[0][0], uView[1][0], uView[2][0]); vec3 camUp = vec3(uView[0][1], uView[1][1], uView[2][1]); int kind = int(iParams.x + 0.5); float seed = iParams.z; vec2 offset = corner; float extent = 5.0; // fireflies / motes need room for their halo if (kind == 2 || kind == 4 || kind == 6) extent = 1.0; if (kind == 3) { // flame tongues are taller than wide extent = 1.0; offset *= vec2(1.0, 1.3); } if (kind == 5) { // smoke puffs rotate slowly extent = 1.0; float a = seed * 6.2832 + iParams.y * 1.5; offset = mat2(cos(a), sin(a), -sin(a), cos(a)) * offset; } vec3 c = iPosSize.xyz; vec3 wp = c + (camRight * offset.x + camUp * offset.y) * iPosSize.w * extent; vec4 col = iColor; if (kind == 1) { // dust motes only sparkle inside sun shafts float vis = sunShadowFast(c) * shaftCookie(c); col.rgb *= uSunColor.rgb * uSunDir.w * 0.8; col.a *= vis; } if (kind == 5) // smoke is lit by the sky and warmed by nearby fire light col.rgb *= hemiAmbient(vec3(0, 1, 0)) * 2.5 + pointLights(c, vec3(0, -1, 0)) * 0.4; vUV = corner + 0.5; vColor = col; vKind = kind; vLifeSeed = iParams.yz; gl_Position = uViewProj * vec4(wp, 1.0); }