Skip to main content

LINE

Constant LINE 

Source
pub const LINE: &str = "// World-space line pass: single source for every backend.\n//\n// The CPU expanded each line into a camera-facing ribbon whose corners already\n// sit off the line centre (gfx::lines::build_vertices), so the vertex stage\n// only applies the camera VP.\n//\n// Alpha does the two things a line needs: `edge` fades the outer pixel of the\n// ribbon so the line antialiases without MSAA, and the vertex colour\'s own\n// alpha carries the CPU-side distance fade. The pass binds no depth attachment\n// -- it runs after the main pass resolved -- so the fragment tests the resolved\n// scene depth itself, which is what lets an occluded line fade instead of\n// vanishing.\n//\n// USE_MSAA is a HOST difference rather than a target one: Vulkan reads the\n// multisampled main depth while Metal reads the resolved copy.\n\n#ifndef USE_MSAA\n#define USE_MSAA 0\n#endif\n\n// Per-frame view inputs, 80 B. Mirrors `LineView` in each backend\'s uniforms\n// module.\nstruct LineView\n{\n    // The main pass\'s view-projection (jittered when TAA is on), so a line\n    // lands on the same pixel the geometry it sits on did.\n    float4x4 vp;\n    // Alpha multiplier for the part of a line behind scene geometry. 0 hides\n    // occluded lines outright; a small value leaves a hint of the line showing\n    // through, which is what makes it useful for orienting in a dense scene.\n    float occluded_alpha;\n    float _pad0;\n    float _pad1;\n    float _pad2;\n};\n\n[[vk::binding(0, 0)]] ConstantBuffer<LineView> view : register(b0);\n\n#if USE_MSAA\n[[vk::binding(1, 0)]] Texture2DMS<float> scene_depth;\n#else\n[[vk::binding(1, 0)]] Texture2D<float> scene_depth;\n#endif\n\n// Matches `LineVertex` (32 B: pos at 0, edge at 12, colour at 16), which the\n// host input layouts declare and `line_vertex_layout_matches_shaders` pins.\nstruct LineVertexIn\n{\n    [[vk::location(0)]] float3 pos : POSITION;\n    [[vk::location(1)]] float edge : TEXCOORD0;\n    [[vk::location(2)]] float4 color : COLOR;\n};\n\n// The varyings lead deliberately: D3D packs a stage signature in declaration\n// order and links the two stages by matching semantic *and* register.\nstruct LineVertexOut\n{\n    [[vk::location(0)]] float edge : TEXCOORD0;\n    [[vk::location(1)]] float4 color : TEXCOORD1;\n    float4 position : SV_Position;\n};\n\n[shader(\"vertex\")]\nLineVertexOut line_vertex(LineVertexIn v)\n{\n    LineVertexOut o;\n    o.position = mul(view.vp, float4(v.pos, 1.0));\n    o.edge = v.edge;\n    o.color = v.color;\n    return o;\n}\n\nfloat line_scene_depth(int2 pixel)\n{\n#if USE_MSAA\n    return scene_depth.Load(pixel, 0);\n#else\n    return scene_depth.Load(int3(pixel, 0));\n#endif\n}\n\n[shader(\"fragment\")]\nfloat4 line_fragment(LineVertexOut i) : SV_Target\n{\n    // Ribbon edge fade: `edge` runs -1..1 across the width, so one pixel of its\n    // own screen-space derivative is the softest edge that still reads as a\n    // solid line.\n    float aa = max(fwidth(i.edge), 1e-4);\n    float coverage = 1.0 - smoothstep(1.0 - aa, 1.0, abs(i.edge));\n\n    // Manual depth test against the scene depth. The bias keeps a line drawn\n    // exactly on a surface (a ground-plane axis) from z-fighting itself into a\n    // dashed mess.\n    float scene_z = line_scene_depth(int2(i.position.xy));\n    float occlusion = (i.position.z > scene_z + 1e-6) ? view.occluded_alpha : 1.0;\n\n    float alpha = i.color.a * coverage * occlusion;\n    if (alpha <= 0.002)\n    {\n        discard;\n    }\n    return float4(i.color.rgb, alpha);\n}\n";
Expand description

line.slang.