For some reason I have mostly documented my digital painting and old ink work here. Most likely because I wanted to document the bursts of Inktober related drawings while the watercolor paintings lack both such bursts but also an easy to grasp arc, interpunction in the flow of art.
I really should keep this more up to date. I always look back and there’s so many stuff I might have posted here and there on twitter and some chat channels but without leaving really any trace but for the selected few people that get entry to my makeshift studio and see all crap, mostly non-digital now.
Anyway, here are some recent things that seem not all bad at the current point in time.
Landscape and other paintings
Landscapes and cats, mostly 😄. The CC-based paintings are based off creative-commons licensed photos.
Made on request
Some pretty dark and somewhat personal inks. I’m kinda torn about such things. On one hand it’s really private and I don’t really want to talk about it beyond this artistic/symbolic expression, but not surprisingly, they also feel like very strong pieces.
I thought I document the process I figured out for myself of how to best approach doing watercolor painting based on digital sketches with the help of a DLP projector.
I have been working on my painting skills for some years now and ended up in a on/off relationship with watercolor. Did not like acrylpainting, did a limited amount of gouache painting and kept coming back to watercolor even though it made me quite mad at times.
One of the things I was very dissatisfied with was using pencil to sketch out my paintings. It was always a struggle to draw faint enough so that the markings wouldn’t bother me in the final result and also a lot of losing shapes and lines in the heat of things.
While I made my peace with watercolor not always coming out like you want to, it kept bothering me how I would also lose my sketch and had to start over from zero to redo a painting.
I discovered DLP (Digital Light Processing) projectors by accident in a youtube video. I wasn’t even aware that the technology existed and that it allows for devices that are very different from your clunky old projectors. The “digital micro mirrors” basically allow for fine-controlled projection that isn’t straight forward.
I ended up buying a “EKASN Mini Smart DLP Projector” which no longer seems to be avaible, which sadly often seems to happen, but I imagine that other devices based on the same DLP chips will work very similar.
My projector runs “Android TV” as operating system which offers a lot of options of how to get images on there, but in the end, the installed File explorer thing comes with a Browser based upload thing (with Chinese UI 🤣) that seems to work best.
Starting a Painting
When I want to paint a painting, it starts with the paper I want to paint on. I usually work with watercolor paper blocks, so I chose the texture and size I want.
So let’s say I use Arches cotton paper, 31cm x 23cm. That means I create a new image that has a nice big resolution that works well on my Cintiq. Usually I chose the larger dimension to be 1920 which is the FullHD width and also a good fit for the height on my screen with enough room on the left and right for palettes, toolbars and references and whatnot.
So for the Arches 31cm x 23cm in landscape format and a target width of 1920 pixel, we need a height of 1424px (1920 x 23 / 31). I usually tape my paintings to have a nice white border in the end, so I include that in my template and use the area for some simple projection markers.
Here I created a border for the painter’s tape I have which is 18mm wide. You can download the empty template in OpenRaster-format below. (I use OpenRaster so I can have a multi-layer image I can open in Krita as well as Gimp).
The example above has multiple sketch layers. For one the handdrawn sketch and then a layer with black at a low opacity where I planned the shadows for the scene.
When I do the shadows, I duplicate the shadows and use an edge filter to get the outlines for it, too. Then I save two different images. One just with the lines and one with the shadow layer.
Once I’m ready to start projecting, I save the projection images as PNG and run them through my preparation script.
if [ -z $1 ] || [ -z $2 ]; then
echo "Usage: c900prepare <image> <output>"
# scale to c900 native resolution, rotated if needed
convert $1 -rotate "90<" -scale 1280x720\! $2Code language: PHP (php)
This is a linux shell script using ImageMagick and the last line is the most important $1 is the input file here and $2 the output file.
If this all sounds to complicated for you, the basic idea of the command is that I scale down my projection images to the exact native resolution of the projector (1280×720). This scaling disregards the correct aspect ratio of the image and stretches it to fit. What the script also does is take care of the orientation. 1280×720 is obviously landscape format, but sometimes I want to project in portrait format that is higher than its wide. So this command rotates the image by 90 degrees if it is portrait format so that the former top of the image is to right which seems to be the easiest way to setup my projection equipment.
Setting up the projection
So I have my table top easel where I can adjust the angle, sometimes I work at an angle like this for controlled washes, sometimes I work flat. I bought these photography arms that I assembled to this McGyver-ed configuration. This way I can adjust my arms in all kinds of directions. I usually try have the projector a good length in front of me so that it doesn’t project downwards and I am always shadowing what I paint. By projecting from the front the shadows fall towards me and the area under my brush is as illuminated as possible.
As you can see the projection comes from quite an angle at the paper, but it still perfectly hits the square of it. The manual projection adjustment allows each corner of the projection to be moved pixel by pixel until it matches the canvas.
The projector position should be made to fit the paper as good as possible. Reset the projection if necessary and put the projector at a distance where all four corners of the paper are in the light. Make sure the image is centered on the paper.
Now use the projection adjustment to move the corners inwards until they match the paper. I usually adjust it so that the light creates a bit of shine outside of the paper and then adjust that so that the shine has the same brightness along the whole edge of the paper. This seems to be more precise than trying to have the slightly fuzzy projection edge match the paper edge (Arches paper also has a black binding which makes that even more difficult).
This process fixes the disregard of the aspect ratio in my preparation step as it stretches the projectors native resolution back to the aspect ratio of the paper I started out with. If I did my math right, the lines I draw around the image in my template match exactly with the inner border of my tape and the little projection marker boxes fill out the corners.
I really like to work this way, it allows me to work digitally on my sketches and move things around, scale them, copy and paste parts, whatever, the full digital convenience. If I fail to paint how I want, I can always restart with the same projection sketch. For some of my paintings sometimes I do three or four attempts.
It is no silver bullet. The projected lines are pretty strong if maybe a bit low resolution sometimes. It is still possible to get lost. Especially when I’ve already laid down the darker paint it can be hard to see the lines. I often flip back and forth between the projection image and an empty white image which can help to find lost lines. At some point it is just best to just let go of the projection and just work with the painting. I also have another android tablet for reference images. Mostly for color reference, but I also copy the projection image over to keep working with it while not actually projecting.
This year I felt like I could do an Inktober again. Life got in the way pretty badly and for a while I felt like doing Inktober was too much, but in the end it felt like it rather helped. In the end I ended up doing 21 of the 31 prompts.
“Day 15: Armadillo” and “Day 27: Snack” totally did not come out as intended. But by my extended Inktober rules, I just left them as-is. Redoing stuff when you’re on a daily schedule is just too much.
The others I think are all pretty good and also show a progression in drawing and composition skills compared to earlier years.
I decided it was time for me to rewatch Buffy and Angel and I wanted to do so in the right order. I found this blog post that gives a recommended order and what episodes are especially important to sync up because they reference the other series.
But the episodes are just listed with consecutive number. That in combination with Disney+ insisting to show me the German titles for the episodes made it necessary to keep counting to know when to jump over etc.
So I made myself another version of the list that shows the common season/episode codes for the episodes.
I often don’t actually post my paintings here, which I totally should. Here are some character paintings I did people in /r/characterdrawing
Granny Chanterelle, Tortle Circle of Spores Druid Tetra Erde, Chef Sorcerer, Tiefling (watercolor and gouache) Ophelia, Drow Cleric
In this post I will try to go through high-level design aspects of domainql-form. How I initially envisioned them to work and how they evolved over time driven by our experiences with it.
The first concept was really simple. We have a MobX domain object that represents the root object for the part of the domain we manage with the form, and then we have the <Form/> component that receives the object as value prop.
The <Field/> components reference paths within the object graph by lodash like paths. Here for our example “owner.name”, which first references the owner object that is embedded as property within the root object and then the name property within that owner object.
I mostly imagined one big <Form/> component per view.
This works and for large parts still works this way, but over time we slowly evolved into a more complex model.
The first thing that became on issue was the of course well-known fact that you can’t nest forms within HTML. And at first it seems like, duh, who would do something like that? But then you get a use-case where you have some form fields and then data-table connected to that object and then some more form fields. And of course, the <Datagrid/> needs to do all kinds of form control related things like choosing pagination sizes, letting the user enter filter values etc pp.
Problem: Awkard forms
While in some cases it is just natural to have sub-ordinate objects connected in the form and to edit fields within those, but as soon as you get to lists or deeply nested property paths it gets awkward very quickly, especially if you have to construct the paths dynamically.
Solution: Many Forms Paradigm
So we obviously need to be able to have many forms, often referencing the same object. But we also have cases where we want to edit the nth element out of a list of associated entities.
The form components now point anywhere they like. One root object, many root objects, objects within root objects, doesn’t matter.
We just have many forms that write into the same (non-isolated) objects. These <Form/> components all have their own <form/> elements. But what we want most of the time is that the forms behave as if they were one form.
If the user has entered erroneous data and there is an error displayed, all non-discarding buttons must be disabled. Only things like “Cancel” can remain enabled.
This orchestration of <Form/> component functionality is handled by the new FormContext class. There is a default context that is always used unless the application author created and referenced another FormContext. e.g. For processes that have to independent form-flows side-by-side or a main process and a sidebar-process.
The FormContext also registers all available memoized field-contexts which can be used to implement high-level form behavior on top of domainql-form.
This post is meant to collect my experiences with my new Wacom Cintiq graphics tablet in Ubuntu and document the current state of my configuration for posterity so that it may help others. It contains my Express Keys setup for Krita.
The documentation leaflets provided by Wacom seemed suboptimal to me. It was some IKEA style no-words-only-pictures thing that did not make quite clear to me which part was which.
In the end, I just decided to plug it in like it seemed right. And after connection power, HDMI plug and the USB-C cable for the input devices the whole thing worked perfectly. Graphics tablet was recognized with the right resolution, its own color profile and everything. I just needed to tell Ubuntu that his monitor is supposed to be below my normal one. I also had deactivated the key combinations to move windows between monitors in my Ubuntu configuration, because I never needed it and thus had to restore that.
At first I was disappointed that the pinch zoom gesture worked out-of-the-box in Krita, but I couldn’t get a multi-touch rotation bound to Krita’s canvas rotation.
Krita already very wisely prevents you from accidentally touch-painting on your graphics tablet. But in the end, the few times where it was nice to select tools with the non-dominant hand seemed not to worth it compared to the many times I inadvertently activated other parts of the UI like tool selections or the scroll bars. So I disabled touch for the graphics tablet.
My goal was to have the most common functionality I need for my paint workflow on the Express keys so that I can work without keyboard for larger stretches without moving between pen/express keys and keyboard/mouse operation too much.
The touch wheel does the canvas rotation and the mode-switch in the center just does a reset, which is a combination of resetting canvas rotation, resetting zoom and setting the tool to “Brush”.
Ring left and right are undo and redo, Ring down resets zoom only.
The left/right button pairs below the ring control brush size, opacity and brightness. The last two are less important to my paint workflow, but they are still useful sometimes and I have enough buttons.
The left/right pair on the bottom are pure modifier keys. Pressing control while in Brush mode activates the (mixing) color picker, but there’s a lot of functionality where ctrl and shift are modifiers in Krita.
The commands to set up this configuration are as follows:
xsetwacom --set "Wacom Express Key Remote Pad pad" Touch on
# experimental total touch prevention
xsetwacom --set "Wacom Cintiq Pro 32 Touch Finger touch" Touch off
# settings for krita (with some extra key configuration there)
# zoom (ctrl +/-) (not in diagram)
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 12 "key ctrl plus"
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 15 "key ctrl minus"
# rotation over touch wheel (ctrl ö/ä)
xsetwacom --set "Wacom Express Key Remote Pad pad" AbsWheelUp "key ctrl 0xd6"
xsetwacom --set "Wacom Express Key Remote Pad pad" AbsWheelDown "key ctrl 0xe4"
# wheel button left/right for undo/redo
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 2 "key ctrl z"
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 9 "key ctrl shift z"
# Mode resets rotation and tool to brush and zoom (no modes yet)
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 1 "key 5 b 1"
# wheel down: reset zoom only
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 10 "key 1"
# 1st row: Brush size ö/ä
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 11 "key +0xd6"
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 13 "key +0xe4"
# 2nd row: opacity
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 14 "key +i"
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 16 "key +o"
# 3rd row: color brightness
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 17 "key +k"
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 19 "key +l"
# bottom buttons: ctrl + shift
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 21 "key +ctrl"
xsetwacom --set "Wacom Express Key Remote Pad pad" Button 22 "key +shift"Code language: PHP (php)
As you can see, I put some functionality on the “ö” and “ä” keys that come with my German keyboard and which are always useful keys because they’re almost always free in the default key bindings.
Without a German keyboard, you obviously want other combos there. I think the ö/ä combos here are also the ones where I configured the extra key configuration in Krita to have them. All others are default keys I think.
The source code contains two zoom combos that are not in the diagram and which I might remove completely. I mostly try to work at 1:1 resolution on the graphics tablet anyway and rarely zoom in for details — and there’s always mouse wheel zoom.
Update: In the end I decided to buy the Wacom Flex arm which kind of made all this superfluous. Now I tend to just move the pad into a vertical-ish position slightly to the right so I can rotate my chair and work and have my full keyboard accessible on the left.
I was looking for a good looking dark theme for one of my toy projects and came across a bootstrap theme called “darkly” which looks nice but as so often, comes with a one of those snoopy Google fonts that can/do track you etc pp.
In this case it is even more annoying, because the actual font “Lato” is an open font.
So here it is: a version of the darkly bootstrap 4 theme with the font files to serve from the same server. The CSS uses relative addressing, i.e. the “css” and “webfonts” folder must be siblings on your server