aboutsummaryrefslogtreecommitdiff
path: root/docs/wiki/examples
diff options
context:
space:
mode:
authorKent Daleng <lolexplode@gmail.com>2025-08-17 16:05:41 +0200
committerGitHub <noreply@github.com>2025-08-17 17:05:41 +0300
commitdc93f1c1fd7b67e2da5af2ffada732b9ddeb2d6a (patch)
treea2f2938a7df17c196be7016dc5fe1fc9f75fb484 /docs/wiki/examples
parenta6febb86aa5af0df7bf2792ca027ef95a503d599 (diff)
downloadniri-dc93f1c1fd7b67e2da5af2ffada732b9ddeb2d6a.tar.gz
niri-dc93f1c1fd7b67e2da5af2ffada732b9ddeb2d6a.tar.bz2
niri-dc93f1c1fd7b67e2da5af2ffada732b9ddeb2d6a.zip
github wiki replacement / mkdocs-docs (#2147)
* Add wiki based on mkdocs * wording fixes * fix github bg color on narrow * Fix left sidebar section headers being bigger than pages * fix hover accent * fix list rendering on fractional layout * fix videos * fix automatic full links * remove redundant commented css * improve dark mode contrast * update pygments for better child node coloring * update logo * remove blank lines * add systemd language hint --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
Diffstat (limited to 'docs/wiki/examples')
-rw-r--r--docs/wiki/examples/close_custom_shader.frag147
-rw-r--r--docs/wiki/examples/open_custom_shader.frag128
-rw-r--r--docs/wiki/examples/resize_custom_shader.frag211
3 files changed, 486 insertions, 0 deletions
diff --git a/docs/wiki/examples/close_custom_shader.frag b/docs/wiki/examples/close_custom_shader.frag
new file mode 100644
index 00000000..fdd931ea
--- /dev/null
+++ b/docs/wiki/examples/close_custom_shader.frag
@@ -0,0 +1,147 @@
+// 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;
+}
+
+// Example: make the window 'fall down' with slight rotation.
+vec4 fall_and_rotate(vec3 coords_geo, vec3 size_geo) {
+ // For this shader, set animation curve to linear for best results.
+
+ // Simulate an accelerated fall: square the (linear) progress.
+ float progress = niri_clamped_progress * niri_clamped_progress;
+
+ // Get our rotation pivot point coordinates at the bottom center of the window.
+ vec2 coords = (coords_geo.xy - vec2(0.5, 1.0)) * size_geo.xy;
+
+ // Move the window down to simulate a fall.
+ coords.y -= progress * 200.0;
+
+ // Randomize rotation direction and maximum angle.
+ float random = (niri_random_seed - 0.5) / 2.0;
+ random = sign(random) - random;
+ float max_angle = 0.05 * random;
+
+ // Rotate the window around our pivot point.
+ float angle = progress * max_angle;
+ mat2 rotate = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
+ coords = rotate * coords;
+
+ // Transform the coordinates back.
+ coords_geo = vec3(coords / size_geo.xy + vec2(0.5, 1.0), 1.0);
+
+ // Sample the window texture.
+ vec3 coords_tex = niri_geo_to_tex * coords_geo;
+ vec4 color = texture2D(niri_tex, coords_tex.st);
+
+ // Multiply by alpha to fade out.
+ return color * (1.0 - niri_clamped_progress);
+}
+
+// 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 fall_and_rotate(coords_geo, size_geo);
+}
+
diff --git a/docs/wiki/examples/open_custom_shader.frag b/docs/wiki/examples/open_custom_shader.frag
new file mode 100644
index 00000000..0b3c8af9
--- /dev/null
+++ b/docs/wiki/examples/open_custom_shader.frag
@@ -0,0 +1,128 @@
+// 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 open_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 an area of unspecified size and location, so you must
+// expect and handle coordinates outside the [0, 1] range. The area will be
+// larger than the final window size to accommodate more varied effects.
+//
+// * 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 opaque.
+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 opaque.
+ color *= niri_clamped_progress;
+
+ return color;
+}
+
+// Example: gradually scale up and make opaque, equivalent to the default
+// opening animation.
+vec4 default_open(vec3 coords_geo, vec3 size_geo) {
+ // Scale up the window.
+ float scale = max(0.0, (niri_progress / 2.0 + 0.5));
+ 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 opaque.
+ color *= niri_clamped_progress;
+
+ return color;
+}
+
+// Example: show the window as an expanding circle.
+// Recommended setting: duration-ms 250
+vec4 expanding_circle(vec3 coords_geo, vec3 size_geo) {
+ vec3 coords_tex = niri_geo_to_tex * coords_geo;
+ vec4 color = texture2D(niri_tex, coords_tex.st);
+
+ vec2 coords = (coords_geo.xy - vec2(0.5, 0.5)) * size_geo.xy * 2.0;
+ coords = coords / length(size_geo.xy);
+ float p = niri_clamped_progress;
+ if (p * p <= dot(coords, coords))
+ color = vec4(0.0);
+
+ return color;
+}
+
+// This is the function that you must define.
+vec4 open_color(vec3 coords_geo, vec3 size_geo) {
+ // You can pick one of the example functions or write your own.
+ return expanding_circle(coords_geo, size_geo);
+}
+
diff --git a/docs/wiki/examples/resize_custom_shader.frag b/docs/wiki/examples/resize_custom_shader.frag
new file mode 100644
index 00000000..01246cdc
--- /dev/null
+++ b/docs/wiki/examples/resize_custom_shader.frag
@@ -0,0 +1,211 @@
+// 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 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) {
+ vec4 color = /* ...compute the color... */;
+ return color;
+}
+
+// It takes as input:
+//
+// * coords_curr_geo: coordinates of the current pixel relative to the current
+// 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 current window geometry (in
+// the middle of a resize). 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 an area of unspecified size and location, so you must
+// expect and handle coordinates outside the [0, 1] range. The area will be
+// large enough to accommodate a crossfade effect.
+//
+// * size_curr_geo: size of the current 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.
+
+// Previous (before resize) window texture.
+uniform sampler2D niri_tex_prev;
+
+// Matrix that converts geometry coordinates into the previous 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_prev;
+
+// Next (after resize) window texture.
+uniform sampler2D niri_tex_next;
+
+// Matrix that converts geometry coordinates into the next window texture
+// coordinates.
+uniform mat3 niri_geo_to_tex_next;
+
+
+// Matrix that converts coords_curr_geo into coordinates inside the previous
+// (before resize) window geometry.
+uniform mat3 niri_curr_geo_to_prev_geo;
+
+// Matrix that converts coords_curr_geo into coordinates inside the next
+// (after resize) window geometry.
+uniform mat3 niri_curr_geo_to_next_geo;
+
+
+// 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;
+
+// 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.
+vec4 solid_gradient(vec3 coords_curr_geo, vec3 size_curr_geo) {
+ vec3 coords = coords_curr_geo;
+ vec4 color = vec4(0.0);
+
+ // Paint only the area inside the current geometry.
+ if (0.0 <= coords.x && coords.x <= 1.0
+ && 0.0 <= coords.y && coords.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.y);
+ }
+
+ return color;
+}
+
+// Example: crossfade between previous and next texture, stretched to the
+// current geometry.
+vec4 crossfade(vec3 coords_curr_geo, vec3 size_curr_geo) {
+ // Convert coordinates into the texture space for sampling.
+ vec3 coords_tex_prev = niri_geo_to_tex_prev * coords_curr_geo;
+ vec4 color_prev = texture2D(niri_tex_prev, coords_tex_prev.st);
+
+ // Convert coordinates into the texture space for sampling.
+ vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo;
+ vec4 color_next = texture2D(niri_tex_next, coords_tex_next.st);
+
+ vec4 color = mix(color_prev, color_next, niri_clamped_progress);
+ return color;
+}
+
+// Example: next texture, stretched to the current geometry.
+vec4 stretch_next(vec3 coords_curr_geo, vec3 size_curr_geo) {
+ vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo;
+ vec4 color = texture2D(niri_tex_next, coords_tex_next.st);
+ return color;
+}
+
+// Example: next texture, stretched to the current geometry if smaller, and
+// cropped if bigger.
+vec4 stretch_or_crop_next(vec3 coords_curr_geo, vec3 size_curr_geo) {
+ vec3 coords_next_geo = niri_curr_geo_to_next_geo * coords_curr_geo;
+
+ vec3 coords_stretch = niri_geo_to_tex_next * coords_curr_geo;
+ vec3 coords_crop = niri_geo_to_tex_next * coords_next_geo;
+
+ // We can crop if the current window size is smaller than the next window
+ // size. One way to tell is by comparing to 1.0 the X and Y scaling
+ // coefficients in the current-to-next transformation matrix.
+ bool can_crop_by_x = niri_curr_geo_to_next_geo[0][0] <= 1.0;
+ bool can_crop_by_y = niri_curr_geo_to_next_geo[1][1] <= 1.0;
+
+ vec3 coords = coords_stretch;
+ if (can_crop_by_x)
+ coords.x = coords_crop.x;
+ if (can_crop_by_y)
+ coords.y = coords_crop.y;
+
+ vec4 color = texture2D(niri_tex_next, coords.st);
+
+ // However, when we crop, we also want to crop out anything outside the
+ // current geometry. This is because the area of the shader is unspecified
+ // and usually bigger than the current geometry, so if we don't fill pixels
+ // outside with transparency, the texture will leak out.
+ //
+ // When stretching, this is not an issue because the area outside will
+ // correspond to client-side decoration shadows, which are already supposed
+ // to be outside.
+ if (can_crop_by_x && (coords_curr_geo.x < 0.0 || 1.0 < coords_curr_geo.x))
+ color = vec4(0.0);
+ if (can_crop_by_y && (coords_curr_geo.y < 0.0 || 1.0 < coords_curr_geo.y))
+ color = vec4(0.0);
+
+ return color;
+}
+
+// Example: cropped next texture if it's bigger than the current geometry, and
+// crossfade between previous and next texture otherwise.
+vec4 crossfade_or_crop_next(vec3 coords_curr_geo, vec3 size_curr_geo) {
+ vec3 coords_next_geo = niri_curr_geo_to_next_geo * coords_curr_geo;
+ vec3 coords_prev_geo = niri_curr_geo_to_prev_geo * coords_curr_geo;
+
+ vec3 coords_crop = niri_geo_to_tex_next * coords_next_geo;
+ vec3 coords_stretch = niri_geo_to_tex_next * coords_curr_geo;
+ vec3 coords_stretch_prev = niri_geo_to_tex_prev * coords_curr_geo;
+
+ // We can crop if the current window size is smaller than the next window
+ // size. One way to tell is by comparing to 1.0 the X and Y scaling
+ // coefficients in the current-to-next transformation matrix.
+ bool can_crop_by_x = niri_curr_geo_to_next_geo[0][0] <= 1.0;
+ bool can_crop_by_y = niri_curr_geo_to_next_geo[1][1] <= 1.0;
+ bool crop = can_crop_by_x && can_crop_by_y;
+
+ vec4 color;
+
+ if (crop) {
+ // However, when we crop, we also want to crop out anything outside the
+ // current geometry. This is because the area of the shader is unspecified
+ // and usually bigger than the current geometry, so if we don't fill pixels
+ // outside with transparency, the texture will leak out.
+ //
+ // When crossfading, this is not an issue because the area outside will
+ // correspond to client-side decoration shadows, which are already supposed
+ // to be outside.
+ if (coords_curr_geo.x < 0.0 || 1.0 < coords_curr_geo.x ||
+ coords_curr_geo.y < 0.0 || 1.0 < coords_curr_geo.y) {
+ color = vec4(0.0);
+ } else {
+ color = texture2D(niri_tex_next, coords_crop.st);
+ }
+ } else {
+ // If we can't crop, then crossfade.
+ color = texture2D(niri_tex_next, coords_stretch.st);
+ vec4 color_prev = texture2D(niri_tex_prev, coords_stretch_prev.st);
+ color = mix(color_prev, color, niri_clamped_progress);
+ }
+
+ return color;
+}
+
+// This is the function that you must define.
+vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) {
+ // You can pick one of the example functions or write your own.
+ return stretch_or_crop_next(coords_curr_geo, size_curr_geo);
+}
+