import "includes/math"; import "includes/structs"; struct Varyings { float4 positionCS : SV_Position; nointerpolation uint instance; float2 positionSSPX; } struct GuiBox { float4 backgroundColor; float4 borderColor; float2 positionSSPX; float2 sizePX; float borderWidthPX; float borderRadiusPX; } [[vk::binding(0, 0)]] ConstantBuffer _Global; [[vk::binding(1, 0)]] StructuredBuffer _Boxes; static const float2 VERTICES[4] = { float2(0, 1), float2(1, 1), float2(0, 0), float2(1, 0), }; [shader("vertex")] Varyings vertexMain(uint vertexID : SV_VulkanVertexID, uint instanceID : SV_VulkanInstanceID) { Varyings out; let vertex = VERTICES[vertexID]; let box = _Boxes[instanceID]; let positionSSPX = vertex * box.sizePX + box.positionSSPX; let positionCS = float4(mul(_Global.matrixSSPXtoCS, float3(positionSSPX, 1.0)), 0.0, 1.0); out.positionCS = positionCS; out.instance = instanceID; out.positionSSPX = positionSSPX; return out; } [shader("fragment")] float4 fragmentMain(Varyings frag) : SV_Target { let box = _Boxes[frag.instance]; let halfExtentsPX = 0.5 * box.sizePX; let centerSSPX = box.positionSSPX + halfExtentsPX; let borderHalfWidthPX = 0.5 * box.borderWidthPX; let interiorSDF = boxSDF(frag.positionSSPX, centerSSPX, halfExtentsPX, box.borderRadiusPX) + box.borderWidthPX; float borderSDF = abs(interiorSDF - borderHalfWidthPX) - borderHalfWidthPX; float interiorCoverage = saturate(-interiorSDF + 0.5) * box.backgroundColor.a; float borderCoverage = saturate(-borderSDF + 0.5) * box.borderColor.a; float totalCoverage = interiorCoverage + borderCoverage; return float4( interiorCoverage * box.backgroundColor.rgb + borderCoverage * box.borderColor.rgb, totalCoverage, ); }