Hooray! Watercolor is paintop now! But…

From the very beginning, watercolor was conceived as brush engine. I think it is the best place for it. But it brings some troubles. The most important problem is how to make undo engine.

During a new stroke, the system can have previous strokes that continue to change. And it’s not clear how watercolor should behave with the rest of the engines. And I would like to ask your help. If you have any idea about it, please leave it in comments =)

Another problem is a speed. Now watercolor works very slowly (and only during a stroke).

Nevertheless, watercolor is paintop now. And I’d like to introduce you what it can do. I implemented all 5 strategies:



Wet on dry:


Wet on wet:







P. S.: Here you can look at funny color bug

когда что-то пошло не так.gif

That’s one small step for a man, one giant leap for GSoC project.

For the last month the main time I took the exams, because of this I did not do much for my project. Nevertheless, I implemented the basic primitives and tested them.

Let me tell you about them.

Wet map.

Water is the main part in watercolors. That’s why I started with this.

Wet map contains 2 types of information: water value and speed vector. If the first parameter is clear, then the second one needs explanations. Speed vector needs for rewetting our splats (take it in mind, I will explain what this later).

All this values Wet map contains in KisPaintDevice:

KisPaintDeviceSP m_wetMap;

As the color space was chosen rgb16:

m_wetMap = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb16());

And there are information about water value and speed vector in pixel data.

But in this form Paint Device can’t visualize wet map correctly:

So I transorm Paint Device for visualizing wet map correctly (because it will be important for artists, I think). And now it looks like this:


My implementation is based on a procedural brush. Every brush stamp is a union of dynamic splats. Here you can see the behavior of splats:

Also I tested reweting (when splat go to flowing state from fixed state):


And as a final test I made splat generator for simulating strokes:


What next?

It’s high time to get splats to work in Krita. So I’m going to finish my plugin, and test splats behavior. But it will be primitive:

  1. Clear canvas for updating splats
  2. No undo/redo
  3. Stupid singleton for splat storage

Who am I and what am I going to do

Hi there. My name is Grigory and I am a member of GSOC’17. At the moment I’m finishing the third year at the BMSTU (Moscow).

As my project for GSOC I’m going to do a watercolor brush for Krita.

I feel sure that some of you painted something with watercolors at
least once in your life. And, I dare assume, you know what is the main
feature of this technique. You don’t put pigment on the paper directly. What
remains on the canvas after a brush stroke is a pigment, dissolved in water.
That’s why the picture drawn with watercolors is largely dependent on the
motion of the pigment solution applied to the paper. This process is rather
difficult to simulate, because, depending on the environment, the system
will continue to change for some time after the artist finished painting.

At the moment, there are solutions to the problems of emulsion of watercolor paint, but either they are paid, or they only have a reproduction technique that is raw. For this reason, the task is to make a tool for Krita, capable of reproducing all the techniques of watercolor, because Krita – is a good open-source project for artists.

The basis of my project was the article published in: IEEE Transactions on Visualization and Computer Graphics ( Volume: 19, Issue: 5, May 2013 ).

At the core of this method, authors represent paint pigment as a
collection of dynamic “splat” particles, where each splat is a complex
polygon. Many such splats are placed along the trajectory of a stroke based
on rules controlled by different brush types, and then the vertices of these
splats are advected according to another set of rules at each time step.
Since it is impossible to imagine a watercolor without water, this
method allows to simulate the behavior of the water using a wetmap. It
consists of a 2D grid of cells. Water does not move on canvas and is stored
separately from the list of splats. Water can be added during the splats
adding to the system and individual action. The process of water drying is
simulated by reducing the values stored in grid of cells.

Every splat has three stages of life: flowing, fixed, and dried. When
first added to the canvas, a splat is flowing. In this state of slpat actively
“spreads” through the displacement of vertices. After some time, the splat
ceases to change and goes into the fixed state. While fixed, the splat can
potentially be rewetted to resume advection. After a period of time without
moving, the pigment is determined to have permanently stained the canvas
and the splat is considered dried. Going into this state, splat finally ceases
to change and is removed from the simulation.


To reproduce all possible effects of watercolor are used 5 types of
brushes. The brush types are simple, wet-on-dry, wet-on-wet, blobby, and
crunchy. Each uses a different arrangement of splats per stamp and has
different settings for the brush parameters.

The diameter of the splat d depends on the width of the brush w. Also, for controlling the behavior of splats, different brushes have different values of:

  • r – roughness (in pixels, default – 1 px);
  • f – flow (percentage, default – 100%).
  • l – lifetime of splat (in steps, default – 30).

Simple: The simple brush uses a single splat per stamp, and demonstrates nonuniform pigment distribution because of the random nature of the splat evolution, and blending between strokes due to the advection into surrounding wet portions of the canvas. The diameter d=w.

Wet-on-dry: Wet-on-dry places seven splats per stamp, with six arranged around the perimeter of the seventh at vge-i0ox160, where diameters d=w/2 . This causes the perimeter splats to collect around the edges of the stroke, adding additional pigment for an edge darkening appearance.

Wet-on-wet: Wet-on-wet places a small splat (d=w/2) inside a larger splat (d=3w/2) for each stamp. This results in a progressively darker region toward the center of the stroke for a feathered appearance characteristic of  applying pigment to a wet canvas.

Blobby: The blobby brush places four randomly sized splats (2rpgleyzlu0) in a cross pattern per stamp. Along with adding some noise to the splats color, this creates a more heavily nonuniform stroke shape and pigment density, similar to watercolor paint applied to a rougher canvas or with more granular pigment.

Crunchy: The crunchy brush places one splat per stamp (d=w), but sets r = 5 pixels, f = 25%, and l = 15 steps to reduce how far the vertices propagate while increasing the influence of the random walk component of the advection. The result is a stroke appearance that exhibits more significant branching and broken stroke texture, with very rough edges.

I have already implemented it in the context of the course project, but the final application requires significant improvements and optimizations. But you can look what my application can do 😀

So. If you have any questions, get in touch with me you can find on this website in a special sector.