Is there a way in LibGDX to create a polygon shaped mask? I know how to do a mask with squares and circles but not a polygon. The below code works and renders a mask correctly using a rectangle.
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearDepthf(1f);
Gdx.gl.glClear(GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glDepthFunc(GL20.GL_LESS);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
Gdx.gl.glDepthMask(true);
Gdx.gl.glColorMask(false, false, false, false);
// Renders the rectangle
shapes.begin(ShapeRenderer.ShapeType.Filled);
shapes.setColor(1, 1, 1, 1);
shapes.rect(Gdx.graphics.getWidth() / 2, gdx.graphics.getHeight() / 2, 200f, 200);
shapes.end();
batch.begin();
Gdx.gl.glColorMask(true, true, true, true);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
Gdx.gl.glDepthFunc(GL20.GL_EQUAL);
bg.draw(batch);
batch.end();
Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
This code below however does not work and simply renders a black screen.
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.gl.glClearDepthf(1f);
Gdx.gl.glClear(GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glDepthFunc(GL20.GL_LESS);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
Gdx.gl.glDepthMask(true);
Gdx.gl.glColorMask(false, false, false, false);
// This should be the polygon being rendered as a mask here
polyBatch.begin();
polygonSprite.draw(polyBatch);
polyBatch.end();
batch.begin();
Gdx.gl.glColorMask(true, true, true, true);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
Gdx.gl.glDepthFunc(GL20.GL_EQUAL);
bg.draw(batch);
batch.end();
Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
This code below however renders the polygon just fine and uses the same coordinates as the last example.
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// This polygon uses the same coordinates as the last example
// however it now displays the polygon.
polyBatch.begin();
polygonSprite.draw(polyBatch);
polyBatch.end();
Try moving the batch.begin(); in the third paragraph downwards so that it doesn't enclose the Gdx.gl functions, like that:
//batch.begin();
//from here
Gdx.gl.glColorMask(true, true, true, true);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
Gdx.gl.glDepthFunc(GL20.GL_EQUAL);
//to here
batch.begin();
bg.draw(batch);
batch.end();
Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
Related
I use ortho camera and FitViewport at my project.
In my render() method i create a fremeBuffer to store actual state of my game, then create a pixmap of that buffer and finally i set a new shader and do my postprocess stuff with that frame:
//--- render frame to buffer
screenBuffer.begin();
camera.update();
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
stage.draw();
//--- create pixmap from that buffer
pixmap = ScreenUtils.getFrameBufferPixmap(0, 0,screenBuffer.getWidth(), screenBuffer.getHeight());
batch.flush();
screenBuffer.end();
//--- create texture from pixmap
renderedScreenTexture = new Texture(pixmap);
//--- finally render frame with postprocess shader
camera.update();
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setShader(monoShader);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(renderedScreenTexture, 0,0);
batch.draw(renderedScreenTexture, 0, 0, 640, 320, 0, 0, 640, 320, false, true);
batch.end();
At my resize method I have:
viewport.update(width, height);
camera.position.set(camera.viewportWidth / 2,camera.viewportHeight / 2, 0);
The problem is that after resizing a window FitViewport doesen't work.
When i remove a creating frameBuffer from render method FitViewport works fine.
Can anybody tell me what is wrong with my code or whole concept?
Try this:
// the viewPort you are using
FitViewport v = viewport;
// end your buffer with your viewPort's position and size
screenBuffer.end(v.getScreenX(),v.getScreenY(),
v.getScreenWidth(),v.getScreenHeight());
You may have to call fitViewport.apply() before drawing your frameBuffer.
I'm working on 3d app in libgdx engine.
I just figured out that decalBatch isn't drawing into stencil buffer.
I wanned to make stencil masks for 3d world, and it's not working at all.
This is the code which works for sprite batch, but it's not working with decal batch.
Pls help!
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_STENCIL_BUFFER_BIT);
// batch.setProjectionMatrix(camera.combined);
// setup drawing to stencil buffer
Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
Gdx.gl20.glStencilFunc(GL20.GL_ALWAYS, 0x1, 0xffffffff);
Gdx.gl20.glStencilOp(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);
Gdx.gl20.glColorMask(false, false, false, false);
// draw base pattern
shapeRenderer.begin(ShapeType.Filled);
shapeRenderer.identity();
shapeRenderer.setColor(1f, 0f, 0f, 0.5f);
shapeRenderer.rect(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), 100, 100);
shapeRenderer.end();
spriteBatch.begin();
// fix stencil buffer, enable color buffer
Gdx.gl20.glColorMask(true, true, true, true);
Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);
// draw where pattern has NOT been drawn
Gdx.gl20.glStencilFunc(GL20.GL_NOTEQUAL, 0x1, 0xff);
// decalBatch.add(decal);
// decalBatch.flush();
spriteBatch.draw(Assets.instance.background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// draw where pattern HAS been drawn.
// Gdx.gl20.glStencilFunc(GL20.GL_EQUAL, 0x1, 0xff);
// spriteBatch.draw(Assets.instance.actor1, -Gdx.graphics.getWidth() /
// 2, -Gdx.graphics.getHeight() / 2, Gdx.graphics.getWidth(),
// Gdx.graphics.getHeight());
spriteBatch.end();
EDIT:
I figured out that there should be clearing of Depth buffer, and enabling and disabling of DepthMask, but I cant manage it to work.
Oh I just figured it out.
Depth buffer must be enabled couse Decals are in 3d world.
this is the solution if somebody is interested:
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_STENCIL_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
// setup drawing to stencil buffer
Gdx.gl20.glEnable(GL20.GL_STENCIL_TEST);
Gdx.gl20.glStencilFunc(GL20.GL_ALWAYS, 0x1, 0xffffffff);
Gdx.gl20.glStencilOp(GL20.GL_REPLACE, GL20.GL_REPLACE, GL20.GL_REPLACE);
Gdx.gl20.glColorMask(false, false, false, false);
Gdx.gl20.glDepthMask(false);
// draw base pattern
shapeRenderer.begin(ShapeType.Filled);
shapeRenderer.identity();
shapeRenderer.setColor(1f, 0f, 0f, 0.5f);
shapeRenderer.rect(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2, 100, 100);
shapeRenderer.end();
// fix stencil buffer, enable color buffer
Gdx.gl20.glColorMask(true, true, true, true);
Gdx.gl20.glDepthMask(true);
Gdx.gl20.glStencilOp(GL20.GL_KEEP, GL20.GL_KEEP, GL20.GL_KEEP);
// draw where pattern has NOT been drawn
Gdx.gl20.glStencilFunc(GL20.GL_NOTEQUAL, 0x1, 0xff);
decalBatch.add(decal);
decalBatch.flush();
Gdx.gl20.glDisable(GL20.GL_STENCIL_TEST);
So drawing a shape should be really easy, right? Well, the following draws exactly nothing.
...why?
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.rect(WIDTH / 2, HEIGHT / 2, 50, 50);
shapeRenderer.end();
Make sure your camera is properly initialized.
For Example:
camera = new OrthographicCamera(); //Put this in init
camera.setToOrtho(0,0,WIDTH,HEIGHT);
I'm trying to make an easter egg in my AS3 app, that appears when the user hovers their cursor over a seperate trigger, and disappears when they stop hovering over it.
var hideEast:Tween=new Tween(easter_mc,"alpha",null,100,0,1,false);
easterTrigger_btn.addEventListener(MouseEvent.MOUSE_OVER, triEas);
easterTrigger_btn.addEventListener(MouseEvent.MOUSE_OUT, remEas);
function triEas (e:MouseEvent):void{
var showEast:Tween=new Tween(easter_mc,"alpha",null,0,100,1,false);
}
function remEas (e:MouseEvent):void{
var hideEast;
}
This is the code I've tried to use. It shows the movie clip when the trigger is being hovered over, but the movie clip stays when the triggered isn't being hovered over anymore.
Because you don't have any animation in your MOUSE_OUT handler.
Also, I would recommend tweening engine from Jack Doyle - TweenLite.
trigger.addEventListener(MouseEvent.MOUSE_OVER, onOver, false, 0, true);
trigger.addEventListener(MouseEvent.MOUSE_OUT, onOut, false, 0, true);
function onOver(e:MouseEvent):void {
TweenLite.to(trigger, 0.3, {alpha: 1, ease: Sine.easeOut});
}
function onOut(e:MouseEvent):void {
TweenLite.to(trigger, 0.5, {alpha: 0, ease: Sine.easeInOut});
}
Or you can go further and use visibility.
trigger.alpha = 0;
trigger.visible = false;
TweenPlugin.activate([AutoAlphaPlugin]);
trigger.addEventListener(MouseEvent.MOUSE_OVER, onOver, false, 0, true);
trigger.addEventListener(MouseEvent.MOUSE_OUT, onOut, false, 0, true);
function onOver(e:MouseEvent):void {
TweenLite.to(trigger, 0.3, {autoAlpha: 1, ease: Sine.easeOut});
}
function onOut(e:MouseEvent):void {
TweenLite.to(trigger, 0.5, {autoAlpha: 0, ease: Sine.easeInOut});
}
I have created 2 shapes, circle and rectangle, one on top of the other to resemble a key lock. I then try to apply a stroke but its stroking both shapes. What I want it to do is just stroke the merged pattern and not any of the intersections.
context.beginPath();
context.fillStyle = "#ccc";
context.arc(115, 550, 12, 0, 2 * Math.PI, false);
context.moveTo(105, 555);
context.fillStyle = "#999";
context.rect(105, 555, 20, 30);
context.fill();
context.stroke();
context.closePath();
If I try to draw the rect first, then the arc on top there are extra line paths when you stroke, its like I have to close Path and then draw it again.
You can't use a rect and a whole circle if you want the path to do without the intersecting part.
Instead you have to draw only part of the circle and only part of the rectangle. This should do it for you:
context.beginPath();
context.fillStyle = "#ccc";
context.arc(115, 550, 12, 2.5, 2.2 * Math.PI, false);
context.moveTo(105+20, 555);
context.fillStyle = "#999";
// instead of a rect, we really want three lines
context.lineTo(105+20,555+30);
context.lineTo(105,555+30);
context.lineTo(105,555);
context.fill();
context.stroke();
context.closePath();
While working on my own irregular shape answer, I discovered a lab project by Professor Cloud that solved my problem.
This page, SVG-to-Canvas, parses an SVG graphic to Canvas code. So if you have an application like Illustrator with which you can draw and save the graphic as SVG, then you can parse the usable canvas codes and just plug them in.
You can use compositing and temporary canvas. Something like that:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var tempCanvas = document.getElementById('tempCanvas');
var tempContext = tempCanvas.getContext('2d');
tempContext.save();
// clear temp context
tempContext.clearRect(0, 0, canvas.width, canvas.height);
// draw all rects with strokes
tempContext.beginPath();
tempContext.strokeStyle='red';
tempContext.lineWidth=3;
tempContext.arc(100, 100, 60, 0, 2 * Math.PI, false);
tempContext.rect(20,150,100,200);
tempContext.stroke();
// set compositing to erase existing drawings
// where the new drawings are drawn
tempContext.globalCompositeOperation='destination-out';
// fill all rects
// This "erases" all but the outline stroke
tempContext.beginPath();
tempContext.fillStyle='blue';
tempContext.arc(100, 100, 60, 0, 2 * Math.PI, false);
tempContext.rect(20,150,100,200);
tempContext.fill();
// draw outlines from tempcanvas into canvas
ctx.drawImage(tempCanvas, 0, 0);
// draw into canvas
ctx.beginPath();
ctx.fillStyle='green';
ctx.globalAlpha = 0.2;
ctx.rect(20,150,100,200);
ctx.arc(100, 100, 60, 0, 2 * Math.PI, false);
ctx.fill();
tempContext.restore();
And a jsfiddle: https://jsfiddle.net/EvaF/8to68dtd/2/