/* * 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 ShapeFragmentUniforms { float4 bounds; float4 points[3]; float4 viewport; float4 color; float4 params; }; [[vk::binding(0, 3)]] ConstantBuffer uniforms : register(b0, space3); struct FSOutput { float4 color : SV_Target0; }; FSOutput main(float2 uv : TEXCOORD0) { uint shape_type = (uint)uniforms.params.x; float distance_from_edge = 0.0; float coverage = 1.0; if (shape_type == 1) { distance_from_edge = min( min(uv.x * uniforms.bounds.z, (1.0 - uv.x) * uniforms.bounds.z), min(uv.y * uniforms.bounds.w, (1.0 - uv.y) * uniforms.bounds.w) ); float edge_width = max(fwidth(distance_from_edge), 0.5); coverage = 1.0 - smoothstep(uniforms.params.y - edge_width, uniforms.params.y + edge_width, distance_from_edge); } else if (shape_type >= 3 && shape_type <= 4) { float2 center_offset = (uv - 0.5) * uniforms.bounds.zw; float radius = min(uniforms.bounds.z, uniforms.bounds.w) * 0.5; float distance_from_center = length(center_offset); float edge_width = max(fwidth(distance_from_center), 0.5); if (shape_type == 3 && distance_from_center > radius) { coverage = 1.0 - smoothstep(radius - edge_width, radius + edge_width, distance_from_center); } if (shape_type == 4) { float outer_coverage = 1.0 - smoothstep(radius - edge_width, radius + edge_width, distance_from_center); float inner_coverage = smoothstep(radius - uniforms.params.y - edge_width, radius - uniforms.params.y + edge_width, distance_from_center); coverage = outer_coverage * inner_coverage; } } FSOutput output; output.color = uniforms.color; output.color.a *= coverage; return output; }