-1

I have a line actor that might have other object that intersect with it, And I need to crop out that part.

enter image description here

Above is the image actor

enter image description here

this rectangle is also a image actor might appear randomly along the lines.

enter image description here And this is the sample of the result I wanted to get. I need advice on how to achieve this with libgdx.

[EDIT]

As suggest I am trying to use fbo to draw into a buffer. Below is the code I am currently working on.

@Override
public void draw(Batch batch, float parentAlpha) {

    fbo.begin();
    getStage().getViewport().apply();

    Gdx.gl.glClearColor(0f,0f,0f,0f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    batch.draw(trLine,position.x,position.y);
    batch.flush();

    fbo.end();
    getStage().getViewport().apply();

    batch.draw(fbo.getColorBufferTexture(),0,0);

}

I am able to buffer the draw into the buffer and draw it later but it happen to be different size. below is the code for creation and dispose of fbo. and it is outside of the draw loop.

fbo = new FrameBuffer(Pixmap.Format.RGBA8888,getStage().getViewport().getWidth(),getStage().getViewport().getHeight(),false,true);

[SOLVED FBO]

Below is the coding that have working fbo but the blending is not working as expected. Will keep trying until it works.

fbo.begin();

Gdx.gl.glClearColor(0f,0f,0f,0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

batch.begin();
batch.draw(trLine,position.x,position.y);
batch.end();


int srcFunc = batch.getBlendSrcFunc();
int dstFunc = batch.getBlendDstFunc();

batch.enableBlending();
batch.begin();
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_FUNC_REVERSE_SUBTRACT);
for(int i = 0 ; i < cropRectangles.size() ; i++){   batch.draw(cropTexture.get(i),cropRectangles.get(i).x,cropRectangles.get(i).y);
}
batch.end();

fbo.end();

getStage().getViewport().apply();

//reset blending before drawing the desire result
batch.begin();
batch.setBlendFunction(srcFunc, dstFunc);
batch.draw(fbo.getColorBufferTexture(),0,0);
batch.end();

But the output is not getting any blending effect. it is still a rectangle with filled white color.

enter image description here

[SOLVED FULL CODE]

I finally apply the equation correctly and able to reset it so it doesn't affect other things that I draw after this.

fbo.begin();

Gdx.gl.glClearColor(0f,0f,0f,0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

batch.begin();
batch.draw(trLine,position.x,position.y);
batch.end();


int srcFunc = batch.getBlendSrcFunc();
int dstFunc = batch.getBlendDstFunc();



batch.enableBlending();

batch.begin();
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glBlendEquation(GL20.GL_FUNC_REVERSE_SUBTRACT);

for(int i = 0 ; i < cropRectangles.size() ; i++){

                batch.draw(cropTexture.get(i),cropRectangles.get(i).x,cropRectangles.get(i).y);

}

batch.end();
batch.flush();

fbo.end();

Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD);

getStage().getViewport().apply();

batch.begin();
batch.setBlendFunction(srcFunc, dstFunc);
batch.draw(fbo.getColorBufferTexture(),0,0);
batch.end();
Leon Armstrong
  • 1,285
  • 3
  • 16
  • 41
  • Not quite sure what you mean by cropping out part of a picture, because you have not examples of that above. In your last picture, you would just draw the lines and then the rectangles. When using Stage, this means the actors have to be added to the Stage in the order you want them drawn. You can control this more easily using Groups that represent layers: https://stackoverflow.com/a/17558220/506796 – Tenfour04 Oct 01 '17 at 00:55
  • the frame is transparent and also because there is few object will be under the frame. is there any way to make the linebreak when it touch specific actor? – Leon Armstrong Oct 01 '17 at 06:54
  • I have little understand how scissor work , but is there any other way to invert the scissor? like I put a rectangle and cut out some portion of the line? (only the line) – Leon Armstrong Oct 01 '17 at 08:07

2 Answers2

1

You can use blend mode to achieve this.Your rectangle should have 2 parts. Outer part and transparent part.

Outer part is your actual part going to be draw as usual.

Transparent part will be another rectangle with a full alpha and you should use blending for this part.

Visual Blending Tool

examplemode

glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);

This mode clearing intersection area, it seems like correct mode .

You can easly find example usages of blending in libgdx.

    SpriteBatch sb = (SpriteBatch)batch;

    // draw our destination image
    sb.draw(dst, 0, 0);
    sb.end();

    // remember SpriteBatch's current functions
    int srcFunc = sb.getBlendSrcFunc();
    int dstFunc = sb.getBlendDstFunc();

    // Let's enable blending
    sb.enableBlending();
    sb.begin();

    // blend them
    sb.setBlendFunction(GL20.GL_ONE, GL20.ONE_MINUS_SRC_ALPHA);
    sb.draw(src, 0, 0);

    // Reset
    sb.end();
    sb.begin();
    sb.setBlendFunction(srcFunc, dstFunc);

Additionally you must change blend equation as well. And its not unique for sprite batch so we need to change for all game.

//Equation for effect you want    
Gdx.gl.glBlendEquation(GL20.GL_FUNC_REVERSE_SUBTRACT);

//After draw you should also reset this
Gdx.gl.glBlendEquation(GL20.GL_FUNC_ADD);

Now we should take this drawn to FrameBufferObject because transparent area will show background color of your spritebatch. If it's okey for you then it's done but you want to see another texture at this transparent area like background image or something then we have one more step.

You should read this article for whats the purpose of FBO(FrameBufferObject)

Frame Buffer from official wiki

You need to use this for merge your sprites and transparent areas so you can use those as whole image and see through background images from transparent area.

Maybe using second viewport or sprite batch would be easier and much more efficient according to your game.

Deniz Yılmaz
  • 1,084
  • 9
  • 16
  • Can you provide some code on how to implement framebuffer into the blending? Or I should update my code into the question , I am still trying to get this work as it may affect my whole project – Leon Armstrong Oct 26 '17 at 12:11
  • Framebuffer return you a new texture. framebuffer.getTexture(); Then all you have to do is blending as regular texture. https://stackoverflow.com/questions/25347456/how-to-do-blending-in-libgdx You can find libgdx examples of blending on google. – Deniz Yılmaz Oct 27 '17 at 08:19
  • I am sorry , I can't even make the fbo work with my actor , because it is inside an Actor. I just do regular draw to fbo , and the result is different with the normal draw in stage. the size and coordinate is all mess up – Leon Armstrong Oct 27 '17 at 08:42
  • I have updated my question to provide more on my current work on fbo part. – Leon Armstrong Oct 27 '17 at 08:48
  • Is your view port smaller than your screen sizes ? Try with screen resolutions as parameter of FBO – Deniz Yılmaz Oct 27 '17 at 09:12
  • FBO taking screen in to buffer so if you taking screen after applying viewport it could cause to have smaller size. And when you draw this fbo also with viewport you basically applying viewport twice. Removing one of the viewport apply also solve your issue. – Deniz Yılmaz Oct 27 '17 at 09:17
  • Yes, I have resized and using fitviewpot with 800 and 452. I changed the fbo width and height with Gdx.graphics.getWidth() and Height. The output is completely out of my device now. – Leon Armstrong Oct 27 '17 at 09:17
  • 1
    Then remove getStage().getViewport().apply(); just before fbo draw cuz your fbo already should be transformed to your viewport. – Deniz Yılmaz Oct 27 '17 at 09:18
  • If again fbo out of your screen then change draw coordinates 0,0 to your viewport coordinates – Deniz Yılmaz Oct 27 '17 at 09:20
  • removing viewpot.apply solved my problem! I will try to apply the blending now. I appreciate your help. – Leon Armstrong Oct 27 '17 at 09:21
  • Also fbo.getTexture returns reversed texture on Y axis. You will realise when you use non symmetrical texture. Texture does not have flip method but textureregion does. So convert fbo texture to texture region. Then flip respect to Y axis and convert back to texture. textureregion=new TextureRegion(frameBuffer.getColorBufferTexture()); textureregion.flip(false,true); texture=new Texture(textureregion.getTexture() ); – Deniz Yılmaz Oct 27 '17 at 09:30
  • good news is it doesn't have flipping problem , it is shown as expected although I am having a Y down set. – Leon Armstrong Oct 27 '17 at 09:38
  • I have updated my questions , I am a business apps developer , might need sometimes to understand the graphic programming. I will update here when I able to solve it. Hope it can help others too – Leon Armstrong Oct 27 '17 at 10:02
  • You need to set blending for app Gdx.gl.glBlendEquation(GL20.GL_FUNC_REVERSE_SUBTRACT); – Deniz Yılmaz Oct 27 '17 at 10:30
  • And you should blend in framebuffer because you need blending between lines and rectangles. – Deniz Yılmaz Oct 27 '17 at 10:32
  • yes thats things I'm missing , I have updated my solution into the question in case someone need it. and I will move it outside of the loop since the rectangle and line is not moving frequently. to save processing load. – Leon Armstrong Oct 27 '17 at 10:49
0

One solution for this situation, fill that rectangle with solid background color(i mean make one rectangle inside that rectangle ring). It will cropped out that part.

Madhav Gor
  • 211
  • 2
  • 12