From cbebf86fb76109e13ecca6ead65fddef36a9f2d2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 30 Jun 2026 22:25:01 +0530 Subject: [PATCH] Port the bgimage shader --- kitty/shaders/bgimage.slang | 90 +++++++++++++++++++++++++++++++++++++ kitty/shaders/slang.py | 7 ++- 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 kitty/shaders/bgimage.slang diff --git a/kitty/shaders/bgimage.slang b/kitty/shaders/bgimage.slang new file mode 100644 index 000000000..684f3a4e1 --- /dev/null +++ b/kitty/shaders/bgimage.slang @@ -0,0 +1,90 @@ +#language slang 2026 +// Copyright (C) 2026 Kovid Goyal +// Distributed under terms of the GPLv3 license. + +import alpha_blend; + +// Constants and Macros +#define left 0 +#define top 1 +#define right 2 +#define bottom 3 +#define tex_left 0.0 +#define tex_top 0.0 +#define tex_right 1.0 +#define tex_bottom 1.0 + +#define x_axis 0 +#define y_axis 1 + +static const float2 tex_map[4] = { + float2(tex_left, tex_top), + float2(tex_left, tex_bottom), + float2(tex_right, tex_bottom), + float2(tex_right, tex_top) +}; + + +struct VertexOutput { + float2 texcoord : TEXCOORD; + float4 position : SV_Position; +}; + +// Helper Functions +float scale_factor(float window_size, float image_size) { + return window_size / image_size; +} + +float tiling_factor(int i, float4 sizes, float tiled) { + int window = i; + int image = i + 2; + return tiled * scale_factor(sizes[window], sizes[image]) + (1.0 - tiled); +} + +// Main Vertex Shader Entry Point +[shader("vertex")] +VertexOutput vertex_main( + uint vertex_id : SV_VertexID, + uniform float tiled, + uniform float4 sizes, + uniform float4 positions, +) { + const float2 pos_map[4] = { + float2(positions[left], positions[top]), + float2(positions[left], positions[bottom]), + float2(positions[right], positions[bottom]), + float2(positions[right], positions[top]) + }; + + + VertexOutput output; + // Calculate outputs + float2 tex_coords = tex_map[vertex_id]; + output.texcoord = float2( + tex_coords[x_axis] * tiling_factor(x_axis, sizes, tiled), + tex_coords[y_axis] * tiling_factor(y_axis, sizes, tiled) + ); + output.position = float4(pos_map[vertex_id], 0.0, 1.0); + return output; +} + +// Global Texture Bindings +uniform Sampler2D image; + +// Helper Functions +float4 alpha_blend(float4 color, float4 bg) { + // Performs standard linear alpha blending: src * src.a + dst * (1 - src.a) + float3 blended_rgb = color.rgb * color.a + bg.rgb * (1.0 - color.a); + float blended_alpha = color.a + bg.a * (1.0 - color.a); + return float4(blended_rgb, blended_alpha); +} + +// Main Fragment Shader Entry Point +[shader("fragment")] +float4 fragment_main(float2 texcoord: TEXCOORD, uniform float4 background) : SV_Target { + // Sample the texture using Slang's intrinsic texture object syntax + float4 color = image.Sample(texcoord); + // Compute final color with alpha blending + float4 premult_color = alpha_blend(color, background); + return premult_color; +} diff --git a/kitty/shaders/slang.py b/kitty/shaders/slang.py index 2603122f4..2dba04b17 100644 --- a/kitty/shaders/slang.py +++ b/kitty/shaders/slang.py @@ -341,8 +341,11 @@ def fixup_opengl_code(glsl_code: str) -> str: in_uniform_block = True in_uniform_block_contents = False line = '// ' + line - elif line.startswith('const ') and '] = {' in line: # }] - line = line.replace('{', f'{words[1]}[](', 1) # }]) + elif '] = {' in line: # }] this is https://github.com/shader-slang/slang/issues/11802 + typename = words[0] + if words[0] == 'const': + typename = words[1] + line = line.replace('{', f'{typename}[](', 1) # }]) line = line.removesuffix('};') + ');' lines.append(line) ans = '\n'.join(lines)