diff options
Diffstat (limited to 'docs/wiki/examples')
| -rw-r--r-- | docs/wiki/examples/close_custom_shader.frag | 147 | ||||
| -rw-r--r-- | docs/wiki/examples/open_custom_shader.frag | 128 | ||||
| -rw-r--r-- | docs/wiki/examples/resize_custom_shader.frag | 211 |
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); +} + |
