Whither Krita?

Moritz Moeller realritz at virtualritz.com
Sat Sep 19 12:25:24 CEST 2009


On 09/19/2009 06:14 PM, Dmitry Kazakov wrote:
> I've thought about something like that for Krita recently. And i've got
> the following idea:
>
> All the actions on the image (except of painting) could be based on adj.
> layers. E.g. if you want to change the size of the image (or switch to a
> different colorspace), you can just add a proper layer into the stack.
> If you do not want to have an additional layer, you can merge it down.

What you describe is essentially a node based system. With nodes 
arranged in a stack. Imho, any image editor is best absed on a node 
based system. Wether you exposed that to the user or not is a different 
question.
The advantange is: layers, layers with nested groups, sub-layers, 
adjustement layers, etc. -- all the stuff an app like Photoshop offers 
these days -- is a subset of the functionality of a node-based 
(procedural) graph describing the image.
This also gives one resolution independece, as long as filters are 
written in a way that bases anything they do on some abstract unit, a 
"point", (as opposed to pixels).

Most modern high end compositing packages (Nuke, Digital Fusion, etc) 
work this way. They also have powerful procedural paint ops, although 
they are not geared towards natural media painting (but there is no 
reason that they couldn't, its just the user base that doesn't need it).


A brush stroke is ideally recorded as a spline. That spline is converted 
into a 2d spline patch mesh. Width and direction (twist) of this patch 
can already be varied according to data read from the stylus when the 
user paints the stroke.
All other stylus data is attached, as variables, to the control points 
of the patch. It gets interpolated automatically when the patch mesh is 
tessellated for rendering (in real time) and is available to any brush 
engine that renders the brush.

This way you can edit brush strokes at any time, re-paint them (or 
subsections of them). And what is most interesting: write brushes that 
correctly antialias themselves.
The points on the tessellated patch are rectangular grids that can be 
processed in a SIMD manner.

Essentially, I'm suggesting a 2D implementation of the REYES dicing & 
shading pipeline for 2D brushes. Modern REYES implementations (3Delight, 
PRMan), archive interactive framerates dicing & shading 3d primitives 
with simpler shaders (with complexities comparable to those as would be 
found in a brush).
See http://en.wikipedia.org/wiki/Reyes_rendering

The shading rate during interaction (painting) can be adjusted to the 
speed of the user's system. When too slow, the brush is renderd with a 
low shading rate (a "point" in brush space maps to several pixels, in 
image space). When the system is idle next, the stroke is just 
re-rendered with the proper (higher) shading rate. When the user zooms, 
procedural brushes can re-render themseves, allowing for fractal brushes 
with unlimited detail etc.

This apporach allows reolution independent brushes. It also still allows 
for old school, bitmap-repetition-based brushes, by plain use of texture 
maps (that are painted as decals, on the patch mesh)

The main thing from the brush writer's perspective is that the whole 
thing is implicit. This means brushes have to be written as implicit 
functions with no knowledge about non-local data. Proper spot sizes (for 
the point [not pixel!]) for which the brush is evaluated, as well as 
derivatives of any variable or even user defined function, can be made 
available by the system, automagically, in an SIMD implementation of 
such an engine.
Finally, SIMD = perfectly suited for multi-threading.

The brushes could be written C++ or a specialized language or a fast 
enough scripting language (Lua comes to mind).

I.e. to write a brush that draws a line with a width matching the speed 
the user painted with (assuming this was not mapped to width of the patch):

brush myBrush() {
   /* x & y are pre-defined variables.
      x runs along the length,
      y along the width of the stroke
    */
   float speed = getvar( "speed" ); // we assume speed it inside 0..1
   float opacity = filterstep( 0.5 * ( 1 - speed ), y )
                   - filterstep( 0.5 * ( 1 + speed ), y );
   O = foo; // O = final opacity of brush
   C = O * getvar ( "color" ); // C = the final color of the brush
}

I assume filterstep() is a build-in function, doing a filtered step() of 
the variable under the threshold provided as the 1st argument.

I have several ideas as to how these brushes can be rendered (to allow 
e.g. smearing of the image the brush is applied to, or smearing the 
brush itself). These methods can be all made transparent from the 
brush-writer's perspective (aka: they don't have to care about this).

> This idea has many advantages:
> 1) We can keep design of the Krita extremely simple:
>    - a small kernel for managing stack
>    - a paintop kernel
> 2) All the featutures, like tranformation, CS-switch, channel-blending
> can be easily made as filters (mind! no kis_transformation_layer! its
> simply not needed)
> 3) A user will have a uniform interface(!) for all actions
> 4) At the moment, we have too much code duplication in Visitors that
> makes image/ design weird.

I agree 100%. Except for the implememtation. Instead of a stack I suggest.

1)   - a small kernel dealing with managing the graph of nodes
      - a paintop kernel (see above)
      - brushes are nodes themselves, making use of the paintop kernel

2)   - as Dmitry said. But: everything is based on points (not pixels) 
and the sizes of these points are available everywhere. Raw pixel are 
avaiable too, but writers of nodes/brushes are urged to make sure their 
creations function properly when the mapping of points to pixels is not 
1:1 (and/or the grid of points is not aligned with the grid of pixels).

There are several OSS REYES 3D implememtations that can serev as a 
tutorial on how to do this. A whole bunch of transformation maths 
becomes a lot simpler of course, as Krita would only need a 2D 
implementation.
Examples are http://pixie.sf.net/ http://aqsis.org



There is another few posts of mine, in the archives (from 2007, I 
think), where I already tried advertising these approaches. Might help 
digging the resp. thread out, to understand better where I'm coming from. :)


.mm


More information about the kimageshop mailing list