[documentation/docs-krita-org/krita/4.3] /: GSoC 2020: Add Disney Animation's SeExpr as a new Fill Layer type

L. E. Segovia null at kde.org
Fri Aug 7 15:38:06 BST 2020


Git commit a71ad098ba1c33708d60365edf66fb8219674644 by L. E. Segovia.
Committed on 07/08/2020 at 14:37.
Pushed by lsegovia into branch 'krita/4.3'.

GSoC 2020: Add Disney Animation's SeExpr as a new Fill Layer type

This commit documents the SeExpr Fill Layer generator, as implemented in graphics/krita!380 and graphics/krita!411.

See !145

CCMAIL: kimageshop at kde.org
(cherry picked from commit 9bb62c8ea128d9c5a059438108a5c8492d10e3c6)

A  +-    --    images/layers/SeExpr-David-Revoy.jpg
A  +17   -0    images/seexpr/LICENSE.md
A  +-    --    images/seexpr/SeExpr_add_variable.png
A  +-    --    images/seexpr/SeExpr_add_variable_vector.png
A  +-    --    images/seexpr/SeExpr_editor.png
A  +-    --    images/seexpr/SeExpr_editor_preset_mgmt.png
A  +-    --    images/seexpr/SeExpr_editor_script_error.png
A  +-    --    images/seexpr/SeExpr_editor_widgets.png
A  +-    --    images/seexpr/SeExpr_first_render.png
A  +-    --    images/seexpr/SeExpr_overwrite_preset.png
A  +-    --    images/seexpr/SeExpr_prop_1.png
A  +-    --    images/seexpr/SeExpr_rename_preset.png
A  +-    --    images/seexpr/SeExpr_save.png
A  +-    --    images/seexpr/SeExpr_script.png
A  +-    --    images/seexpr/Se_voronoi_1.png
A  +-    --    images/seexpr/Se_voronoi_2.png
A  +-    --    images/seexpr/Se_voronoi_3.png
A  +-    --    images/seexpr/Se_voronoi_4.png
A  +-    --    images/seexpr/Se_voronoi_5.png
A  +67   -0    reference_manual/layers_and_masks/fill_layer_generators/seexpr.rst
M  +1    -0    reference_manual/layers_and_masks/fill_layers.rst
A  +51   -0    reference_manual/resource_management/seexpr_scripts.rst
A  +706  -0    reference_manual/seexpr.rst
A  +255  -0    tutorials/seexpr.rst

https://invent.kde.org/documentation/docs-krita-org/commit/a71ad098ba1c33708d60365edf66fb8219674644

diff --git a/images/layers/SeExpr-David-Revoy.jpg b/images/layers/SeExpr-David-Revoy.jpg
new file mode 100644
index 000000000..17dd7c4b4
Binary files /dev/null and b/images/layers/SeExpr-David-Revoy.jpg differ
diff --git a/images/seexpr/LICENSE.md b/images/seexpr/LICENSE.md
new file mode 100644
index 000000000..94ba4cf59
--- /dev/null
+++ b/images/seexpr/LICENSE.md
@@ -0,0 +1,17 @@
+The images Se_voronoi_*.png are under the following license:
+
+Copyright Disney Enterprises, Inc.  All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License
+and the following modification to it: Section 6 Trademarks.
+deleted and replaced with:
+
+6. Trademarks. This License does not grant permission to use the
+trade names, trademarks, service marks, or product names of the
+Licensor and its affiliates, except as required for reproducing
+the content of the NOTICE file.
+
+You may obtain a copy of the License at
+http://www.apache.org/licenses/LICENSE-2.0
+
diff --git a/images/seexpr/SeExpr_add_variable.png b/images/seexpr/SeExpr_add_variable.png
new file mode 100644
index 000000000..d611abebf
Binary files /dev/null and b/images/seexpr/SeExpr_add_variable.png differ
diff --git a/images/seexpr/SeExpr_add_variable_vector.png b/images/seexpr/SeExpr_add_variable_vector.png
new file mode 100644
index 000000000..74a66571f
Binary files /dev/null and b/images/seexpr/SeExpr_add_variable_vector.png differ
diff --git a/images/seexpr/SeExpr_editor.png b/images/seexpr/SeExpr_editor.png
new file mode 100644
index 000000000..843c7b344
Binary files /dev/null and b/images/seexpr/SeExpr_editor.png differ
diff --git a/images/seexpr/SeExpr_editor_preset_mgmt.png b/images/seexpr/SeExpr_editor_preset_mgmt.png
new file mode 100644
index 000000000..9d4146c98
Binary files /dev/null and b/images/seexpr/SeExpr_editor_preset_mgmt.png differ
diff --git a/images/seexpr/SeExpr_editor_script_error.png b/images/seexpr/SeExpr_editor_script_error.png
new file mode 100644
index 000000000..35316d3bc
Binary files /dev/null and b/images/seexpr/SeExpr_editor_script_error.png differ
diff --git a/images/seexpr/SeExpr_editor_widgets.png b/images/seexpr/SeExpr_editor_widgets.png
new file mode 100644
index 000000000..5b7d7e0e9
Binary files /dev/null and b/images/seexpr/SeExpr_editor_widgets.png differ
diff --git a/images/seexpr/SeExpr_first_render.png b/images/seexpr/SeExpr_first_render.png
new file mode 100644
index 000000000..24bd59fdf
Binary files /dev/null and b/images/seexpr/SeExpr_first_render.png differ
diff --git a/images/seexpr/SeExpr_overwrite_preset.png b/images/seexpr/SeExpr_overwrite_preset.png
new file mode 100644
index 000000000..0a6d18bdc
Binary files /dev/null and b/images/seexpr/SeExpr_overwrite_preset.png differ
diff --git a/images/seexpr/SeExpr_prop_1.png b/images/seexpr/SeExpr_prop_1.png
new file mode 100644
index 000000000..3a2017699
Binary files /dev/null and b/images/seexpr/SeExpr_prop_1.png differ
diff --git a/images/seexpr/SeExpr_rename_preset.png b/images/seexpr/SeExpr_rename_preset.png
new file mode 100644
index 000000000..66c209597
Binary files /dev/null and b/images/seexpr/SeExpr_rename_preset.png differ
diff --git a/images/seexpr/SeExpr_save.png b/images/seexpr/SeExpr_save.png
new file mode 100644
index 000000000..359c3db1d
Binary files /dev/null and b/images/seexpr/SeExpr_save.png differ
diff --git a/images/seexpr/SeExpr_script.png b/images/seexpr/SeExpr_script.png
new file mode 100644
index 000000000..a94db9bee
Binary files /dev/null and b/images/seexpr/SeExpr_script.png differ
diff --git a/images/seexpr/Se_voronoi_1.png b/images/seexpr/Se_voronoi_1.png
new file mode 100644
index 000000000..270bf786b
Binary files /dev/null and b/images/seexpr/Se_voronoi_1.png differ
diff --git a/images/seexpr/Se_voronoi_2.png b/images/seexpr/Se_voronoi_2.png
new file mode 100644
index 000000000..d937ddc01
Binary files /dev/null and b/images/seexpr/Se_voronoi_2.png differ
diff --git a/images/seexpr/Se_voronoi_3.png b/images/seexpr/Se_voronoi_3.png
new file mode 100644
index 000000000..fc2623628
Binary files /dev/null and b/images/seexpr/Se_voronoi_3.png differ
diff --git a/images/seexpr/Se_voronoi_4.png b/images/seexpr/Se_voronoi_4.png
new file mode 100644
index 000000000..72dc31aa6
Binary files /dev/null and b/images/seexpr/Se_voronoi_4.png differ
diff --git a/images/seexpr/Se_voronoi_5.png b/images/seexpr/Se_voronoi_5.png
new file mode 100644
index 000000000..8025849a2
Binary files /dev/null and b/images/seexpr/Se_voronoi_5.png differ
diff --git a/reference_manual/layers_and_masks/fill_layer_generators/seexpr.rst b/reference_manual/layers_and_masks/fill_layer_generators/seexpr.rst
new file mode 100644
index 000000000..64cd6bb89
--- /dev/null
+++ b/reference_manual/layers_and_masks/fill_layer_generators/seexpr.rst
@@ -0,0 +1,67 @@
+.. meta::
+   :description:
+        How to use SeExpr as a Fill Layer in Krita.
+
+.. metadata-placeholder
+
+   :authors: - L. E. Segovia <amy at amyspark.me>
+   :license: GNU free documentation license 1.3 or later.
+
+.. index:: SeExpr
+.. _seexpr_fill_layer:
+
+SeExpr
+------
+
+.. versionadded:: 4.3.1
+
+.. image:: /images/layers/SeExpr-David-Revoy.jpg
+
+Fills the layer with a pattern specified through Disney Animation's
+`SeExpr expression language <https://wdas.github.io/SeExpr>`_.
+
+.. seealso::
+    - :ref:`seexpr_tut_intro`
+    - :ref:`seexpr`
+    - :ref:`resource_seexpr_scripts`
+    - `"Procedural texture generator (example and wishes)" on Krita Artists <https://krita-artists.org/t/procedural-texture-generator-example-and-wishes/7638>`_
+    - `Inigo Quilez's articles <https://iquilezles.org/www/index.htm>`_
+    - `The Book of Shaders <https://thebookofshaders.com/>`_
+
+SeExpr is an embeddable, arithmetic expression language that enables you to
+write shader-like scripts. Through this language, Krita can add dynamically 
+generated textures like lava (example above), force fields, wood, marble, 
+etc. to your layers.
+
+As with Patterns, you can create your own and use those as well.
+For some examples, please check out the thread `"Procedural texture generator (example and wishes)" on Krita Artists <https://krita-artists.org/t/procedural-texture-generator-example-and-wishes/7638>`_.
+You can download them as a bundle through `Amyspark's blog <https://www.amyspark.me/blog/posts/2020/07/03/third-alpha-release.html>`_.
+
+Script
+    Select the desired preset out of any existing bundled presets.
+    This tab is identical to the Pattern preset selector.
+
+    .. image:: /images/seexpr/SeExpr_script.png
+
+Options
+    This tab allows you to edit the selected preset, and apply its script 
+    to the layer.
+
+    .. image:: /images/seexpr/SeExpr_editor.png
+
+    There are three sections. The first bar allows you to edit and save the selected preset:
+
+    .. image:: /images/seexpr/SeExpr_editor_preset_mgmt.png
+
+    If your script is syntactically correct, the middle box lets you
+    adjust its variables through widgets.
+
+    .. image:: /images/seexpr/SeExpr_editor_widgets.png
+
+    The lower box contains the script text, and shows the detected syntax 
+    errors, if any.
+
+    .. image:: /images/seexpr/SeExpr_editor_script_error.png
+
+    You can adjust how much space the latter two boxes have through their
+    splitter.
diff --git a/reference_manual/layers_and_masks/fill_layers.rst b/reference_manual/layers_and_masks/fill_layers.rst
index 2c474f91b..cbb08f8ca 100644
--- a/reference_manual/layers_and_masks/fill_layers.rst
+++ b/reference_manual/layers_and_masks/fill_layers.rst
@@ -7,6 +7,7 @@
    :authors: - Wolthera van Hövell tot Westerflier <griffinvalley at gmail.com>
              - Scott Petrovic
              - Alan
+             - L. E. Segovia <amy at amyspark.me>
    :license: GNU free documentation license 1.3 or later.
 
 .. index:: Layers, Fill, Generator
diff --git a/reference_manual/resource_management/seexpr_scripts.rst b/reference_manual/resource_management/seexpr_scripts.rst
new file mode 100644
index 000000000..815be24a8
--- /dev/null
+++ b/reference_manual/resource_management/seexpr_scripts.rst
@@ -0,0 +1,51 @@
+.. meta::
+   :description:
+        Creating and managing SeExpr script presets in Krita.
+
+.. metadata-placeholder
+
+   :authors: - L. E. Segovia <amy at amyspark.me>
+   :license: GNU free documentation license 1.3 or later.
+
+.. index:: Resources, SeExor
+.. _resource_seexpr_scripts:
+
+SeExpr Scripts
+==============
+
+.. image:: /images/seexpr/SeExpr_editor.png
+   :align: center
+
+SeExpr scripts allow you to render dynamically generated textures.
+They are saved as .se files.
+They can be used as fill for generated layers.
+
+.. seealso::
+    - :ref:`seexpr_tut_intro`
+    - :ref:`seexpr`
+    - :ref:`seexpr_fill_layer`
+    - `"Procedural texture generator (example and wishes)" on Krita Artists <https://krita-artists.org/t/procedural-texture-generator-example-and-wishes/7638>`_
+    - `Inigo Quilez's articles <https://iquilezles.org/www/index.htm>`_
+    - `The Book of Shaders <https://thebookofshaders.com/>`_
+
+Adding new scripts
+------------------
+
+Like with :ref:`resource_patterns`, there is a similar UI with which you
+can manage SeExpr presets.
+This panel is available by opening the Fill Layer dialog, and selecting
+:guilabel:`SeExpr`:
+
+.. image:: /images/seexpr/SeExpr_script.png
+    :align: center
+
+At the bottom of the tab, beneath the resource-filter input field, there are the :guilabel:`Import resource` and :guilabel:`Delete resource` buttons. Select the former to add presets to the list.
+
+Similarly, removing presets can be done by pressing the :guilabel:`Delete resource` button. Krita will not delete the actual file then, but rather black list it, and thus not load it.
+
+Temporary scripts
+-----------------
+
+Layers keep a copy of the textual script that was used to generate them.
+You can access it by going to the Options tab and copying the text.
+You can then paste it into a new SeExpr Fill Layer.
diff --git a/reference_manual/seexpr.rst b/reference_manual/seexpr.rst
new file mode 100644
index 000000000..f3bcd6477
--- /dev/null
+++ b/reference_manual/seexpr.rst
@@ -0,0 +1,706 @@
+.. meta::
+   :description:
+        SeExpr Quick Reference for Krita
+
+.. metadata-placeholder
+
+   :authors: - L. E. Segovia <amy at amyspark.me> (reStructuredText)
+             - Disney Enterprises, Inc. (for the original)
+   :license: GNU free documentation license 1.3 or later, Apache 2.0
+
+.. index:: Fill Layer, SeExpr
+
+.. _seexpr:
+
+======================
+SeExpr Quick Reference
+======================
+
+This page details all the available variables, functions, and operators in SeExpr.
+It is a heavily edited version of the official `user documentation <https://wdas.github.io/SeExpr/doxygen/userdoc.html>`_, adapted for usage with Krita.
+
+.. seealso::
+    - Source code at `KDE Invent <https://invent.kde.org/lsegovia/seexpr>`_
+    - Disney's SeExpr `API Documentation <http://wdas.github.io/SeExpr/doxygen/>`_
+
+.. seealso::
+    - :ref:`seexpr_tut_intro`
+    - :ref:`seexpr_fill_layer`
+    - :ref:`resource_seexpr_scripts`
+    - `"Procedural texture generator (example and wishes)" on Krita Artists <https://krita-artists.org/t/procedural-texture-generator-example-and-wishes/7638>`_
+    - `Inigo Quilez's articles <https://iquilezles.org/www/index.htm>`_
+    - `The Book of Shaders <https://thebookofshaders.com/>`_
+
+.. contents::
+
+*********
+Variables
+*********
+
+External variables
+==================
+
+These variables are provided by host applications, in this case Krita.
+They are registered with SeExpr's autocomplete help, which can be
+accessed by :kbd:`Ctrl+Space`.
+
+.. glossary::
+
+    $u, $v
+        Pixel position in normalized coordinates.
+
+    $w, $h
+        Image's width and height in pixels.
+
+Local Variables
+===============
+
+Local variables can be defined at the start of the expression::
+
+    $a = noise($P);
+    $b = noise($a * 1);
+    pow($a, 0.5) + $b
+
+External variables can also be overridden by local assignment. This can be useful to scale the noise frequency for instance::
+
+    $P = $P * 10; # increase noise frequency
+    fbm(vnoise($P) + $P/4)
+
+
+******************
+Control Structures
+******************
+
+SeExpr, unlike many languages, provides **no control structures** except
+a form of `if` statements, known as the *ternary operator*::
+
+    $u = $i < .5 ? 0.0 : 10.0
+
+*******************************************
+Operators (listed in decreasing precedence)
+*******************************************
+
+.. glossary::
+
+    [ a, b, c ]
+        vector constructor
+
+    $P[ n ]
+        vector component access
+
+        .. hint:: ``n`` must be 0, 1, or 2, e.g.::
+
+            $P[0]
+
+    ^
+        exponentiation
+
+        .. note:: Same as the ``pow`` function.
+
+    !
+        logical NOT
+
+    ~
+        inversion
+        
+        .. hint::
+            ::
+
+                ~$A
+
+            gives the same result as::
+
+                1 - $A
+
+    * /  %
+        multiply, divide, modulus
+
+        .. note:: ``%`` is the same as the ``fmod`` function.
+
+    + -
+        add, subtract
+
+    < >  <=  >=
+        comparison: less than, greater than, less or equal than, greater or equal than
+
+        .. note:: Only uses the first component of a vector.
+
+    ==  !=
+        equality, inequality
+
+    &&
+        logical AND
+
+    ||
+        logical OR
+
+    ? :
+        ternary ``if`` operator
+
+        .. hint:: Example::
+
+            $u < .5 ? 0 : 1
+
+    ->
+        apply - The function on the right of the arrow is applied to the expression on the left.
+
+        .. hint:: Examples::
+
+            $Cs -> contrast(.7) -> clamp(0.2, 0.8)
+            $u -> hsi(20, 1.2, 1, $Cs -> gamma(1.2))
+
+********************
+Assignment Operators
+********************
+
+Besides the basic assignment statement::
+
+    $foo = $bar
+
+you can also do operator assignments such as::
+
+    $foo += $bar;
+
+which is equivalent to::
+
+    $foo = $foo + $bar;
+
+Additionally, there are:
+
+- ``+=``
+- ``-=``
+- ``/=``
+- ``%=``
+- ``*=``
+- ``^=``
+
+********
+Comments
+********
+
+You can add comments to your script by using the ``#`` character.
+SeExpr will then skip the rest of the line for rendering purposes.
+However, they are not ignored; comments can still be used to declare
+the valid value range of integer, float, and vector variables.
+This enables you to manage them using widgets that will accept the
+specified range.
+
+.. hint::
+    ``$var0`` is an integer variable that ranges between 0 and 10 inclusive::
+
+        $var0 = 0; # 0, 10
+
+    ``$var1`` is a floating point variable with the same range::
+
+        $var1 = 0; # 0.000, 10.000
+
+    ``$var2`` is a vector variable::
+
+        $var2 = [0, 0, 0] # 0.000, 10.000
+
+    The latter is very helpful; SeExpr considers vectors with range ``[0, 1]`` as colors::
+
+        # this is a dark red
+        $color = [0.5, 0, 0] # 0.000, 1.000
+
+    In all cases, if not specified, the associated widgets' range will go from 0 to 1.
+
+For a multi-line expression, each line may have its own comment.
+
+*****************
+Logging Functions
+*****************
+
+.. glossary::
+
+    void **printf** ( string format, [param0, param1, ...] )
+        Prints a string to stdout that is formatted as given. Formatting
+        parameters possible are ``%f`` for float (takes first component of vector
+        argument) or ``%v`` for vector.
+
+        .. hint::
+            For example, if you wrote::
+
+                printf("test %f %v",[1,2,3],[4,5,6]);
+
+            you would get::
+
+                test 1 [4,5,6]
+
+***************************************
+Color, Masking, and Remapping Functions
+***************************************
+
+.. glossary::
+
+    float **bias** ( float x, float b)
+        Variation of gamma where control parameter goes from ``0`` to ``1`` with
+        values ``> 0.5`` pulling the curve up and values ``< 0.5`` pulling the curve
+        down.  Defined as ``pow(x, log(b)/log(0.5))``.
+
+    float **boxstep** ( float x, float a )
+    float **gaussstep** ( float x, float a, float b )
+    float **linearstep** ( float x, float a, float b )
+    float **smoothstep** ( float x, float a, float b )
+        The step functions are zero for ``x < a`` and one for ``x > b`` (or ``x > a`` in
+        the case of boxstep).  Between ``a`` and ``b``, the value changes
+        continuously between zero and one.  The ``gausstep`` function uses the
+        standard Gaussian "bell" curve which is based on an exponential
+        curve.  The ``smoothstep`` function uses a cubic curve.  Intuitively,
+        ``gausstep`` is has a sharper transition near one and a softer transition
+        near zero whereas ``smoothstep`` is has a medium softness near both one
+        and zero.
+
+    float **clamp** ( float x, float lo, float hi )
+        Constrain ``x`` to range ``[lo, hi]``.
+
+    float **compress** ( float x, float lo, float hi ) 
+        Compress the dynamic range from ``[0, 1]`` to ``[lo, hi]``.
+
+    float **contrast** ( float x, float c )
+        Adjust the contrast.  For ``c`` from ``0`` to ``0.5``, the contrast
+        is decreased.  For ``c > 0.5``, the contrast is increased.
+
+    float **expand** ( float x, float lo, float hi )
+        Expand the dynamic range from ``[lo, hi]`` to ``[0, 1]``.
+
+    float **fit** ( float x, float a1, float b1, float a2, float b2 )
+        Linear remapping of ``[a1..x..b1]`` to ``[a2..x..b2]``
+
+    float **gamma** ( float x, float g)
+        ``pow(x, 1/g)``
+
+    float **invert** ( float x )
+        Invert the value.  Defined as ``1 - x``.
+
+    color **hsi** ( color x, float h, float s, float i, float map=1 )
+        The ``hsi``  function shifts the hue by ``h`` (in degrees) and
+        scales thesaturation and intensity by ``s`` and ``i``
+        respectively.  A map may be
+        supplied which will control the shift - the full shift will happen
+        when the map is one and no shift will happen when the map is zero. 
+        The shift will be scaled back for values between zero and one.
+
+    color **hsltorgb** ( color hsl )
+    color **rgbtohsl** ( color rgb )
+        RGB to HSL color space conversion. 
+        HSL is Hue, Saturation, Lightness (all in range ``[0, 1]``).
+        These functions have also been extended to support RGB and HSL values
+        outside of the range ``[0, 1]`` in a reasonable way.  For any RGB or HSL
+        value (except for negative values), the conversion is well-defined
+        and reversible.
+
+    color **midhsi** ( color x, float h, float s, float i, float map, float falloff=1, int interp=0 )
+        The ``midhsi`` function is just like the ``hsi`` function except that the
+        control map is centered around the mid point (value of ``0.5``) and can
+        scale the shift in both directions. At the mid point, no shift
+        happens.  At *1.0*, the full shift happens, and at ``0.0``, the full
+        inverse shift happens.  Additional ``falloff`` and ``interp`` controls are
+        provided to adjust the map using the ``remap`` function.  The default
+        ``falloff`` and ``interp`` values result in no remapping.
+
+    float **mix** ( float a, float b, float alpha )
+        Blend of a and b according to alpha.  Defined as
+        ``a*(1-alpha) +b*alpha``.
+
+    float **remap** ( float x, float source, float range, float falloff, int interp )
+        General remapping function.  When ``x`` is within ``± range`` of source,
+        the result is one.  The result falls to zero beyond that range over
+        ``falloff`` distance.  The falloff shape is controlled by ``interp``.
+
+        .. note::
+            Numeric values or named constants may be used:
+
+            - int **linear** = 0
+            - int **smooth** = 1
+            - int **gaussian** = 2
+
+***************
+Noise Functions
+***************
+
+.. glossary::
+
+    float **cellnoise** ( vector v )
+    float **cellnoise1** ( float x )
+    float **cellnoise2** ( float x, float y )
+    float **cellnoise3** ( float x, float y, float z )
+    color **ccellnoise** ( vector v )
+        ``cellnoise`` generates a field of constant colored cubes based on the
+        integer location.  This is the same as the `PRMan cellnoise function <https://renderman.pixar.com/resources/RenderMan_20/cellnoise.html>`_.
+
+        .. note::
+            ``ccellnoise`` outputs color cellnoise.
+
+
+    float **fbm** ( vector v, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+    color **cfbm** ( vector v, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+    vector **vfbm** ( vector v, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+    float **fbm4** ( vector v, float time, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+    color **cfbm4** ( vector v, float time, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+    vector **vfbm4** ( vector v, float time, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+        ``fbm`` (Fractal Brownian Motion) is a multi-frequency noise function. 
+        The base frequency is the same as the ``noise`` function.  The total
+        number of frequencies is controlled by ``octaves``.  The ``lacunarity``
+        is the spacing between the frequencies - a value of 2 means each
+        octave is twice the previous frequency.  The ``gain`` controls how much
+        each frequency is scaled relative to the previous frequency.
+
+        .. note::
+
+            ``cfbm`` and ``cfbm4`` outputs color noise.
+
+            ``vfbm`` and ``vfbm4`` outputs vector noise.
+
+    float **hash** ( float seed1, [float seed2, ...] )
+        Like ``rand``, but with no internal seeds.  Any number of seeds may be
+        given and the result will be a random function based on all the
+        seeds.
+
+    float **noise** ( vector v )
+    float **noise** ( float x, float y )
+    float **noise** ( float x, float y, float z )
+    float **noise** ( float x, float y, float z, float w )
+    color **cnoise** ( vector v)
+    color **cnoise4** ( vector v, float t)
+    float **pnoise** ( vector v, vector period )
+    float **snoise** ( vector v)
+    float **snoise4** ( vector v, float t)
+    vector **vnoise** (vector v )
+    vector **vnoise4** (vector v, float t )
+        ``noise`` is a random function that smoothly blends between samples at
+        integer locations.  This is Ken Perlin's original noise function.
+
+        .. note::
+
+            ``cnoise`` and ``cnoise4`` output color noise.
+
+            ``noise4`` outputs signed vector noise.
+
+            ``pnoise`` outputs periodic noise.
+
+            ``snoise`` and ``snoise4`` output signed noise with range ``[-1, 1]``.
+
+            ``vnoise`` outputs signed vector noise.
+
+    float **rand** ( [float min, float max], [float seed] )
+        Random number between ``[min, max]`` (or ``[0, 1]`` if unspecified).
+        If a seed is supplied, it will be used in addition to the internal
+        seeds and may be used to create multiple distinct generators.
+
+    float **turbulence** ( vector v, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+    color **cturbulence** ( vector v, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+    vector **vturbulence** ( vector v, int octaves = 6, float lacunarity = 2, float gain = 0.5 )
+        ``turbulence`` is a variant of ``fbm`` where the absolute value of each
+        noise term is taken.  This gives a more billowy appearance.
+
+    float **voronoi** ( vector v, int type = 1, float jitter = 0.5, float fbmScale = 0, int fbmOctaves = 4, float fbmLacunarity = 2, float fbmGain = 0.5)
+    color **cvoronoi** ( vector v, int type = 1, float jitter = 0.5, float fbmScale = 0, int fbmOctaves = 4, float fbmLacunarity = 2, float fbmGain = 0.5)
+    vector **pvoronoi** ( vector v, float jitter = 0.5, float fbmScale = 0, int fbmOctaves = 4, float fbmLacunarity = 2, float fbmGain = 0.5)
+        ``voronoi`` is a cellular noise pattern. It is a jittered variant of
+        ``cellnoise``.
+        The type parameter describes different variants of the noise
+        function.  The ``jitter`` param controls how irregular the pattern is
+        (0 is like ordinary cellnoise).  The ``fbm...`` params can be
+        used to distort the noise field.  When ``fbmScale`` is zero (the
+        default), there is no distortion.  The remaining params are the same
+        as for the ``fbm`` function.
+
+        .. hint::
+
+            Voronoi types 1 through 5:
+
+            |image0|  |image1|  |image2|  |image3|  |image4| 
+
+        .. note::
+            ``cvoronoi`` returns a random color for each cell and
+            ``pvoronoi`` returns the point location of the center of the cell.
+
+
+*******************
+Selection Functions
+*******************
+
+.. glossary ::
+
+    float **choose** ( float index, float choice1, float choice2, [...] )
+        Chooses one of the supplied choices based on the index (assumed to be
+        in range ``[0, 1]``).
+
+    int **cycle** ( int index, int loRange, int hiRange )
+        Cycles through values between loRange and hiRange based on supplied
+        index.  This is an offset ``mod`` function.  The result is computed as
+        ``loRange + value % (hiRange-loRange+1)``.
+
+    int **pick** ( float index, int loRange, int hiRange, [ float weights, ... ] )
+        Picks values randomly between loRange and hiRange based on supplied
+        index (which is automatically hashed).  The values will be
+        distributed according to the supplied weights.  Any weights not
+        supplied are assumed to be 1.0.
+
+    float **wchoose** ( float index, float choice1, float weight1, float choice2, float weight2, [...] )
+        Chooses one of the supplied choices based on the index (assumed to be
+        in range ``[0, 1]``). The values will be distributed according to
+        the supplied weights.
+
+.. hint::
+
+    This example returns integer values between 1 and 10::
+
+        pick(value, 1, 10)
+
+    This example returns the values 1 and 2 twice and 2.5 times as often
+    respectively as compared to the other values (3-10)::
+
+        pick(value, 1, 10, 2, 2.5)
+
+    This example returns 10, 11, and 13 through 20 (12 is skipped due to zero weight)::
+
+        pick(value, 10, 20, 1, 1, 0)
+
+
+********************************************
+General Mathematical Constants and Functions
+********************************************
+
+.. glossary::
+
+    float **PI**
+        ::
+
+            float PI = 3.14159...
+
+    float **E**
+        ::
+
+            float E = 2.71828...
+
+.. glossary ::
+
+    float **abs** ( float x)
+        Absolute value of ``x``.
+
+    float **cbrt** ( float x )
+        Cube root.
+
+    float **ceil** ( float x )
+        Next higher integer.
+
+    float **exp** ( float x )
+        ``E`` raised to the ``x`` power.
+
+    float **floor** ( float x )
+        Next lower integer.
+
+    float **fmod** ( float x, float y )
+        Remainder of ``x / y``.
+
+        .. note:: Also available as the ``%`` operator.
+
+    float **log** ( float x )
+        Natural logarithm.
+
+    float **log10** ( float x )
+        Base 10 logarithm.
+
+    float **max** ( float a, float b )
+        Greater of ``a`` and ``b``.
+
+    float **min** ( float a, float b )
+        Lesser of ``a`` and ``b``.
+
+    float **pow** ( float x, float y )
+        ``x`` to the ``y`` power.
+
+        .. note:: Also available as the ``^`` operator.
+
+    float **round** ( float x )
+        Nearest integer.
+
+    float **sqrt** ( float x )
+        Square root.
+
+    float **trunc** ( float x )
+        Nearest integer towards zero.
+
+**********************
+Trigonometry Functions
+**********************
+
+.. glossary::
+
+    float **acos** ( float x )
+        Arc cosine.
+
+    float **acosd** ( float x )
+        Arc cosine in degrees.
+
+    float **acosh** ( float x )
+        Hyperbolic arc cosine.
+
+    float **asin** ( float x )
+        Arc sine.
+
+    float **asind** ( float x )
+        Arc sine in degrees.
+
+    float **asinh** ( float x )
+        Hyperbolic arc sine.
+
+    float **atan** ( float x )
+        Arc tangent.
+
+    float **atand** ( float x )
+        Arc tangent in degrees.
+
+    float **atan2** ( float y, float x)
+        Arc tangent of ``y/x`` between ``-PI`` and ``PI``.
+
+    float **atan2d** ( float y, float x )
+        Arc tangent in degrees of ``y/x`` between ``-180º`` and ``180º``.
+
+    float **atanh** ( float x )
+        Hyperbolic arc tangent.
+
+    float **cos** ( float x )
+        Cosine.
+
+    float **cosd** ( float x )
+        Cosine in degrees.
+
+    float **cosh** ( float x )
+        Hyperbolic cosine.
+
+    float **deg** ( float x )
+        Radians to degrees.
+
+    float **hypot** ( float x, float y )
+        Length of 2D vector ``[x, y]``.
+
+    float **rad** ( float x )
+        Degrees to radians.
+
+    float **sin** ( float x )
+        Sine.
+
+    float **sind** ( float x )
+        Sine in degrees.
+
+    float **sinh** ( float x )
+        Hyperbolic sine.
+
+    float **tan** ( float x )
+        Tangent.
+
+    float **tand** ( float x )
+        Tangent in degrees.
+
+    float **tanh** ( float x )
+        Hyperbolic tangent.
+
+****************
+Vector Functions
+****************
+
+.. glossary::
+
+    float angle ( vector a, vector b )
+        Angle between two vectors (in radians).
+
+    vector **cross** ( vector a, vector b )
+        Vector cross product.
+
+    float **dist** ( vector a, vector b )
+        Distance between two points.
+
+    float **dot** ( vector a, vector b)
+        Vector dot product.
+
+    float **length** ( vector v )
+        Length of vector.
+
+    vector **norm** ( vector v )
+        Vector scaled to unit length.
+
+    vector **ortho** ( vector a, vector b )
+        Vector orthographic to two vectors.
+
+    vector **rotate** ( vector v, vector axis, float angle )
+        Rotates ``v`` around axis by given ``angle`` (in radians).
+
+    vector **up** ( vector v, vector up )
+        Rotates ``v`` such that the Y axis points in the given ``up`` direction.
+
+
+**************
+Vector Support
+**************
+
+*Vectors* (points, colors, or 3D vectors) may be intermixed with *scalars*
+(simple floating point values).  If a scalar is used in a vector context, it is
+replicated into the three components, e.g. ``0.5`` becomes ``[0.5, 0.5, 0.5]``. 
+
+If a vector is used in a scalar context, only the first component is used.
+One of the benefits of this is that all the functions that are defined
+to work with scalars automatically extend to vectors.  For instance,
+``pick``, ``choose``, ``cycle``, ``spline``, etc., will work just fine
+with vectors.
+
+Arithmetic operators such as ``+``, ``*``, etc., and scalar functions are
+applied component-wise to vectors.  For example, applying the ``gamma``
+function to a map adjusts the gamma of all three color channels.
+
+***************
+Curve Functions
+***************
+
+Interpolation of parameter values to a set of control points is governed
+by the following functions.
+
+.. glossary::
+
+    color **ccurve** ( float param, float pos0, color val0, int interp0, float pos1, color val1, int interp1, [...] )
+        Interpolates color ramp given by control points at ``param``. Control
+        points are specified by triples of parameters ``pos_i``, ``val_i``, and
+        ``interp_i``.
+        
+        .. hint::
+            Interpolation codes are:
+
+            - 0 - none
+            - 1 - linear
+            - 2 - smooth
+            - 3 - spline
+            - 4 - monotone (non-oscillating) spline
+
+    float **curve** ( float param, float pos0, float val0, int interp0, float pos1, float val1, int interp1, [...] )
+        Interpolates a 1D ramp defined by control points at ``param``. Control
+        points are specified by triples of parameters ``pos_i``, ``val_i``, and
+        ``interp_i``.
+        
+        .. hint::
+            Interpolation codes are:
+
+            - 0 - none
+            - 1 - linear
+            - 2 - smooth
+            - 3 - spline
+            - 4 - monotone (non-oscillating) spline
+
+    float **spline** ( float param, float y1, float y2, float y3, float y4, [...] )
+        Interpolates a set of values to the parameter specified where
+        ``y1``, ..., ``yn`` are distributed evenly from ``[0, 1]``.
+
+**************
+Custom Plugins
+**************
+
+Custom functions may be written in C++ and loaded as one or more dynamic plugins.  See `Writing Custom Expression Plugins <https://wdas.github.io/SeExpr/doxygen/plugins.html>`_ for more details.
+
+.. warning:: This functionality is not supported in Krita.
+
+.. |image0| image:: /images/seexpr/Se_voronoi_1.png
+.. |image1| image:: /images/seexpr/Se_voronoi_2.png
+.. |image2| image:: /images/seexpr/Se_voronoi_3.png
+.. |image3| image:: /images/seexpr/Se_voronoi_4.png
+.. |image4| image:: /images/seexpr/Se_voronoi_5.png
diff --git a/tutorials/seexpr.rst b/tutorials/seexpr.rst
new file mode 100644
index 000000000..acd7e951e
--- /dev/null
+++ b/tutorials/seexpr.rst
@@ -0,0 +1,255 @@
+.. meta::
+   :description lang=en:
+        Introduction to SeExpr
+
+.. metadata-placeholder
+   :authors: - L. E. Segovia <amy at amyspark.me>
+   :license: GNU free documentation license 1.3 or later.
+
+.. _seexpr_tut_intro:
+
+Introduction to SeExpr
+======================
+
+.. versionadded:: 4.3.1
+
+   This document will introduce you to the SeExpr expression language.
+
+****************
+What is SeExpr?
+****************
+
+SeExpr is an embeddable expression language, designed by Disney Animation,
+that allows host applications to render dynamically generated content.
+Pixar calls it `in its documentation <https://renderman.pixar.com/resources/RenderMan_20/PxrSeExpr.html>`_ a "scriptable pattern generator and
+combiner".
+
+SeExpr is available within Krita as a Fill Layer.
+
+.. seealso::
+    - :ref:`seexpr`
+    - :ref:`seexpr_fill_layer`
+    - :ref:`resource_seexpr_scripts`
+    - `"Procedural texture generator (example and wishes)" on Krita Artists <https://krita-artists.org/t/procedural-texture-generator-example-and-wishes/7638>`_
+    - `Inigo Quilez's articles <https://iquilezles.org/www/index.htm>`_
+    - `The Book of Shaders <https://thebookofshaders.com/>`_
+
+**********
+Background
+**********
+
+To understand what SeExpr is about, we need to differentiate between two types
+of graphics, *raster* and *procedural*.
+
+The vast majority of the computer-generated stuff you see every day belong to
+the first type-- images like photos, your favourite anime screenshots, memes,
+are all a multitude of tiny little dots of color, or *pixels*, arranged into a
+grid.
+
+Raster graphics have two drawbacks. First, once you create them, their
+resolution is **fixed**. You cannot zoom in and magically get any more detail.
+And if you need to change them, either you go back to the source and sample it
+again (which is sometimes impossible), or edit it with a raster graphics
+program, like Krita.
+
+One of the biggest problems, however, is that we are always limited by the
+**space** our programs can use; either secondary storage, like SD cards, or
+RAM. Unless compressed, image memory needs are `quadratic in the size of the
+image <https://blender.stackexchange.com/questions/112505/why-is-my-half-resolution-render-taking-a-quarter-of-the-time-of-the-full-one>`_.
+For a quick example, the :ref:`create_new_document` dialog of Krita tells
+you three bits of information: its size in pixels, the size of the pixel
+itself, and *the total memory needed*.
+
+.. image:: /images/Krita_newfile.png
+
+Here's a summary for square textures. Note that the memory needed
+is for *one layer only*:
+
+===== ==============
+Size  Memory needed
+===== ==============
+256   256 KB
+512   1 MB
+1024  4 MB
+2048  16 MB
+4096  64 MB
+===== ==============
+
+An alternative is to use :ref:`vector_graphics`. Vector graphics, for instance 
+SVGs, employ mathematic formulae like splines and Bézier curves to describe a
+shape. As they are mathematically defined, they can be resized to suit your 
+needs without losing resolution.
+
+SeExpr belongs to a different class, *procedural graphics*. Similarly to vector
+graphics, procedural graphics only need a few KBs of secondary storage for
+their definition. But they are not defined by mathematical formulae; you
+actually *code* how the color is calculated at each point of the texture.
+And, because it is not limited in its precision, you can render complex
+patterns in your layers at completely arbitrary resolution.
+
+****************
+Writing a script
+****************
+
+In this tutorial, we'll show you how to write a script in SeExpr, render it to
+a layer, and then save it as a preset.
+
+We'll start by going to the :ref:`layer_docker`, and adding a new Fill Layer.
+Then select the SeExpr generator from the list. You'll be greeted by this
+window:
+
+   .. image:: /images/seexpr/SeExpr_editor.png
+
+The SeExpr generator dialog is divided in two tabs. For now, we'll stay on
+:guilabel:`Options`.
+
+.. note::
+   :ref:`fill_layers` describes these tabs in more detail.
+
+Let's start by painting a layer in light blue.
+
+First, SeExpr scripts must define an output variable, let's call it ``$color``.
+As SeExpr thinks of colors in the :ref:`RGB color space<model_rgb>`,
+color variables are defined by a triplet of numbers known as a *vector*.
+We'll start by defining the ``$color`` variable and giving it a value.
+
+Go to the text box, and clear it if it has any text.
+Then, define and set ``$color`` to something like ``[0.5, 0.5, 1]``
+(half lit red, half lit green, fully lit blue)::
+
+   $color = [0.5, 0.5, 1];
+
+SeExpr needs to know which variable holds the final color value. This
+is done by writing at the end, on its own line, the name of the variable::
+
+   $color
+
+The script should now look like this::
+
+   $color = [0.5, 0.5, 1];
+   $color
+
+Click :guilabel:`OK`, and you'll render your first script!
+
+   .. image:: /images/seexpr/SeExpr_first_render.png
+
+.. warning::
+   To be absolutely precise, SeExpr **has no color management**.
+   It always renders textures as :ref:`32-bit float <bit_depth>`,
+   :ref:`gamma corrected <linear_and_gamma>`,
+   sRGB images. Krita transforms them to your document's color space
+   using the sRGB-elle-V2-srgbtrc.icc profile.
+
+   See :ref:`color_managed_workflow` for what this means.
+
+**********************************
+Managing your script using widgets
+**********************************
+
+There is also another way to define and edit your variables.
+Open the fill layer's properties by right clicking on :guilabel:`Fill Layer 1`,
+and selecting :guilabel:`Layer Properties...`.
+
+.. image:: /images/seexpr/SeExpr_prop_1.png
+
+Notice the middle box? Once it detects a syntactically correct script,
+SeExpr enables a whole chunk of knobs to manage individual variables.
+In our example above, you can change ``$color``'s in three ways:
+
+- enter the red, green, or blue channel's value in the input fields
+- move the little colored sliders to change the respective channel
+- click on the preview square to the left of the boxes, to select a completely new color.
+
+The last button on the middle box is always :guilabel:`Add new variable`.
+Click it and this dialog will open:
+
+.. image:: /images/seexpr/SeExpr_add_variable.png
+
+This dialog shows you all the types of variables that SeExpr accepts:
+
+.. glossary ::
+
+   Curve and Color curve
+      They are the SeExpr version of :ref:`Stop Gradients <resource_gradients>`: they interpolate a ramp given by a set of values.
+
+      Curves represent 1D gradients, returning a single float at each evaluation point.
+
+      Color curves represent RGB gradients, returning a Color at each point.
+
+   Integers and Floats
+      Numbers.
+
+   Vector
+      A triplet of floats.
+
+   Color
+      A vector representing a RGB color.
+
+   Swatch
+      A list of Colors.
+
+   String
+      Usually single words.
+
+For instance, you could replicate ``$color`` in the :guilabel:`Vector` tab:
+
+.. image:: /images/seexpr/SeExpr_add_variable_vector.png
+
+**************************
+Creating your first preset
+**************************
+
+Once your script is ready, you can reuse it by making a preset.
+
+You can create one through the top bar of the Options tab:
+
+   .. image:: /images/seexpr/SeExpr_editor.png
+
+Select :guilabel:`Save New SeExpr Preset...` and the following dialog will
+open:
+
+  .. image:: /images/seexpr/SeExpr_save.png
+
+You can edit the name of the preset in the top line edit box, and set a  thumbnail for easy identification.
+
+.. hint :: The dialog will append "Copy" to the preset's name if it is a copy of an existing one. You can change it at will.
+
+The dialog provides the following choices for setting a thumbnail:
+
+.. glossary::
+
+   Load Existing Thumbnail
+      If the preset already has a thumbnail (for instance, if you created it from an existing preset), this button will load and apply it.
+
+   Load Image
+      Applies an image from the filesystem as a thumbnail.
+
+   Render Script to Thumbnail
+      Renders your script to a 256x256 texture, and applies the latter as a thumbnail.
+
+   Clear Thumbnail
+      Deletes the thumbnail. Note that, if the preset is a copy of an existing one, this can be reverted by clicking :guilabel:`Load Existing Thumbnail`.
+
+*************************
+Changing existing presets
+*************************
+
+If you change a preset's script, you will notice two new buttons in the top bar of the :guilabel:`Options` tab:
+
+   .. image:: /images/seexpr/SeExpr_overwrite_preset.png
+
+The reload button will restore the preset to its original properties, while clicking on :guilabel:`Overwrite Preset` will save your changes.
+
+Additionally, you can edit the preset's name by clicking on the rename button,
+entering the new name, and clicking on :guilabel:`Save`:
+
+   .. image:: /images/seexpr/SeExpr_rename_preset.png
+
+
+*********************
+Bundling your presets
+*********************
+
+Sharing your scripts is easy! SeExpr script presets are just like any other
+resource in Krita. Follow the instructions in :ref:`resource_management` to
+create your own bundles.


More information about the kimageshop mailing list