- Home /
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(); }
Answer by taoa · Mar 01, 2011 at 09:20 AM
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 :)
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?
Holy crap. Javasript. Ouch. Give me some time then :) BTW: ins$$anonymous$$d of perfor$$anonymous$$g 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.
O$$anonymous$$, 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
Answer by s.papian · Nov 18, 2011 at 12:27 PM
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!
Answer by leonardoebs · Mar 20, 2012 at 03:22 PM
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
Answer by dbravo · Apr 05, 2012 at 12:39 PM
Hi, did anyone manage to run this code on iPhone? I need exactly this but it is running too slow.. is there another workaround?
Answer by dbravo · Apr 05, 2012 at 12:39 PM
Hi, did anyone manage to run this code on iPhone? I need exactly this but it is running too slow.. is there another workaround?