---
title: Choosing a renderer
description: The cell renderer works everywhere. The shader renderer is faster on large surfaces. Which devices have it and what it can draw.
---

`Modifier.dither`, `Modifier.ditherFill`, `Modifier.ditherMask` and the `DitherText` and `DitherImage` components take a `renderer`:

| Value | Meaning |
| --- | --- |
| `DitherRenderer.Cells` | One rectangle per cell run on the canvas. The default. |
| `DitherRenderer.Shader` | One fragment shader for the element, when possible. |
| `DitherRenderer.Auto` | The shader above 20,000 cells, cells below. |

Both draw the same picture. In the tests, the shader output matches the cell output for every built-in field and Bayer size to within a handful of pixels in 40,000. The noise field matches exactly, because the cell renderer and the shader use the same float hash.

<iframe class="live-example" src="https://stipple-demo.vercel.app/?embed=1&animated=1#renderers" title="Live example: renderers" loading="lazy" allow="autoplay"></iframe>

## What the shader can draw

The shader renderer draws an element only if all of these hold. Otherwise the cell renderer draws it, with no error:

- the field is a `ShaderField`, which all the built-in fields except `ditherProgress`'s progress field are: `solid`, `linear`, `radial`, `noise`, `waves`, `ripples` and `sweep`;
- the pattern is Bayer 2, 4 or 8, or any pattern up to 256 cells wide, blue noise included (the shader reads it from a texture);
- the theme has two to eight colours, so a palette of up to eight works; cells can be squares or dots;
- the platform has runtime shaders, and the platform's compiler accepts the program.

For `ditherFill` and `ditherMask` the shader draws inside the offscreen layer those modifiers already use, so the content keeps its shape and transparency. The sweep's progress reaches the shader as a uniform, so an animated reveal compiles one program.

## Where it runs

| Target | Shader | Checked on |
| --- | --- | --- |
| Android 13 and later | AGSL `RuntimeShader` | Samsung SM-G991B, Android 15 (API 35) |
| Android 12 and earlier | None: cells | Not checked on a device |
| JVM desktop | Skia runtime effect | macOS, in the test suite |
| wasmJs | Skia runtime effect | Chromium and WebKit (the engine of Safari), headless, software GL |
| iOS | Skia runtime effect | **Unverified.** It compiles, and has not been run. |

Firefox has not been checked, and neither has Safari itself.
