Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Masking images? — Gideros Forum

Masking images?

NinjadoodleNinjadoodle Member
edited February 2016 in General questions
Hi guys

I've searched the forums in and out, but can't seem to find any way of masking images in gideros.

The answers I've found seem to be workarounds, but I'm not sure whether that info is still relevant, or whether masks are now possible.

Thank you heaps for your help!

Comments

  • hgy29hgy29 Maintainer
    Yes, this topic sometimes pop up again :)

    There is a few ways to achieve masking in OpenGL:
    - Using stencil buffer to impress a mask picture and then render others shapes only in places where stencil was marked. This is the technique used by Path2D. It allows precise masking at the expense of a double rendering pass. This is not (yet) exposed to lua by Gideros
    - Using alpha blending composition: you can multiply a mask bitmap with a regular Sprite. This is already available in Gideros and is most of the time faster than the first technique.
    - Using shader (like in the vignette exemple I sent you): probably the fastest way.
  • Hi @hgy29

    Thank you for the answers, I will have a look at the vignette example as soon as I can get the sharers working :)
  • NinjadoodleNinjadoodle Member
    edited February 2016
    Hi @hgy29

    I've had a look at your example, but to be honest I have no idea what any of the values mean, lol. I think I would need to go through some sort of manual, in order to understand how to make shaders.

    If anyone would be able to show me a small example how to do this using blending modes, I would be eternally grateful :)

    Thanks you very much for all your help - you guys rock!
  • edited December 2016
    Hi @hgy29
    Sorry for pop up again,
    I have an image png and I want to make 6 part (2*3) from this image by using mask images (They are not square nor rectangle but like the jigsaw puzzle). How can I do this in Gideros, at this time (I see many new apis added so I hope it will be easy now)

    (Example mask shape and game that I want to make: https://play.google.com/store/apps/details?id=com.kristanix.android.jigsawpuzzleepic)

    Thank so much!
    Coming soon
  • Try path2D to create a vector shape. Apply a bitmp to a render target and set the texture of the path 2D to the render target.

    A recent feature is that you can now select a region of the bitmap using render target.

    I did a similar thing in Grammar Smash English for the smashing effect.
  • @NatWobble Thanks! I will try to implement your comment.
    In my game, the mask is defined and are fixed images (As I attach bellow). So basically, I think it can not create by vector shape using path2D?
    16_9.png
    448 x 336 - 6K
    Coming soon
  • hgy29hgy29 Maintainer
    @vitalitymobile, I can think of two ways to achieve that:

    The first way is using rendertargets and alpha blending: create a render target, draw your image on it, then draw the mask right above using multiply blending mode, so that white pixels in the mask will leave underlying color untouched and black pixels will turn them to black. Better: if the mask 'black' color could be actually transparent, then your rendertarget cutted part shall become transparent too.

    The second way would be to use a shader with double texture input (image and mask): the shader would then automatically eliminate masked pixels, but shaders are still not completely portable, meaning that you need to write a GLSL one (for open gl based platforms) and an HLSL one (for windows RT/UWP).
    +1 -1 (+1 / -0 )Share on Facebook
  • edited December 2016
    Hi @hgy29
    Yes, thank so much I follow the first way and have resulted as expected.
    The remain jobs are change black to transparent and check for touch area of pieces (Do not allow user to hold transparent area to move the piece )

    In theory, the second method would be great if we can write both GLSL and HLSL and put it into Gideros API as simple setMask Method

    (From Mask Requirement session here https://docs.coronalabs.com/guide/media/imageMask/index.html
    I guess they use your the second way in above comment
    )

    Thank so much!
    Screen Shot 2016-12-23 at 11.35.52 AM.png
    2860 x 1466 - 611K

    Likes: antix

    Coming soon
    +1 -1 (+1 / -0 )Share on Facebook
  • john26john26 Maintainer
    edited January 2017
    @Ninjadoodle, thanks for reminding me, the shader stuff in Gideros desperately needs documentation and tutorials. I will try to get some stuff on the website in the near future (new year resolution!)
    +1 -1 (+2 / -0 )Share on Facebook
  • edited January 2017
    @hgy29

    Could you please show me "shader program" to using this file bellow as the mask and then apply into an image?
    (I just playing with http://giderosmobile.com/forum/discussion/6816/how-to-create-a-circle-transition-with-transparency#Item_2
    But can not procedure the result
    )

    Thank!
    6_1.png
    544 x 544 - 11K
    6_1.png 11.2K
    Coming soon
  • hgy29hgy29 Maintainer
    Quick and dirty:
    local JigsawVShader=
    [[
    attribute vec4 POSITION0;
    attribute vec2 TEXCOORD0;
     
    uniform mat4 g_MVPMatrix;
     
    varying mediump vec2 texCoord;
     
    void main()
    {
    	gl_Position = g_MVPMatrix * POSITION0;
    	texCoord = TEXCOORD0;
    }
    ]]
     
    local JigsawFShader=[[
    uniform lowp sampler2D gMask;
    uniform lowp sampler2D gJig;
    uniform mediump vec4 jigRect;
    uniform mediump vec4 maskInfo;
     
    varying mediump vec2 texCoord;
     
    #ifdef GLES2
    precision mediump float;
    #endif
     
    void main()
    {
    	vec4 mask= texture2D(gMask, texCoord);
    	if (mask.r<0.5)
    		discard;
    	vec4 jig=texture2D(gJig, texCoord*jigRect.zw+jigRect.xy);
     
    	gl_FragColor = jig;
    }
    ]]
     
    local JigsawShaderAttrs=
    {
    {name="POSITION0",type=Shader.DFLOAT,mult=3,slot=0,offset=0},
    {name="vColor",type=Shader.DUBYTE,mult=0,slot=1,offset=0},
    {name="TEXCOORD0",type=Shader.DFLOAT,mult=2,slot=2,offset=0}
    }
     
    local JigsawShaderConstants={
    {name="g_MVPMatrix",type=Shader.CMATRIX,sys=Shader.SYS_WVP, vertex=true},
    {name="gMask",type=Shader.CTEXTURE,mult=1,vertex=false},
    {name="gJig",type=Shader.CTEXTURE,mult=1,vertex=false},
    {name="jigRect",type=Shader.CFLOAT4,mult=1,vertex=false},
    }
     
     
    local JigsawShader= Shader.new(
    JigsawVShader,JigsawFShader,
    Shader.FLAG_FROM_CODE,JigsawShaderConstants,JigsawShaderAttrs) 
     
    local jigsaw=Texture.new("DSC_1529.JPG",true) 
    local piece=Pixel.new(Texture.new("PuzzleMask.png",true),50,50)
    piece:setTexture(jigsaw,1)
    piece:setShader(JigsawShader)
    piece:setShaderConstant("jigRect",Shader.CFLOAT4,1,0.1,0.1,0.3,0.3)
     
    application:setBackgroundColor(0xFF00FF)
     
    stage:addChild(piece) 
    piece:setPosition(50,50)
    +1 -1 (+4 / -0 )Share on Facebook
  • i think a mask function should be provided in gideros automatically, it's quite useful stuff.
    +1 -1 (+4 / -0 )Share on Facebook
  • @hgy29 Thanks, It works!
    How can I modify relate x,y position of the mask in the image (I mean reposition mask in the image so that we have difference parts)?
    Coming soon
  • hgy29hgy29 Maintainer
    edited January 2017
    You can do that using:
    piece:setShaderConstant("jigRect",Shader.CFLOAT4,1,x,y,w,h)
    where x and y are the starting point in your image divided by the size of your image rounded up to the next power of 2, and w and h are similarily the width and height of the area of your image you want to map to your mask, mask size being itself rounded up to the next power of 2.

    So assuming you want to map ix,iy,iw,ih source rect of your image to your jigsaw piece, x,y,w,h could be computed like this:
    local imageExtW,imageExtH=math.pow(2,1+math.floor(math.log(image:getWidth())/math.log(2))),math.pow(2,1+math.floor(math.log(image:getHeight())/math.log(2)))
    local maskVisW,maskVisH=mask:getWidth()/math.pow(2,1+math.floor(math.log(mask:getWidth())/math.log(2))),mask:getHeight()/math.pow(2,1+math.floor(math.log(mask:getHeight())/math.log(2)))
     
    local x,y,w,h=ix/imageExtW,iy/imageExtH,iw/(imageExtW*maskVisW),ih/(imageExtH*maskVisH)
    NB: Not tested, but I hope you'll get the idea

    Likes: SinisterSoft

    +1 -1 (+1 / -0 )Share on Facebook
  • Thank @hgy29
    It works! You are the Master of math and the King of shader. Two achievements!
    Screen Shot 2017-01-12 at 11.30.14 PM.png
    952 x 680 - 64K
    Coming soon
    +1 -1 (+4 / -0 )Share on Facebook
  • I haven't checked yet how this actually works, but it seems like commonly needed and very useful. Could this possibly be abstracted to something like Sprite:mask(sprite)?
    My Gideros games: www.totebo.com
    +1 -1 (+2 / -0 )Share on Facebook
  • edited May 2017
    @hgy29 Is there any bad performance or heavy texture memory when I create 16 pieces and assign texture using:

    piece:setTexture(jigsaw,1)

    Can I make 16 TextureRegion from main texture (jigsaw) and then set TextureRegion to piece instead of the main texture?

    piece:setTexture(one_jigsaw_texture_region,1)

    (I try it but it does not work maybe because of class TextureRegion is not the child of class TextureBase)

    Thanks!
    Coming soon
  • hgy29hgy29 Maintainer
    There won't be any performance nor memory impact if you use the same big texture multiple times: it will be allocated only once.
  • @hgy29 Thank!
    Now I am implementing drag piece, how can I get alpha or something similar to avoid user drag when clicking on the transparent area (black area of mask image)?
    (Like this idea: http://giderosmobile.com/forum/discussion/6561/bitmapx-bitmap-class-with-pixel-perfect-hit-detection/p1)

    ( piece is Pixel class: local piece=Pixel.new(Texture.new(mask_path,true),544,544))
    Coming soon
  • hgy29hgy29 Maintainer
    Currently only RenderTarget have a getAlpha() call, so you will need to draw your piece mask onto a render target and then use getAlpha() to check if the mask is black or white at mouse location.
    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.