x


Painting stencil on a surface.

Hi, I've been trying and experimenting on GetPixel/SetPixels to read color data of a 64 x 64 pixels psd file and paste the retrieved data into a Texture2D. The stencil (PSD file) comes with a single layer without background. The Texture2d that is created inside the code is formatted as ARGB32 and the PSD is also imported as ARGB32. In the test link you can see that each star overlaps and removes the previously painted one.

How is it possible to solve this problem so that stars overlap but don't remove eachother?

WebPlayer test: http://jovialart.com/WebPlayer/WebPlayer.html

Thoughts appreciated.

here is script:

var stencil:Texture2D;
var tagFilter:String;
var paintMaterial:Material;

private var tex : Texture2D;
private var stencilUV:Color[];
private var i:int;
private var pixelUV;

function Start(){
    stencilUV = new Color[stencil.width * stencil.height];
    tex = new Texture2D (1024,1024, TextureFormat.ARGB32, false);
    //ReadStencilTexture();
}


function Update () {
    if(DetectPaintable(tagFilter)){
        CreateStencil(pixelUV.x,pixelUV.y,stencil);
    }
}

function DetectPaintable(tagFilter:String):boolean{
    // Only if we hit something, do we continue
    var hit : RaycastHit;
    if(Physics.Raycast (camera.ScreenPointToRay(Input.mousePosition), hit)){
    if (hit.transform.gameObject.tag == tagFilter){
    // Only when we press the mouse
    if (!Input.GetMouseButton (0))
        return;
    // Just in case, also make sure the collider also has a renderer
    // material and texture. Also we should ignore primitive colliders.
    var renderer : Renderer = hit.collider.renderer;
    var meshCollider = hit.collider as MeshCollider;
    if (renderer == null || renderer.sharedMaterial == null ||
        renderer.sharedMaterial.mainTexture == null || meshCollider == null)
        return;

    pixelUV= hit.textureCoord;
    pixelUV.x *= tex.width;
    pixelUV.y *= tex.height;
    return true;
    }
    }
}

function CreateStencil(x:int,y:int, texture:Texture2D){
    paintMaterial.mainTexture = tex;
    for (var xPix =0; xPix<texture.width; xPix++){
        for (var yPix=0;yPix<texture.height; yPix++){
                stencilUV[i] = texture.GetPixel (xPix,yPix) * texture.GetPixel (xPix,yPix).a + tex.GetPixel((x -texture.width/2) +xPix, (y -texture.height/2)+yPix) * (1-texture.GetPixel(xPix,yPix).a); // <-----
            i++;
        }
    }
    i=0;
    tex.SetPixels(x -texture.width/2, y-texture.height/2,texture.width,texture.height,stencilUV);
    tex.Apply();
}
more ▼

asked Mar 01 '11 at 06:47 AM

Kourosh gravatar image

Kourosh
1.5k 47 53 65

(comments are locked)
10|3000 characters needed characters left

6 answers: sort voted first

You should do what a graphics card does when you ask it to perform alpha blending (alpha blending is what you're trying to do here):

final rgb colour = sourceColour*sourceAlpha + destinationColour*oneMinusSourceAlpha

or in your case:

final rgb colour = (rgb colour of the texture you're applying * alpha colour of the texture you're applying) + (rgb colour of the texture into which you are rendering * (1 - alpha colour of the texture you're applying))

That way you won't just overwrite the alpha values of your 64x64, you'll blend them properly :)

more ▼

answered Mar 01 '11 at 09:20 AM

taoa gravatar image

taoa
1.6k 8 13 34

Thanks taoa, i did what you mentioned, and also included the webplayer test. still having issues... In the "CreateStencil" function inside the loops there is a Color array called "stencilUV" where i implemented what you commented. is this what you meant?

Mar 02 '11 at 01:04 AM Kourosh

Holy crap. Javasript. Ouch. Give me some time then :) BTW: instead of performing a raycast every frame and only using it if you click the mouse, do the other way around, only do your raycast if the mouse is clicked. A mouse click test is about thirty seven billions times quicker than a ray cast test. Roughly.

Mar 02 '11 at 10:52 AM taoa

OK, I believe your code is generally correct, but your main issue here is that you use the alpha value of your source image (the one you apply) to multiply in both your source texture and your destination texture all colours components... including the alpha values! You should only multiply the rgb components, and for the alpha component of the final colour, choose the highest value between the source and the destination. Also, you're calling three (3! yes, 3!) times the function texture.GetPixel (xPix,yPix). Please, Call it once (1) and store it into a Color variable :p

Mar 02 '11 at 11:26 AM taoa

HoOoray!! Success!! thanks taoa! you rock :)

Mar 02 '11 at 04:17 PM Kourosh

Glad I helped! ^_^

Mar 02 '11 at 06:25 PM taoa
(comments are locked)
10|3000 characters needed characters left

There is logic mistake in the script. I spend much time before I realize that I need to swap this couple of lines in CreateStencil function:

        for (var xPix =0; xPix<texture.width; xPix++){
                    for (var yPix=0;yPix<texture.height; yPix++){
                    ...
                    }

This two lines need to swap, to get script working correct. Oterwise iterator writes into array Y-row at first. Than changes X. And again writes Y-row. This is the reason why I was getting wrong drawing result.

more ▼

answered Aug 29 '12 at 10:41 AM

AkhmadMax gravatar image

AkhmadMax
1 1 3

(comments are locked)
10|3000 characters needed characters left

I'm trying to implement this scrip, but with no luck so far... Could you post the correct script? It would be an awesome help.

Thanks in advance

more ▼

answered Mar 20 '12 at 03:22 PM

leonardoebs gravatar image

leonardoebs
1

(comments are locked)
10|3000 characters needed characters left

Hi Kourosh, would you be so kind to share your corrected script, i'm having a hard time multiplying my rgb components with the alpha channels.. Thx!

more ▼

answered Nov 18 '11 at 12:27 PM

s.papian gravatar image

s.papian
1

(comments are locked)
10|3000 characters needed characters left

Hi, did anyone manage to run this code on iPhone? I need exactly this but it is running too slow.. is there another workaround?

more ▼

answered Apr 05 '12 at 12:39 PM

dbravo gravatar image

dbravo
1 1 1 2

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x354
x326
x37
x30
x5

asked: Mar 01 '11 at 06:47 AM

Seen: 2306 times

Last Updated: Feb 02 at 04:55 AM