#version 440 core

layout(push_constant) uniform Params {
    // Size of the source image.
    uint source_size_xy;
    // Offset to place the image at in the target texture.
    //
    // Origin is the top-left.
    uint target_offset_xy;
    // Size of the target texture.
    uint target_size_xy;
};

layout(location = 0) out vec2 source_coords;

vec2 unpack(uint xy) {
    return vec2(xy & 0xFFFF, (xy >> 16) & 0xFFFF);
}

void main() {
    vec2 source_size = unpack(source_size_xy);
    vec2 target_offset = unpack(target_offset_xy);
    vec2 target_size = unpack(target_size_xy);

    // Generate rectangle (counter clockwise triangles)
    //
    // 0 0 1 1 1 0
    float x_select = float(((uint(gl_VertexIndex) + 1u) / 3u) % 2u);
    // 1 0 0 0 1 1
    float y_select = float(((uint(gl_VertexIndex) + 5u) / 3u) % 2u);

    source_coords = vec2(
        // left -> right (on screen)
        mix(0.0, 1.0, x_select),
        // bottom -> top (on screen)
        mix(1.0, 0.0, y_select)
    ) * source_size;

    vec2 target_coords_normalized = (target_offset + source_coords) / target_size;

    // Flip y and transform [0.0, 1.0] -> [-1.0, 1.0] to get NDC coordinates.
    vec2 v_pos = ((target_coords_normalized * 2.0) - vec2(1.0)) * vec2(1.0, -1.0); 

    gl_Position = vec4(v_pos, 0.0, 1.0);
}