↓
iaen.es Devlog Leer en español

Gotic · 9 min read

30 screen-space shaders in Godot 4 to choose my game's art style

Pixel art, oil paint, stained glass, thermal camera, VHS… 30 shaders that change the look of Gotic's whole island without touching a single model. Compare them on the farm by day and at the festival by night.

#shaders#art#godot#mods#tools

30 screen-space shaders in Godot 4 to choose my game's art style

All of Gotic's art is generated in code: houses, trees, people and animals are built from a few geometric shapes with flat colours. It works, but one day I wanted to know whether the game could look like something else without remaking a single model. That's how the filtros mod was born: a style study with 30 screen filters.

No filterOil paintNo filterOil paint

How it works

Each style is a canvas_item shader that reads the already rendered image (hint_screen_texture) and returns a new one. It lives in a ColorRect inside a CanvasLayer on layer −1, below the HUD (which sits on layer 1). The 3D world gets filtered while text, buttons and windows stay untouched.

layer = CanvasLayer.new()
layer.layer = -1          # HUD is on layer 1, windows on layer 2
rect = ColorRect.new()
rect.set_anchors_preset(Control.PRESET_FULL_RECT)
rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
rect.material = ShaderMaterial.new()

The trick has a limit: a canvas_item only sees colours, with no depth or normals. The outlines in the comic or neon styles come from colour changes. Sizes are measured as fractions of the screen height, because a phone has more pixels than the PC and a 3 px stroke would not look the same.

In game: K or the ESTILO button opens the list, F3 and F4 step back and forward, you can blend at 100, 70 or 40 % with the original image, and at the end there's an automatic slideshow that shows every style for 5 seconds.

What went wrong (and got redone)

None of them worked first time. Looking at full-size screenshots:

  • Pixel art painted the grass grey. The PICO-8 palette has no yellowish greens. It switched to Sweetie 16, with a colour distance that weighs hue more.
  • The CRT filled the screen with arcs. The phosphor mask, computed on the curved glass with a 1.33-pixel period, caused moiré. It now runs in screen coordinates, one whole pixel per colour.
  • Oil brush strokes came out like 1 px hair. Rotating coordinates by an angle that varies across the screen twists them far from the origin. Each stroke now rotates around its own centre.
  • At night, six styles went pitch black (Game Boy, ASCII, film noir, ink wash, pop art, engraving) because they used fixed thresholds. The fix was auto-exposure: the average light of nine fixed screen points, which changes nothing by day.
  • The thermal camera made the grass hot, and the kaleidoscope kept repeating grass until its wedge was aimed at the character.
  • Oil, pointillism and cross-stitch didn't convince at all and were rebuilt from scratch.

What I still don't know

All 1,148 checks in the test suite pass, including one that compiles all 30 shaders (headless Godot compiles them). But there are no FPS numbers on a phone: it got installed and the phone was locked. On paper the most expensive are oil (25 strokes sampled per pixel), pointillism, stained glass, VHS and the edge-detecting ones. The animated styles (VHS, glitch, psychedelia, kaleidoscope, CRT, old film) appear frozen on one frame here.

It's a development tool: before release it gets switched off or its folder removed. But one of these 30 may end up being Gotic's style.

The 30 styles

Click a screenshot to enlarge it and use the arrows to move between them. Switch between the farm at 8:00 and the Brumacosta festival at 22:00.

More from Gotic →