Vulkan is the only backend with the Y axis pointing down in normalized device coordinates, while all the geometry here is built in the bottom-left based system of OpenGL. The vertex shaders computing clip space from pixel coordinates now negate Y by a flipY uniform, kept at offset 12 in every block they share, and the clip space quads computed on our side, in PiP and in the offscreen passes of the group call viewport, are negated directly. The 3D renderers already handle this with clipSpaceCorrMatrix(). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
51 lines
1.3 KiB
GLSL
51 lines
1.3 KiB
GLSL
#version 450
|
|
|
|
layout(location = 0) in vec2 inQuadPos;
|
|
|
|
layout(location = 0) out vec2 v_texcoord;
|
|
layout(location = 1) out float v_alpha;
|
|
|
|
layout(binding = 2) uniform sampler2D particleStateTex;
|
|
|
|
layout(std140, binding = 0) uniform Params {
|
|
vec4 rect;
|
|
vec2 size;
|
|
uvec2 particleResolution;
|
|
vec4 scale;
|
|
// -1.0 when the NDC Y axis points down (Vulkan), 1.0 otherwise.
|
|
float flipY;
|
|
};
|
|
|
|
void main() {
|
|
uint particleId = uint(gl_InstanceIndex);
|
|
uint pX = particleId % particleResolution.x;
|
|
uint pY = particleId / particleResolution.x;
|
|
|
|
vec4 state = texelFetch(
|
|
particleStateTex,
|
|
ivec2(int(pX), int(pY)),
|
|
0);
|
|
vec2 inOffset = state.xy;
|
|
float inLifetime = state.z;
|
|
|
|
vec2 particleSize = size / vec2(particleResolution);
|
|
|
|
vec2 topLeft = vec2(float(pX) * particleSize.x, float(pY) * particleSize.y);
|
|
v_texcoord = (topLeft + inQuadPos * particleSize) / size;
|
|
|
|
topLeft += inOffset;
|
|
float scaleFactor = scale.x;
|
|
vec2 center = topLeft + (particleSize * 0.5);
|
|
vec2 position
|
|
= center + ((inQuadPos - vec2(0.5)) * particleSize * scaleFactor);
|
|
|
|
vec2 ndc;
|
|
ndc.x = rect.x + position.x / size.x * rect.z;
|
|
ndc.y = rect.y + position.y / size.y * rect.w;
|
|
ndc.x = -1.0 + ndc.x * 2.0;
|
|
ndc.y = -1.0 + ndc.y * 2.0;
|
|
|
|
gl_Position = vec4(ndc.x, ndc.y * flipY, 0.0, 1.0);
|
|
|
|
v_alpha = clamp(inLifetime / 0.6, 0.0, 1.0) * scale.z;
|
|
}
|