Filling a shape with a gradient on ILI9341

Hi. I’m running a 2.8 ILI9431 off of an Wemos Mini D1 (or maybe even an ESP32) and wanted to see if anyone had already tackled this problem before I re-invent the wheel. I’m trying to fill shapes, such as a circle, arc, square, etc with a two color gradient. I’ve used a few different libraries, to draw and fill shapes with a single color, and that works fine. But I’d like to be able to fill those shapes ideally with a start and stop color, evenly distributed and perhaps specify a fill angle (horizontal, vertical, 45 degrees, and so on). I’d appreciate any help anyone can provide.


Bodmer already supports colour gradients. Just study the library code.

It should be fairly easy. You set a "window" and use pushColor() for each pixel. Adjusting the colour as you go. Horizontal or vertical gradients are easy. Diagonal gradients require quite a lot of maths.

Confession. I have not actually looked at Bodmer's code.


As David points out, certain types of gradient fills can be relatively easy to implement.

Depending on the graphics library you are using, many filled shapes (such as rectangles, triangles and circles) are usually rasterized by the library into horizontal “scan lines” (in a loop incrementing the Y-axis position). For example, in the case of a filled circle primitive, one generally “walks” along the Y-axis range, computing the start and endpoints of the horizontal lines that intercept the circumference. If you want a vertical (top-to-bottom) gradient, you would simply compute a new fill color during each Y loop iteration.

Computing the gradient itself is easy: most people simply use a linear interpolation algorithm to blend between two RGB values (the color stops) depending on the progression along the Y axis (in the case of vertical gradients). i.e., if you are blending from blue (0x00,0x00,0xFF) to red (0xFF,0x00,0x00) on a circle that ranges from Y=0 to Y=100, the color used at Y=25 might be (0x3F,0x00,0xBF).

Vertical gradients tend to be easier simply because most graphics libraries rasterize into horizontal scan lines for efficiency (due to pixel arrangement in memory). Horizontal gradients are done in a similar same way conceptually (i.e. you would generally walk the X axis producing vertical strips of the same color). The key here with horizontal and vertical gradients is that one is often outputting lines at a time (of a single color), enabling relatively fast rendering. The moment you start to use arbitrary-angled gradients, it is no longer straightforward to output strips of pixels with the same pixel value — which usually means per-pixel rendering instead of line-based rendering (with impact on performance since a color computation is now performed for every pixel).

Once you have the basic gradient blend, you might want to explore non-linear gradients or piece-wise linear gradients. For example, to create gradient buttons in my GUI library, it was a simple matter to define a gradient with 3 color stops (the start, midpoint and end), with a position (%) for the midpoint. This way, one can create an effect where the shape has a gradual gradient progression that then accelerates to a different color at the bottom, for example.

Have fun!