aboutsummaryrefslogtreecommitdiff
path: root/wiki
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-05-12 09:52:21 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-12 09:52:36 +0400
commit9004c8395438038d69f7b479a8a9035663cb4be0 (patch)
tree349acfc1e9ac7df31bb52db66f7f9e8a59d19e79 /wiki
parent29c7552852874a08f9e70ed52ddfb6be8f55bc69 (diff)
downloadniri-9004c8395438038d69f7b479a8a9035663cb4be0.tar.gz
niri-9004c8395438038d69f7b479a8a9035663cb4be0.tar.bz2
niri-9004c8395438038d69f7b479a8a9035663cb4be0.zip
Implement custom shader for window-close anim
Diffstat (limited to 'wiki')
-rw-r--r--wiki/Configuration:-Animations.md41
-rw-r--r--wiki/examples/close_custom_shader.frag113
-rw-r--r--wiki/examples/resize_custom_shader.frag7
3 files changed, 159 insertions, 2 deletions
diff --git a/wiki/Configuration:-Animations.md b/wiki/Configuration:-Animations.md
index f228a5a8..9bc184eb 100644
--- a/wiki/Configuration:-Animations.md
+++ b/wiki/Configuration:-Animations.md
@@ -169,6 +169,47 @@ animations {
}
```
+##### `custom-shader`
+
+<sup>Since: 0.1.6, experimental</sup>
+
+You can write a custom shader for drawing the window during a close animation.
+
+See [this example shader](./examples/close-custom-shader.frag) for a full documentation with several animations to experiment with.
+
+If a custom shader fails to compile, niri will print a warning and fall back to the default, or previous successfully compiled shader.
+
+> [!WARNING]
+>
+> Custom shaders do not have a backwards compatibility guarantee.
+> I may need to change their interface as I'm developing new features.
+
+Example: close will fill the current geometry with a solid gradient that gradually fades away.
+
+```
+animations {
+ window-resize {
+ spring damping-ratio=1.0 stiffness=800 epsilon=0.0001
+
+ custom-shader r"
+ vec4 close_color(vec3 coords_geo, vec3 size_geo) {
+ vec4 color = vec4(0.0);
+
+ if (0.0 <= coords_geo.x && coords_geo.x <= 1.0
+ && 0.0 <= coords_geo.y && coords_geo.y <= 1.0)
+ {
+ vec4 from = vec4(1.0, 0.0, 0.0, 1.0);
+ vec4 to = vec4(0.0, 1.0, 0.0, 1.0);
+ color = mix(from, to, coords_geo.y);
+ }
+
+ return color * (1.0 - niri_clamped_progress);
+ }
+ "
+ }
+}
+```
+
#### `horizontal-view-movement`
All horizontal camera view movement animations, such as:
diff --git a/wiki/examples/close_custom_shader.frag b/wiki/examples/close_custom_shader.frag
new file mode 100644
index 00000000..8a777b99
--- /dev/null
+++ b/wiki/examples/close_custom_shader.frag
@@ -0,0 +1,113 @@
+// Your shader must contain one function (see the bottom of this file).
+//
+// It should not contain any uniform definitions or anything else, as niri
+// provides them for you.
+//
+// All symbols defined by niri will have a niri_ prefix, so don't use it for
+// your own variables and functions.
+
+// The function that you must define looks like this:
+vec4 close_color(vec3 coords_geo, vec3 size_geo) {
+ vec4 color = /* ...compute the color... */;
+ return color;
+}
+
+// It takes as input:
+//
+// * coords_geo: coordinates of the current pixel relative to the window
+// geometry.
+//
+// These are homogeneous (the Z component is equal to 1) and scaled in such a
+// way that the 0 to 1 coordinates lie within the window geometry. Pixels
+// outside the window geometry will have coordinates below 0 or above 1.
+//
+// The window geometry is its "visible bounds" from the user's perspective.
+//
+// The shader runs over the full screen area, so you must expect and handle
+// coordinates outside the [0, 1] range. If the window is scrolled off-screen,
+// all of the coordinates to the shader can fall outside the [0, 1] range.
+//
+// * size_geo: size of the window geometry in logical pixels.
+//
+// It is homogeneous (the Z component is equal to 1).
+//
+// The function must return the color of the pixel (with premultiplied alpha).
+// The pixel color will be further processed by niri (for example, to apply the
+// final opacity from window rules).
+
+// Now let's go over the uniforms that niri defines.
+//
+// You should only rely on the uniforms documented here. Any other uniforms can
+// change or be removed without notice.
+
+// The window texture.
+uniform sampler2D niri_tex;
+
+// Matrix that converts geometry coordinates into the window texture
+// coordinates.
+//
+// The window texture can and will go outside the geometry (for client-side
+// decoration shadows for example), which is why this matrix is necessary.
+uniform mat3 niri_geo_to_tex;
+
+
+// Unclamped progress of the animation.
+//
+// Goes from 0 to 1 but may overshoot and oscillate.
+uniform float niri_progress;
+
+// Clamped progress of the animation.
+//
+// Goes from 0 to 1, but will stop at 1 as soon as it first reaches 1. Will not
+// overshoot or oscillate.
+uniform float niri_clamped_progress;
+
+// Random float in [0; 1), consistent for the duration of the animation.
+uniform float niri_random_seed;
+
+// Now let's look at some examples. You can copy everything below this line
+// into your custom-shader to experiment.
+
+// Example: fill the current geometry with a solid vertical gradient and
+// gradually make transparent.
+vec4 solid_gradient(vec3 coords_geo, vec3 size_geo) {
+ vec4 color = vec4(0.0);
+
+ // Paint only the area inside the current geometry.
+ if (0.0 <= coords_geo.x && coords_geo.x <= 1.0
+ && 0.0 <= coords_geo.y && coords_geo.y <= 1.0)
+ {
+ vec4 from = vec4(1.0, 0.0, 0.0, 1.0);
+ vec4 to = vec4(0.0, 1.0, 0.0, 1.0);
+ color = mix(from, to, coords_geo.y);
+ }
+
+ // Make it transparent.
+ color *= (1.0 - niri_clamped_progress);
+
+ return color;
+}
+
+// Example: gradually scale down and make transparent, equivalent to the
+// default closing animation.
+vec4 default_close(vec3 coords_geo, vec3 size_geo) {
+ // Scale down the window.
+ float scale = max(0.0, ((1.0 - niri_clamped_progress) / 5.0 + 0.8));
+ coords_geo = vec3((coords_geo.xy - vec2(0.5)) / scale + vec2(0.5), 1.0);
+
+ // Get color from the window texture.
+ vec3 coords_tex = niri_geo_to_tex * coords_geo;
+ vec4 color = texture2D(niri_tex, coords_tex.st);
+
+ // Make the window transparent.
+ color *= (1.0 - niri_clamped_progress);
+
+ return color;
+}
+
+// This is the function that you must define.
+vec4 close_color(vec3 coords_geo, vec3 size_geo) {
+ // You can pick one of the example functions or write your own.
+ return solid_gradient(coords_geo, size_geo);
+}
+
diff --git a/wiki/examples/resize_custom_shader.frag b/wiki/examples/resize_custom_shader.frag
index 71710a9f..a95e678f 100644
--- a/wiki/examples/resize_custom_shader.frag
+++ b/wiki/examples/resize_custom_shader.frag
@@ -37,6 +37,9 @@ vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) {
// final opacity from window rules).
// Now let's go over the uniforms that niri defines.
+//
+// You should only rely on the uniforms documented here. Any other uniforms can
+// change or be removed without notice.
// Previous (before resize) window texture.
uniform sampler2D niri_tex_prev;
@@ -65,12 +68,12 @@ uniform mat3 niri_curr_geo_to_prev_geo;
uniform mat3 niri_curr_geo_to_next_geo;
-// Unclamped progress of the resize.
+// Unclamped progress of the animation.
//
// Goes from 0 to 1 but may overshoot and oscillate.
uniform float niri_progress;
-// Clamped progress of the resize.
+// Clamped progress of the animation.
//
// Goes from 0 to 1, but will stop at 1 as soon as it first reaches 1. Will not
// overshoot or oscillate.