You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I would like to extend the experimental custom pixel shader constant buffer (PixelShaderSettings) with the current and previous cursor rectangle, their resolved colors, and the timestamp of the last cursor change.
With those values, an HLSL shader could draw time-based cursor movement animations—such as trails, smears, and warps—without trying to infer the cursor position from the composited frame.
The current constant buffer tells a shader when it is running and how large the viewport is, but provides no cursor state: where the cursor is, where it was before the last move, what color it is actually drawn in, or when the move occurred.
This information cannot be recovered reliably from the framebuffer. There is no cursor marker or stencil, so a shader would need to distinguish the cursor from glyphs, selection highlights, and reverse-video content. Cursor shape and auto-resolved color make that heuristic less reliable, while the lack of a history buffer prevents the shader from retaining the source rectangle of an in-flight move. Blinking also removes the cursor from the frame entirely, making it appear to have moved or vanished.
The relevant data already exists on the CPU side near where the constant buffer is populated. Many cursor-motion effects in other terminals depend on this state. Ghostty, for example, exposes it as iCurrentCursor, iPreviousCursor, iCurrentCursorColor, iPreviousCursorColor, and iTimeCursorChange. Without an equivalent, these effects cannot be ported faithfully using the current API.
I have a working local prototype against main (AtlasEngine / BackendD3D), along with demo shaders and a screen recording. I am opening this issue first to determine whether the team is interested in this API and its proposed shape before submitting a PR.
terminal-shader-demo.mp4
Proposed technical implementation details
Append the following fields to the existing constant buffer so that shaders declaring only the current fields remain compatible:
cbuffer PixelShaderSettings
{
// existingfloat Time;
float Scale;
float2 Resolution;
float4 Background;
// proposedfloat4 CurrentCursor; // x, y, width, height — in pixelsfloat4 PreviousCursor; // same, before the last cursor changefloat4 CurrentCursorColor; // resolved, premultiplied RGBAfloat4 PreviousCursorColor; // same, before the last cursor changefloat TimeCursorChange; // value of Time at the last cursor change
};
The cursor rectangles use viewport pixels, with the origin at the top-left and positive x/y extending right/down. This is the same coordinate space as SV_POSITION.xy and Resolution. xy contains the top-left corner and zw the width and height of the rectangle actually drawn, including adjustments for bar, underscore, doubleUnderscore, and vintage cursor shapes.
The colors contain the values resolved by the built-in cursor renderer, including the #ffffff auto-color path and its perceivability adjustment. TimeCursorChange uses the same clock and 1000-second wrap as Time.
Proposed behavior:
Append the fields without changing the behavior of existing shaders.
Seed the previous cursor state from the current state when the shader is created or recreated, preventing an initial animation from (0, 0).
Track cursor geometry independently of the blink phase, so blinking is not treated as movement.
Reset the transition after scrolling, resizing, or render-setting changes to avoid trails across coordinate-space jumps.
The local prototype adds approximately 115 lines across common.h, AtlasEngine.cpp, BackendD3D.h, and BackendD3D.cpp, with no behavior change to the built-in cursor. I also created a small debug shader and SDF-based sample effects under samples/PixelShaders/.
I manually tested all five cursor shapes, blinking, scrolling, resizing, explicit and automatic cursor colors, shader recreation, and the existing sample shaders.
This proposal is limited to the uniforms themselves and one small demonstration shader. General HLSL shader chaining, built-in cursor effects, new settings UI, and shipping Ghostty shader ports are out of scope.
Questions for the team:
Is this kind of extension to the custom-shader contract acceptable?
Is the proposed uniform set and pixel-based coordinate system the shape you would prefer?
The prototype was developed with AI-assisted tooling (Codex, Claude Code). I have reviewed, built, and manually tested the implementation.
Description of the new feature
I would like to extend the experimental custom pixel shader constant buffer (
PixelShaderSettings) with the current and previous cursor rectangle, their resolved colors, and the timestamp of the last cursor change.With those values, an HLSL shader could draw time-based cursor movement animations—such as trails, smears, and warps—without trying to infer the cursor position from the composited frame.
The current constant buffer tells a shader when it is running and how large the viewport is, but provides no cursor state: where the cursor is, where it was before the last move, what color it is actually drawn in, or when the move occurred.
This information cannot be recovered reliably from the framebuffer. There is no cursor marker or stencil, so a shader would need to distinguish the cursor from glyphs, selection highlights, and reverse-video content. Cursor shape and auto-resolved color make that heuristic less reliable, while the lack of a history buffer prevents the shader from retaining the source rectangle of an in-flight move. Blinking also removes the cursor from the frame entirely, making it appear to have moved or vanished.
The relevant data already exists on the CPU side near where the constant buffer is populated. Many cursor-motion effects in other terminals depend on this state. Ghostty, for example, exposes it as
iCurrentCursor,iPreviousCursor,iCurrentCursorColor,iPreviousCursorColor, andiTimeCursorChange. Without an equivalent, these effects cannot be ported faithfully using the current API.I have a working local prototype against
main(AtlasEngine / BackendD3D), along with demo shaders and a screen recording. I am opening this issue first to determine whether the team is interested in this API and its proposed shape before submitting a PR.terminal-shader-demo.mp4
Proposed technical implementation details
Append the following fields to the existing constant buffer so that shaders declaring only the current fields remain compatible:
The cursor rectangles use viewport pixels, with the origin at the top-left and positive x/y extending right/down. This is the same coordinate space as
SV_POSITION.xyandResolution.xycontains the top-left corner andzwthe width and height of the rectangle actually drawn, including adjustments forbar,underscore,doubleUnderscore, andvintagecursor shapes.The colors contain the values resolved by the built-in cursor renderer, including the
#ffffffauto-color path and its perceivability adjustment.TimeCursorChangeuses the same clock and 1000-second wrap asTime.Proposed behavior:
(0, 0).The local prototype adds approximately 115 lines across
common.h,AtlasEngine.cpp,BackendD3D.h, andBackendD3D.cpp, with no behavior change to the built-in cursor. I also created a small debug shader and SDF-based sample effects undersamples/PixelShaders/.I manually tested all five cursor shapes, blinking, scrolling, resizing, explicit and automatic cursor colors, shader recreation, and the existing sample shaders.
This proposal is limited to the uniforms themselves and one small demonstration shader. General HLSL shader chaining, built-in cursor effects, new settings UI, and shipping Ghostty shader ports are out of scope.
Questions for the team:
The prototype was developed with AI-assisted tooling (Codex, Claude Code). I have reviewed, built, and manually tested the implementation.