debug_lines.slang

cross platform rendering playground

src/passes/debug/debug_lines.slang

2.47 KB
#include "shared.h"
#include "renderer_types.h"

[vk::push_constant]
DebugLinesPushConstants pc;

struct DebugLineOut {
    vec4 position : SV_Position;
    vec4 color : TEXCOORD0;
};

// thick lines: each input (2 verts) protrudes to a camera-facing quad
// (6 verts / 2 triangles), widht is per-vertex px, averaged over endpoints
[shader("vertex")]
DebugLineOut vsThickMain(u32 vertexID: SV_VertexID) {
    DebugLineOut o;

    u32 line_idx = vertexID / 6;
    u32 corner = vertexID % 6;

    DebugLineVertexGPU va = pc.lines[line_idx * 2 + 0];
    DebugLineVertexGPU vb = pc.lines[line_idx * 2 + 1];
    FrameUBO frame = *pc.frame;

    vec4 ca = vec4(va.pos, 1.0) * frame.view_proj;
    vec4 cb = vec4(vb.pos, 1.0) * frame.view_proj;

    f32 wa = asfloat(va.width_bits);
    f32 wb = asfloat(vb.width_bits);
    f32 half_px = (wa + wb) * 0.25f;

    // degen: behind camera
    if (ca.w <= 0.0f || cb.w <= 0.0f || half_px <= 0.0f) {
        o.position = vec4(0.0, 0.0, 2.0, 1.0); // w=1, z beyond far -> clipped
        o.color = va.color;
        return o;
    }

    vec2 na = ca.xy / ca.w;
    vec2 nb = cb.xy / cb.w;

    // screen space direction (aspect-correct) for a stable perpendicular.
    vec2 pa = vec2(na.x * pc.viewport_w, na.y * pc.viewport_h);
    vec2 pb = vec2(nb.x * pc.viewport_w, nb.y * pc.viewport_h);
    vec2 d = pb - pa;
    f32 len = length(d);
    if (len < 1e-4) {
        o.position = vec4(0.0, 0.0, 2.0, 1.0);
        o.color = va.color;
        return o;
    }
    vec2 n = vec2(-d.y, d.x) / len;

    // grab endpoint + side for this corner.
    // tri 1: a+n, a-n, b+n | Tri 2: b+n, a-n, b-n
    vec4 c;
    vec2 off;
    f32 pick_w;
    if (corner == 0) {
        c = ca;
        off = n;
        pick_w = ca.w;
    } else if (corner == 1) {
        c = ca;
        off = -n;
        pick_w = ca.w;
    } else if (corner == 2) {
        c = cb;
        off = n;
        pick_w = cb.w;
    } else if (corner == 3) {
        c = cb;
        off = n;
        pick_w = cb.w;
    } else if (corner == 4) {
        c = ca;
        off = -n;
        pick_w = ca.w;
    } else {
        c = cb;
        off = -n;
        pick_w = cb.w;
    }

    vec2 off_clip = vec2(off.x * half_px / (pc.viewport_w * 0.5), off.y * half_px / (pc.viewport_h * 0.5)) * pick_w;
    o.position = vec4(c.xy + off_clip, c.zw);
    o.color = (corner == 2 || corner == 3 || corner == 5) ? vb.color : va.color;
    return o;
}

[shader("fragment")]
vec4 fsMain(DebugLineOut input) : SV_Target {
    return input.color;
}