Search code examples
c#unity-game-enginegraphicshlslshaderlab

Efficient way to draw circles


I'm drawing circles in the following way:

for each pixel px
{
    if (isInside(px)) px.color =  white
    else px.color = black
}

bool isInside(pixel p)
{
    for each circle cir
    {
        if (PixelInsideCircle(p, cir)) return true
    }
    return false
}
    
bool PixelInsideCircle(pixel p, circle cir)
{
    float x = p.pos.x - cir.pos.x, y = p.pos.y - cir.pos.y;
    return x*x + y*y <= cir.radius*cir.radius
}

Here's the result:

image

There are around 50 circles. Any way to optimize it? I'm using unity3d. I'm filling the RenderTexture using compute shader and directly drew (Graphics.Blit) to the camera. I'm drawing only circles and I want to increase the circles from 50 to 1000. I've tried to use aabb and kd tree but could not figure out how to correctly implement it, using tree only worsen the performance. Thought to use intersection test for every column but not sure if it's a good idea. I'm making this for android and ios. Any help ?


Solution

  • I do not code in/with unity/C#/DirectX but if you insist on filling by pixels see

    for some ideas on easing the math ...

    I would not use compute shaders but render QUADS (AABB) for each circle instead using Vertex+Fragment shaders.

    As next step I would try to use Geometry shader that emits triangle fan around your circle (so the ratio between filled and empty space is better) this also require just center and radius instead of AABB so you can use POINTS instead of QUADS see:

    Its doing similar things (but its in GLSL). Also I noted you have:

    return (p.pos.x - cir.pos.x)^2 + (p.pos.y - cir.pos.y)^2 - (cir.radius)^2 <= 0 
    

    try to change it to:

    return (p.pos.x - cir.pos.x)^2 + (p.pos.y - cir.pos.y)^2 <= (cir.radius)^2
    

    its one less operation. Also (cir.radius)^2 should be passed to Fragment from Vertex (or Geometry) so it does not need to be computed on per pixel basis