Color pixels with a circle shape using setPixels32

Hi,

I’m looking to paint a GameObject with a circle shape, the center of the shape would be the coordinate where I hit.
Here is the code using SetPixel :

//We hit
        if (Physics.Raycast(cam.transform.position, cam.transform.forward, out _hit, weapon.range, mask))
        {
       
            //Get Coords of pixel we hit
            Vector2 pixelUV = _hit.textureCoord;
            //Get reference to gameObject rendered
            Renderer rend = _hit.transform.gameObject.GetComponent<Renderer>();
            //Get the gameObject texture
            Texture2D tex = rend.material.mainTexture as Texture2D;

            float pixelUVX = pixelUV.x;
            float pixelUVY = pixelUV.y;

            int centerX = (int)Mathf.Round(pixelUVX * tex.width);
            int centerY = (int)Mathf.Round(pixelUVY * tex.height);
       
            int radius = 12;
            for (int j = 0; j <= radius; j++) {

                for (int i = 0; i < 360; i ++) {

                    double angle = i * System.Math.PI / 180;
                    int x = (int)(centerX + j * System.Math.Cos(angle));
                    int y = (int)(centerY + j * System.Math.Sin(angle));

                    tex.SetPixel(x, y, currentColor);
                }
            }
            tex.Apply();
        }

It works, but :

  1. the circle is not perfect (but good enough though)
  2. it is very slow

I’ve heard about SetPixels32, apparently this method is way more faster than SetPixel, but I cant manage to make it work the way I want to. I cant figure out how to adapt my code to SetPixels32…
Could you help me out on this?

SetPixel is indeed slower than SetPixels. What I think you are looking for is the overload method for SetPixels, it hides at the bottom of the documentation very well :wink:
You might also want to use, GetPixels and also use its overload method to get the section to change.

public void SetPixels(int x, int y, int blockWidth, int blockHeight, Color[ ] colors, int miplevel = 0);
public Color[ ] GetPixels(int x, int y, int blockWidth, int blockHeight, int miplevel = 0);

Thanks for the advice, I think that is indeed the way to go!
However, I’m a bit confused on how to set the SetPixels to have a shape of circle. As I understand the method, x, y are the starting point, blockWidth and BlockHeight are the size of the block where the color will change (in otherworld, the number of pixels to change?) and colors array contains each color for each pixel.
How should I make the block the size/shape of a circle then?

for (int j = 0; j <= radius; j++) {

                for (int i = 0; i < 360; i++) {
                   
                    double angle = i * Mathf.PI / 180;
                    int x = (int)(centerX + j * System.Math.Cos(angle));
                    int y = (int)(centerY + j * System.Math.Sin(angle));
                    colors = ???
                    tex.SetPixels(x, y,  blockWidth,  blockHeight, colors, 0);
                }
            }

May I ask if you’re doing this as an exercise to learn how to use SetPixels/etc, or is this intended to be used in a game? If the latter, a combination of RenderTexture+LineRenderer will make better-looking results, will run faster, and will be easier.

Oh, I’ve never heard of that. That is indeed to be used in a game. I’ll look at it right now. If you have any advice on how to do so (draw a circle on runtime with a specific color), I’ll take any of them :slight_smile:
For your informations, the purpose is to draw a circle at click on a gameobject. What I was trying to do with SetPixels is to modify the texture on runtime, I’ve never thought of any other solution.

Since I’ve seen a question like this posted on the forums at least three times this week, I decided to write up a longer article on how to do this sort of thing with more detail. I’ll probably be finishing that later tonight, but you can read it as I write it here.

Wow ok, you’ve totally convinced me. I hope you will finish it soon enough :slight_smile:
Just a couple of informations that could potentially change the problem :

  • I’m trying to change 3D objects. The texture I’m painting is the one attached to the material which is attached to the 3D model.
  • Texture changing should be persistant, meaning when I’ll restart the game, textures should be keep their changes.

Also, textures will use network system, meaning textures will have to update to remote players too (and possibly hundreds of remote players)
Is render texture + line rendered still the best solution?

You will have to do a bit of work to save the render texture to a file (this page should help get started with that), but yes. Syncing the image across network should be even easier if anything, as you’ll be able to sync the objects being drawn rather than the resulting image itself.

Here are some links, the first is in regard to what @StarManta is doing. While the other gives explanation on what SetPixel(s) does in the background.