/*
* Tuxánci 2 - A first person shooter
* Copyright (C) 2025-2026 Connor Thomson
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
struct ShapeVertexUniforms {
float4 bounds;
float4 points[3];
float4 viewport;
float4 color;
float4 params;
};
[[vk::binding(0, 1)]]
ConstantBuffer uniforms : register(b0, space1);
struct VSOutput {
float4 position : SV_Position;
float2 uv : TEXCOORD0;
};
float2 to_clip(float2 point) {
return float2(
2.0 * point.x / uniforms.viewport.x - 1.0,
1.0 - 2.0 * point.y / uniforms.viewport.y
);
}
float2 line_vertex(float2 first, float2 second, uint vertexID) {
float2 direction = normalize(second - first);
float2 normal = float2(-direction.y, direction.x) * uniforms.params.y * 0.5;
static const float2 corners[6] = {
float2( 1.0, 1.0),
float2( 1.0, -1.0),
float2(-1.0, 1.0),
float2(-1.0, 1.0),
float2( 1.0, -1.0),
float2(-1.0, -1.0)
};
float2 corner = corners[vertexID];
return lerp(first, second, corner.x * 0.5 + 0.5) + normal * corner.y;
}
VSOutput main(uint vertexID : SV_VertexID) {
static const float2 quad_positions[6] = {
float2(0.0, 0.0),
float2(1.0, 0.0),
float2(0.0, 1.0),
float2(0.0, 1.0),
float2(1.0, 0.0),
float2(1.0, 1.0)
};
uint shape_type = (uint)uniforms.params.x;
float2 position;
float2 uv = float2(0.0, 0.0);
if (shape_type <= 1 || shape_type >= 3 && shape_type <= 4) {
uv = quad_positions[vertexID];
position = uniforms.bounds.xy + uv * uniforms.bounds.zw;
} else if (shape_type == 2) {
position = line_vertex(uniforms.points[0].xy, uniforms.points[1].xy, vertexID);
} else if (shape_type == 5) {
position = uniforms.points[vertexID].xy;
} else {
uint edge = vertexID / 6;
uint edge_vertex = vertexID % 6;
uint first_index = edge;
uint second_index = (edge + 1) % 3;
position = line_vertex(
uniforms.points[first_index].xy,
uniforms.points[second_index].xy,
edge_vertex
);
}
VSOutput output;
output.position = float4(to_clip(position), 0.0, 1.0);
output.uv = uv;
return output;
}