diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-15 19:38:29 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-15 19:38:29 +0400 |
| commit | 5335ef454be4a1318dae36b1795a8578704f5d81 (patch) | |
| tree | a0fd289a1d3eb8662e95634b0cbf6511e4659a58 /wiki | |
| parent | 496cd59df98620e0e861ed9719321d64f3f636c9 (diff) | |
| download | niri-5335ef454be4a1318dae36b1795a8578704f5d81.tar.gz niri-5335ef454be4a1318dae36b1795a8578704f5d81.tar.bz2 niri-5335ef454be4a1318dae36b1795a8578704f5d81.zip | |
Implement custom shader for window-open
Diffstat (limited to 'wiki')
| -rw-r--r-- | wiki/Configuration:-Animations.md | 42 | ||||
| -rw-r--r-- | wiki/examples/open_custom_shader.frag | 113 |
2 files changed, 155 insertions, 0 deletions
diff --git a/wiki/Configuration:-Animations.md b/wiki/Configuration:-Animations.md index 28486719..d1d0fc9f 100644 --- a/wiki/Configuration:-Animations.md +++ b/wiki/Configuration:-Animations.md @@ -152,6 +152,48 @@ animations { } ``` +##### `custom-shader` + +<sup>Since: 0.1.6, experimental</sup> + +You can write a custom shader for drawing the window during an open animation. + +See [this example shader](./examples/open_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: open will fill the current geometry with a solid gradient that gradually fades in. + +``` +animations { + window-open { + duration-ms 250 + curve "linear" + + custom-shader r" + vec4 open_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 * niri_clamped_progress; + } + " + } +} +``` + #### `window-close` <sup>Since: 0.1.5</sup> diff --git a/wiki/examples/open_custom_shader.frag b/wiki/examples/open_custom_shader.frag new file mode 100644 index 00000000..d5d39cdb --- /dev/null +++ b/wiki/examples/open_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 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; +} + +// 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 solid_gradient(coords_geo, size_geo); +} + |
