#version 430 core // Unit quad vertex (XY -0.5..+0.5) layout(location = 0) in vec2 aQuad; layout(location = 1) in vec2 aTex; // Per-instance: world-space center, authored sheet axes, color. layout(location = 2) in vec4 aCenter; layout(location = 3) in vec4 aAxisX; layout(location = 4) in vec4 aAxisY; layout(location = 5) in vec4 aColor; // Campaign V slice V2c (2026-07-27): was uvec2 aTextureHandle (a raw // ARB_bindless_texture handle); now a slot into the global texture table // (ACDREAM_TEXTURE_HANDLE, injected by // tools/ShaderCompiler/VulkanGlslPreamble.cs). layout(location = 6) in uint aTextureIndex; uniform mat4 uViewProjection; out vec2 vTex; out vec4 vColor; // Campaign V slice V6e: was `flat uvec2 vTextureHandle`. A varying cannot carry // a Vulkan descriptor, so the table SLOT crosses the stage boundary and // particle.frag does the lookup at the sample site. flat out uint vTextureIndex; void main() { vec3 world = aCenter.xyz + aAxisX.xyz * aQuad.x + aAxisY.xyz * aQuad.y; vTex = aTex; vColor = aColor; // Slice V6e: forward the slot untouched; the lookup moved to the fragment // stage, which is the only form Vulkan can express. vTextureIndex = aTextureIndex; gl_Position = uViewProjection * vec4(world, 1.0); }