Fill a shape (ellipse) with a gradient

Hi, I am facing a problem that I can’t seem to find a solution online.

I have a basic game app with an ellipse that goes up and down automatically. What I try to accomplish is to have a gradient that fills the background and another that fills the ellipse. It is mostly for cosmetic purposes, but it is to fit the overall style I am looking for:

I basically created my ellipse as a shape, but I can’t seem to find how to add more than a flat color. How can I create a gradient to fill shapes?

This is what I use to create the ellipse:
this.ellipse = this.add.ellipse(game.config.width / 2, game.config.height / 2, size, size, color);

Shapes cannot have gradient fills. The only way to draw a primitive shape with a gradient is through a Graphics object, which is inefficient and doesn’t work the way you’d expect due to limitations with WebGL. The cleanest and easiest way to pull off the effect you need is to just use a textured image; if you need the ellipse’s color to change dynamically, you could use a grayscale image, then set its tint to the color you want. With additive tints, white will turn into the tint color, black won’t change, and in-between grays will be scaled appropriately.

If you insist on generating the effect at runtime, you could use a Canvas Texture, or combine a gradient-filled rectangle on a Graphics object with a Geometry Mask. Both of these solutions are complicated and rather inefficient (a Canvas Texture maintains an entire canvas that has to uploaded to the GPU, whereas a Graphics object has to constantly be redrawn).

Note that gradient fills in Graphics objects and tints work only on the WebGL renderer.

2 Likes

I’ve been using white image + tint quite a bit lately, its a handy trick.
Just noticed the corner tint option… looks like it might do the trick for a purely programmatic and flexible approach to a gradient:
https://labs.phaser.io/edit.html?src=src/display\tint\corner%20tint.js

Hmmm, are there any performance concerns with using tint?

Nope. During rendering, the tints for each vertex are sent to the vertex shader through attributes, then multiplied in the fragment shader. This is not expensive and it’s done for any textured Game Object on the screen, even ones with no tint set (the tint is, by default, white, which doesn’t change the color). Tint fills are handled in the same way.

However, I will repeat the fact that the canvas renderer doesn’t support tints. If it gets support for them in the future, they will likely be expensive to do on canvas. PIXI, the old renderer used in Phaser 2, supports them by copying the texture to an additional canvas and applying the effect manually, which requires more memory and makes tint updates slow. Anyhow, even if this does happen, it wouldn’t affect the WebGL renderer.

2 Likes