power_play/src/ui/ui_shaders.g
2026-01-02 18:19:50 -06:00

149 lines
4.3 KiB
Plaintext

////////////////////////////////////////////////////////////
//~ Rect shader
//////////////////////////////
//- Vertex shader
VertexShader(UI_DRectVS, UI_DRectPSInput)
{
UI_DParams params = G_Dereference<UI_DParams>(UI_ShaderConst_Params)[0];
StructuredBuffer<UI_DRect> rects = G_Dereference<UI_DRect>(params.rects);
UI_DRect rect = rects[SV_InstanceID];
Vec2 rect_uv = RectUvFromVertexId(SV_VertexID);
Vec2 tex_uv = lerp(rect.tex_slice_uv.p0, rect.tex_slice_uv.p1, rect_uv);
Vec2 target_pos = lerp(rect.bounds.p0, rect.bounds.p1, rect_uv);
UI_DRectPSInput result;
{
result.sv_position = Vec4(NdcFromPos(target_pos, Vec2(params.target_size).xy), 0, 1);
result.rect_idx = SV_InstanceID;
result.base_background_premul = Premul(rect.background_lin);
result.base_border_premul = Premul(rect.border_lin);
result.tint_premul = Premul(rect.tint_lin);
result.debug_premul = Premul(rect.debug_lin);
result.rect_uv = rect_uv;
result.tex_uv = tex_uv;
}
return result;
}
//////////////////////////////
//- Pixel shader
PixelShader(UI_DRectPS, UI_DRectPSOutput, UI_DRectPSInput input)
{
UI_DParams params = G_Dereference<UI_DParams>(UI_ShaderConst_Params)[0];
StructuredBuffer<UI_DRect> rects = G_Dereference<UI_DRect>(params.rects);
SamplerState sampler = G_Dereference(params.sampler);
UI_DRect rect = rects[input.rect_idx];
Vec2 p = input.sv_position.xy;
Vec2 rect_uv = input.rect_uv;
Vec2 p0 = rect.bounds.p0;
Vec2 p1 = rect.bounds.p1;
//- Compute rect dist (negative means pixel is inside of rect)
f32 rect_dist = min(min(p.x - p0.x, p1.x - p.x), min(p.y - p0.y, p1.y - p.y));
{
f32 tl_radius = rect.tl_rounding;
f32 tr_radius = rect.tr_rounding;
f32 br_radius = rect.br_rounding;
f32 bl_radius = rect.bl_rounding;
Vec2 tl = Vec2(p0.x + tl_radius, p0.y + tl_radius);
Vec2 tr = Vec2(p1.x - tr_radius, p0.y + tr_radius);
Vec2 br = Vec2(p1.x - br_radius, p1.y - br_radius);
Vec2 bl = Vec2(p0.x + bl_radius, p1.y - bl_radius);
if (p.x < tl.x && p.y < tl.y) { rect_dist = min(rect_dist, tl_radius - length(tl - p)); }
if (p.x > tr.x && p.y < tr.y) { rect_dist = min(rect_dist, tr_radius - length(tr - p)); }
if (p.x > br.x && p.y > br.y) { rect_dist = min(rect_dist, br_radius - length(br - p)); }
if (p.x < bl.x && p.y > bl.y) { rect_dist = min(rect_dist, bl_radius - length(bl - p)); }
}
rect_dist = -rect_dist;
f32 rect_dist_fwidth = saturate(fwidth(rect_dist));
bool is_inside = rect_dist < 0;
//- Compute background color
Vec4 background_premul = 0;
if (is_inside)
{
if (G_IsRefNil(rect.tex))
{
background_premul = input.base_background_premul;
}
else
{
Texture2D<Vec4> tex = G_Dereference<Vec4>(rect.tex);
background_premul = tex.Sample(sampler, input.tex_uv);
background_premul.rgb *= background_premul.a;
}
}
//- Compute borer color
Vec4 border_premul = input.base_border_premul;
//- Compute border dist
f32 border_dist = 0;
border_dist = abs(rect_dist);
if (is_inside)
{
border_dist -= rect.border_size;
}
//- Compute anti-aliased border-over-background color
Vec4 composite_premul = 0;
{
f32 smoothness = rect_dist_fwidth * params.aa * 0.5;
f32 border_coverage = smoothstep(smoothness, -smoothness, border_dist);
composite_premul = lerp(background_premul, border_premul, border_coverage);
}
//- Finalize
Vec4 result = composite_premul * input.tint_premul;
if (UI_ShaderConst_DebugDraw)
{
result = input.debug_premul;
}
UI_DRectPSOutput output;
output.sv_target0 = result;
return output;
}
////////////////////////////////////////////////////////////
//~ Blit shader
//////////////////////////////
//- Vertex shader
VertexShader(UI_BlitVS, UI_BlitPSInput)
{
Vec2 uv = RectUvFromVertexId(SV_VertexID);
UI_BlitPSInput result;
result.sv_position = Vec4(NdcFromUv(uv).xy, 0, 1);
result.src_uv = uv;
return result;
}
//////////////////////////////
//- Pixel shader
PixelShader(UI_BlitPS, UI_BlitPSOutput, UI_BlitPSInput input)
{
UI_DParams params = G_Dereference<UI_DParams>(UI_ShaderConst_Params)[0];
Texture2D<Vec4> tex = G_Dereference<Vec4>(params.target_ro);
SamplerState sampler = G_Dereference(params.sampler);
Vec2 uv = input.src_uv;
Vec4 result = tex.Sample(sampler, uv);
UI_BlitPSOutput output;
output.sv_target0 = result;
return output;
}