summaryrefslogtreecommitdiff
path: root/shaders/shape.vert.slang
blob: f7ea6b1a8542b48717adbe28b6c3565214548d4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
 * 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 <https://www.gnu.org/licenses/>.
 */

struct ShapeVertexUniforms {
    float4 bounds;
    float4 points[3];
    float4 viewport;
    float4 color;
    float4 params;
};

[[vk::binding(0, 1)]]
ConstantBuffer<ShapeVertexUniforms> 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;
}