[SOLVED] Large Shrinking circle

For a mobile BR like game what is the best way to do a reducing circle? Basically want a death zone.

On Pixi.js I was using a Graphics object and a shrinking mask, but moved the game from 2d to 3d.


One PlayCanvas user used a spotlight and reduced the radius over time which worked quite well.

Seems to me that the key thing is to ensure the circle is drawn with a fixed thickness as it shrinks.

To do that, I’d probably just write a custom bit of GLSL. Check out this example:


Run it here:

Thanks Will, will have a look at that, but very close to what I see. Would just need to allow the out side of the circle to be colored as well. but I can tweak in the glsl.

I’ve updated the code to do that for you.

Thanks, I was looking at it, while you made the change, and saw the change automatically.

1 Like

Is it also possible to apply this as a second pass to models. I know it would have to change so that it is not using the UV, but using the XZ position components.

So it would effectively pass over buildings and trees.

Yes, definitely you can do that too. I would probably just override the same emissive chunk but for the 3D models in my scene.

Will look at how to do that. In the shader how do I use the XYZ instead of the UV.

Also I take the discard would just return the current emission and not the changed value :slight_smile:

Been a while on GLSL which I’ve worked on. And first time in playcanvas. So learning.

Would need the world position of the vertex which is handily available in vPositionW which is type vec3.

Yep, you’d just leave emissive color as is for inside the circle rather than discard.

1 Like

To get this to happen on the diffuse color, or albedo. what chunk do I affect?

material.chunks.diffusePS = [
#ifdef MAPCOLOR”,
“uniform vec3 material_diffuse;”,
“uniform sampler2D texture_diffuseMap;”,
“uniform float circle_radius;”,
“uniform float circle_thickness;”,
“void getAlbedo() {”,
" dAlbedo = vec3(1.0);",
" #ifdef MAPCOLOR",
" dAlbedo *= material_diffuse.rgb;",
" #endif",
" #ifdef MAPTEXTURE",
" dAlbedo *= texture2DSRGB(texture_diffuseMap, $UV).$CH;",
" vec2 uv = $vPositionW.xz - vec2(0, 0);",
" if (length(uv) < circle_radius - circle_thickness * 0.5)",
" {",
" }",
" else if (length(uv) > circle_radius + circle_thickness * 0.5)",
" {",
" dAlbedo += vec3 (1, 0, 0);",
" }",
" #endif",
" #ifdef MAPVERTEX",
" dAlbedo *= gammaCorrectInput(saturate(vVertexColor.$VC));",
" #endif",


My fork of the project, with my changes.


I’ve change it to affect the position, based on the emissive map, but would like to affect the diffuse as well.

I have now fixed the issue. I had to go through the meshInstances and the materials on the models, and add them. The diffuse channel is working as well.

Thanks for your help will.

No worries, glad you got it sorted! :smiley:

How would you go about modifying this to work with ovals, squares, rectangles, etc?