mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-21 12:42:25 +00:00
Proper fix for custom shader scaling on OS window grow + shrink
Some checks are pending
CI / Linux (python=3.14 cc=clang sanitize=1) (push) Waiting to run
CI / Linux (python=3.12 cc=gcc sanitize=0) (push) Waiting to run
CI / Linux (python=3.13 cc=gcc sanitize=1) (push) Waiting to run
CI / Linux package (push) Waiting to run
CI / Bundle test (macos-latest) (push) Waiting to run
CI / Bundle test (ubuntu-latest) (push) Waiting to run
CI / macOS Brew (push) Waiting to run
CI / Test ./dev.sh and benchmark (push) Waiting to run
CodeQL / CodeQL-Build (actions, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, macos-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (go, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (python, ubuntu-latest) (push) Waiting to run
Depscan / Scan dependencies for vulnerabilities (push) Waiting to run
Some checks are pending
CI / Linux (python=3.14 cc=clang sanitize=1) (push) Waiting to run
CI / Linux (python=3.12 cc=gcc sanitize=0) (push) Waiting to run
CI / Linux (python=3.13 cc=gcc sanitize=1) (push) Waiting to run
CI / Linux package (push) Waiting to run
CI / Bundle test (macos-latest) (push) Waiting to run
CI / Bundle test (ubuntu-latest) (push) Waiting to run
CI / macOS Brew (push) Waiting to run
CI / Test ./dev.sh and benchmark (push) Waiting to run
CodeQL / CodeQL-Build (actions, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, macos-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (go, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (python, ubuntu-latest) (push) Waiting to run
Depscan / Scan dependencies for vulnerabilities (push) Waiting to run
This commit is contained in:
parent
e55739bd10
commit
d124d4f097
5 changed files with 62 additions and 23 deletions
|
|
@ -284,11 +284,15 @@ the pipeline via the ``KittyTextures`` struct (``t.a``, ``t.b``, ``t.persist``).
|
|||
frame *N+1*. This allows effects that accumulate state over time (e.g.
|
||||
simulation steps, trails, fluid simulations).
|
||||
|
||||
All three named textures have the same pixel dimensions as the OS window
|
||||
viewport. They must be declared in the top-level ``textures`` directive before
|
||||
they can be referenced. A named texture that is the output target for the
|
||||
current group cannot simultaneously be sampled as input; kitty automatically
|
||||
substitutes the backbuffer in that case.
|
||||
All three named textures cover the same area as the OS Window viewport and are
|
||||
sampled in the same UV co-ordinate space as ``t.pos``, via the ``Sample()``
|
||||
method on ``KittyTexture``. Note that the underlying GPU textures can be larger
|
||||
than the viewport, since kitty grows them to fit the largest OS Window and
|
||||
never shrinks them again, so always sample via ``Sample()`` rather than using
|
||||
the raw ``tex`` sampler. They must be declared in the top-level ``textures``
|
||||
directive before they can be referenced. A named texture that is the output
|
||||
target for the current group cannot simultaneously be sampled as input; kitty
|
||||
automatically substitutes the backbuffer in that case.
|
||||
|
||||
**How groups chain together**
|
||||
|
||||
|
|
|
|||
|
|
@ -31,14 +31,13 @@ fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
|||
uv.y += 0.5f;
|
||||
|
||||
// Original Y pixel coordinate within the viewport (for scanline phase)
|
||||
float fragCoordY = (t.pos.y - t.viewport.y) * float(d.viewport_size_pixels.y);
|
||||
float fragCoordY = t.pos.y * float(d.viewport_size_pixels.y) * t.viewport.w;
|
||||
|
||||
// Scanline darkness at this pixel row
|
||||
float apply = abs(sin(fragCoordY) * 0.25f * SCAN);
|
||||
|
||||
// Sample the backbuffer at the warped viewport UV
|
||||
float2 sample_uv = t.viewport.xy + uv * t.viewport.zw;
|
||||
float3 col = t.backbuffer.Sample(sample_uv).rgb;
|
||||
float3 col = t.backbuffer.Sample(uv).rgb;
|
||||
// apply the tint
|
||||
col = lerp(col, col * TINT.rgb, TINT.a);
|
||||
|
||||
|
|
|
|||
|
|
@ -459,10 +459,6 @@ fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
|||
float timestamp = fmod(d.timestamp, 86400.0f) * TIME_SCALE;
|
||||
|
||||
float2 uv = t.pos;
|
||||
// d.src_rect.zy = (sx, sy) = (vw/W, vh/H): fraction of the shared texture used by this viewport.
|
||||
// Named textures (a, persist) and the backbuffer span the full W×H texture, so we must scale
|
||||
// t.pos back to raw texture UV when sampling them, otherwise we read outside the valid region.
|
||||
float2 tex_uv = uv * d.src_rect.zy;
|
||||
float aspect = pixelDims.x / max(pixelDims.y, 1.0f);
|
||||
|
||||
float2 mouseUV = (d.mouse_pos.xy - t.viewport.xy) / max(t.viewport.zw, float2(1e-5f, 1e-5f));
|
||||
|
|
@ -472,7 +468,7 @@ fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
|||
|
||||
// First group: Accumulate radial aurora rays cast from sky center into scratch texture 'a'
|
||||
if (STAGE == 0) {
|
||||
float prev = t.persist.Sample(tex_uv).r;
|
||||
float prev = t.persist.Sample(uv).r;
|
||||
float decayed = prev * saturate(1.0f - ACCUMULATION_DECAY);
|
||||
|
||||
float deposit = 0.0f;
|
||||
|
|
@ -513,7 +509,7 @@ fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
|||
}
|
||||
|
||||
// Second group: Copy scratch texture 'a' to 'persist'
|
||||
if (STAGE == 1) { return t.a.Sample(tex_uv); }
|
||||
if (STAGE == 1) { return t.a.Sample(uv); }
|
||||
|
||||
// Third group: Main composite pass
|
||||
AuroraRandParams rp = getAuroraParams(d.timestamp, INITIAL_RANDOM_SEED);
|
||||
|
|
@ -522,7 +518,7 @@ fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
|||
|
||||
float2 fragCoord = uv * pixelDims;
|
||||
|
||||
float persistentTrail = t.persist.Sample(tex_uv).r * MOUSE_PERSIST_INTENSITY;
|
||||
float persistentTrail = t.persist.Sample(uv).r * MOUSE_PERSIST_INTENSITY;
|
||||
|
||||
float3 ro = float3(0.0f, 0.0f, -CAMERA_DISTANCE);
|
||||
float2 centeredUV = uv - 0.5f;
|
||||
|
|
@ -562,7 +558,7 @@ fragment_main(float4 color, KittyTextures t, KittyCustomShaderData d) {
|
|||
float gate = smoothCutoff(effectLum, EFFECT_FLOOR, EFFECT_CEILING);
|
||||
col *= gate;
|
||||
|
||||
float4 terminalColor = t.backbuffer.Sample(tex_uv);
|
||||
float4 terminalColor = t.backbuffer.Sample(uv);
|
||||
float termLum = dot(terminalColor.rgb, float3(0.299f, 0.587f, 0.114f));
|
||||
float isBlack = step(termLum, 0.001f);
|
||||
float textPreserve = 1.0f - smoothstep(BLACK_BLEND_THRESHOLD, BLACK_BLEND_THRESHOLD + 0.2f, termLum);
|
||||
|
|
|
|||
|
|
@ -66,11 +66,25 @@ pipeline_fragment_main(float2 backbuffer_pos, int group, float4 viewport, float
|
|||
float4 color = backbuffer.Sample(backbuffer_pos); // pre multiplied linear RGB
|
||||
color = float4(color.rgb / color.a, color.a); // un pre multiplied color passed through pipeline
|
||||
// src_rect encodes (0, sy, sx, 0) — the fraction of the shared texture occupied by the current
|
||||
// viewport. Normalize backbuffer_pos so that t.pos is always in [0,1] viewport UV regardless of
|
||||
// whether the shared texture is larger than the current viewport (e.g. after a window shrink).
|
||||
// viewport. The shared texture is grown to fit the largest OS Window viewport and never
|
||||
// shrunk, so sx/sy are less than one whenever this window is smaller than that. Normalize
|
||||
// backbuffer_pos so that t.pos is always in [0,1] viewport UV and wrap the samplers so that
|
||||
// shaders can address them in that same space, regardless of the size of the shared texture.
|
||||
float2 src_scale = float2(max(1e-6, csd.src_rect[right]), max(1e-6, csd.src_rect[top]));
|
||||
float2 viewport_pos = backbuffer_pos / src_scale;
|
||||
KittyTextures t = { backbuffer, a, b, persist, viewport_pos, viewport, animation_progress, group };
|
||||
// Half a texel inset, in viewport UV, so that clamped samples do not bilinearly blend in the
|
||||
// stale texels that lie just outside the viewport region of the shared texture.
|
||||
float2 max_pos = 1.f - 0.5f / max(float2(csd.viewport_size_pixels), float2(1.f));
|
||||
KittyTextures t = {
|
||||
{ backbuffer, src_scale, max_pos },
|
||||
{ a, src_scale, max_pos },
|
||||
{ b, src_scale, max_pos },
|
||||
{ persist, src_scale, max_pos },
|
||||
viewport_pos,
|
||||
viewport,
|
||||
animation_progress,
|
||||
group
|
||||
};
|
||||
// PIPELINE
|
||||
return vec4_premul(color.rgb, color.a);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,17 +72,43 @@ public struct KittyCustomShaderData {
|
|||
public float cursor_trail_change_time;
|
||||
}
|
||||
|
||||
// A texture kitty renders into, addressed in the same UV co-ordinate space as
|
||||
// KittyTextures.pos. kitty renders into textures that are at least as large as
|
||||
// the largest OS Window viewport, so the pixels for the current OS Window
|
||||
// occupy only the lower-left corner of the texture after the window is made
|
||||
// smaller. Sampling via the Sample() method below hides that detail, so
|
||||
// shaders never need to know the size of the underlying texture.
|
||||
public struct KittyTexture {
|
||||
// The underlying texture. Use this only if you need raw texture UV,
|
||||
// remember to multiply your co-ordinates by scale below when you do.
|
||||
public Sampler2D tex;
|
||||
// The fraction of tex occupied by the OS Window viewport. Always in (0, 1].
|
||||
public float2 scale;
|
||||
// The largest usable co-ordinate for Sample() below. Half a texel less than
|
||||
// one, so that sampling the top/right edge does not blend in texels from
|
||||
// outside the viewport.
|
||||
public float2 max_pos;
|
||||
|
||||
// Sample this texture at pos, which is in the same UV co-ordinate space as
|
||||
// KittyTextures.pos, that is, [0, 1] with the origin at the bottom-left.
|
||||
// Co-ordinates outside that range are clamped to the edge of the viewport.
|
||||
public float4
|
||||
Sample(float2 pos) {
|
||||
return tex.Sample(clamp(pos, float2(0.f), max_pos) * scale);
|
||||
}
|
||||
}
|
||||
|
||||
public struct KittyTextures {
|
||||
// the buffer containing the original rendered pixels from kitty's own rendering. This will
|
||||
// be updated with the output color only after all custom shaders in this group have run
|
||||
public Sampler2D backbuffer;
|
||||
public KittyTexture backbuffer;
|
||||
// The following are named textures that can be sampled from in custom
|
||||
// shaders. The persist texture will persist across frames, anything
|
||||
// written to it in render number N can be read from it in subsequent
|
||||
// renders.
|
||||
public Sampler2D a;
|
||||
public Sampler2D b;
|
||||
public Sampler2D persist;
|
||||
public KittyTexture a;
|
||||
public KittyTexture b;
|
||||
public KittyTexture persist;
|
||||
|
||||
public float2 pos; // the position of this pixel in the viewport (UV coordinates, [0,1] range, origin at bottom-left)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue