[Logic] Paint with soft brush
Asked Answered
S

2

0

Hello everyone,

During the last few days i was coding a painting behavior for a game am working on, and am currently in a very advanced phase, i can say that i have 90% of the work done and working perfectly, now what i need to do is being able to draw with a “soft brush” cause for now it’s like am painting with “pixel style” and that was totally expected cause that’s what i wrote,

My current goal consist of using this solution :

  1. import a brush texture, this : 21317-brush_test.png
  2. create an array that contain all The alpha values of that texture
  3. When drawing use the array elements in order to define the new pixels alpha

And this is my code to do that (it’s not very long, there is too much comments)

//The main painting method
//theObject     = the object to be painted
//tmpTexture    = the object current texture
//targetTexture = the new texture 
void paint (GameObject theObject, Texture2D tmpTexture, Texture2D targetTexture)
{
	//x and y are 2 floats from another class
	//they store the coordinates of the pixel 
	//that get hit by the RayCast
	int x = (int)(coordinates.pixelPos.x);
	int y = (int)(coordinates.pixelPos.y);

	//iterate through a block of pixels that goes fro
	//Y and X and go #brushHeight Pixels up
	// and #brushWeight Pixels right
	for (int tmpY = y; tmpY<y+brushHeight; tmpY++) {
		for (int tmpX = x; tmpX<x+brushWidth; tmpX++) {
			//check if the current pixel is different from the target pixel
			if (tmpTexture.GetPixel (tmpX, tmpY) != targetTexture.GetPixel (tmpX, tmpY)) {
				//create a temporary color from the target pixel at the given coordinates
				Color tmpCol = targetTexture.GetPixel (tmpX, tmpY);
				//change the alpha of that pixel based on the brush alpha
				//myBrushAlpha is a 2 Dimensional array that contain
				//the different Alpha values of the brush
				//the substractions are to keep the index in range
				if (myBrushAlpha [tmpY - y, tmpX - x].a > 0) {
					tmpCol.a = myBrushAlpha [tmpY - y, tmpX - x].a;
				}
				//set the new pixel to the current texture
				tmpTexture.SetPixel (tmpX, tmpY, tmpCol);
			} 
		}
	}
	//Apply 
	tmpTexture.Apply ();
	//change the object main texture 
	theObject.renderer.material.mainTexture = tmpTexture;
}

Now the fun (and bad) part is the code did exactly what i asked for, but there is something that i didn’t think of and i couldn’t solve after spend the whole night trying,

the thing is that by asking to draw anytime with the brush alpha i found myself create a very weird effect which is decreasing the alpha value of an “old” pixel, so i tried to fix that by adding an if statement that check if the current alpha of the pixel is less than the equivalent brush alpha pixel, if it is, then augment the alpha to be equal to the brush, and if the pixel alpha is bigger, then keep adding the brush alpha value to it in order to have that “soft brushing” effect, and in code it become this :

if (myBrushAlpha [tmpY - y, tmpX - x].a > tmpCol.a) {
    tmpCol.a = myBrushAlpha [tmpY - y, tmpX - x].a;
} else {
    tmpCol.a += myBrushAlpha [tmpY - y, tmpX - x].a;
}

But after i’ve done that, i got the “pixelized brush” effect back, am not sure but i think maybe it’s because am making these conditions inside a for loop so everything is executed before the end of the current frame so i don’t see the effect, could it be that ?

Am really lost here and hope that you can put me in the right direction,

Thank you very much and have a great day

Standifer answered 15/11, 2023 at 15:43 Comment(2)

I also tried to break the conditions but still didn't get the willing effect

Standifer

@robertbu i don't know if answers.unity3D send notifications after user tagging, but if it did, i hope you have time to go through this and help me find a solution, thnx

Standifer
U
0

I suspect your using alpha differently than I would expect it to work as an artist in some of your calculations.

Let me explain alpha/opacity from an end user perspective ; and then you can see if your code is doing this? As from reading it it doesn’t seem to me like it is?

Brush Opacity : How much of the pixels information should be imprinted when the brush is applied.

Brush Alpha: For any one pixel on the brush a pixel might have an individual opacity (alpha) that differs from the overall painting opacity.

Example 1:

Brush Opacity 100%
Brush Alpha pixel 1: 100%
Brush Alpha pixel 2: 50%

I am painting BLUE pixels on a YELLOW canvas.

For pixel 1 : Opacity 100% and Pixel Alpha 100% the underlying YELLOW pixel is replaced with a BLUE pixel

For pixel 2: Opacity 100% and Pixel Alpha is 50% the underlying YELLOW pixel is mixed with 50% BLUE and becomes GREEN.

Example 2:

Brush Opacity 50%
Brush Alpha pixel 1: 100%
Brush Alpha pixel 2: 50%

I am still painting BLUE pixels on a YELLOW canvas.

For pixel 1 : Opacity 50% and Pixel Alpha 100% the underlying YELLOW pixel is mixed with a BLUE pixel and becomes GREEN.

For pixel 2: Opacity 50% and Pixel Alpha is 50% the underlying YELLOW pixel is mixed with 25% BLUE and becomes a light YELLOW-GREEN.

The canvas level yellow pixels alpha doesn’t come in to consideration most of the time. Its hue and saturation level would though.

The times when the canvas alpha might be important is in a document with multiple layers. When multiple layers are present often much of each layer is transparency (alpha) level lets pixels below it show through. If you are using multi-layer painting documents and find the layer you are paining on is fully transparent you have to make a choice to either treat it as a neutral canvas (no mixing of color needed) or to go down layers iteratively until it finds some color value to sample to use for color mixing modes.

Also in play might be what type of brush/painting you are trying to emulate? Airbrush? Oil paints? Acrylics? Etc.

Also in play most paint programs offer a range of brush tool options like ‘screen’, ‘burn’, ‘dodge’, ‘multiply’ etc. These affect the output also.

It sounds like to me when you say pixel art you mean close to how most art programs emulate a ‘pencil’ brush. It overwrites whatever is beneath it most of the time; the opacity rules above might apply though. Color mixing in pencil brushes is usually more of an ‘overlay’ rather than the ‘mix’ I applied.

Its actually more difficult to mix colors than you might realize on a canvas. In real life something like airbrush does this easiest. Oil paints on a canvas you usually pre-mix the paint on your pallet before applying it to the canvas otherwise its going to be streaky and not evenly mixed… although that can be a desired effect some times too :slight_smile:

Its all in what you desire the intended end result to look & feel like.

Unasked answered 15/11, 2023 at 11:53 Comment(2)

thank you !! all what you said helped me figuring out something very important, i was replacing the current pixel alpha by the brush alpha which is not correct, in fact what i need is mixing the current pixel color with the target pixel color based on the brush alpha

Standifer

Your welcome I'm glad that was what you were looking for!

Unasked
G
0

Also facing the same issue in holapaints.

Girlish answered 15/11, 2023 at 11:53 Comment(1)

https://holapaints.com/

Girlish

© 2022 - 2025 — McMap. All rights reserved.