Created
July 5, 2015 13:05
-
-
Save xoppa/2978633678fa1c19cc47 to your computer and use it in GitHub Desktop.
Shows how to render primitive shapes using Batch, without using ShapeRenderer. Requires at least libGDX 1.6.4 or latest nightly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.badlogic.gdx.tests.g2d; | |
import com.badlogic.gdx.Gdx; | |
import com.badlogic.gdx.graphics.Color; | |
import com.badlogic.gdx.graphics.GL20; | |
import com.badlogic.gdx.graphics.Mesh; | |
import com.badlogic.gdx.graphics.Texture; | |
import com.badlogic.gdx.graphics.VertexAttribute; | |
import com.badlogic.gdx.graphics.VertexAttributes; | |
import com.badlogic.gdx.graphics.VertexAttributes.Usage; | |
import com.badlogic.gdx.graphics.g2d.Batch; | |
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch; | |
import com.badlogic.gdx.graphics.g2d.TextureRegion; | |
import com.badlogic.gdx.graphics.g3d.utils.MeshBuilder; | |
import com.badlogic.gdx.graphics.glutils.ShaderProgram; | |
import com.badlogic.gdx.scenes.scene2d.Actor; | |
import com.badlogic.gdx.scenes.scene2d.Stage; | |
import com.badlogic.gdx.scenes.scene2d.ui.Image; | |
import com.badlogic.gdx.scenes.scene2d.ui.Skin; | |
import com.badlogic.gdx.scenes.scene2d.ui.TextButton; | |
import com.badlogic.gdx.scenes.scene2d.utils.Drawable; | |
import com.badlogic.gdx.tests.utils.GdxTest; | |
import com.badlogic.gdx.utils.GdxRuntimeException; | |
import com.badlogic.gdx.utils.viewport.ScreenViewport; | |
public class PolygonShapeTest extends GdxTest { | |
PolygonShapeDrawer drawer; | |
PolygonSpriteBatch batch; | |
Stage stage; | |
Skin skin; | |
Actor ellipse; | |
TextureRegion white; | |
@Override | |
public void create () { | |
drawer = new PolygonShapeDrawer(); | |
batch = new PolygonSpriteBatch(); | |
stage = new Stage(new ScreenViewport(), batch); | |
skin = new Skin(Gdx.files.internal("data/uiskin.json")); | |
white = skin.getAtlas().findRegion("white"); | |
white.setRegion(white.getRegionX()+1, white.getRegionY()+1, 1, 1); | |
TextButton button = new TextButton("Behind the shape!", skin); | |
button.setPosition(80, 120); | |
stage.addActor(button); | |
ellipse = new Actor() { | |
@Override | |
public void draw (Batch batch, float parentAlpha) { | |
drawer.setTextureRegion(white); | |
float w = getWidth(), h = getHeight(); | |
drawer.setColor(getColor()); | |
drawer.ellipse(w, h, w * 0.5f, h * 0.5f, 20, getX() + w * 0.5f, getY() + h * 0.5f, 0, 0, 0, -1); | |
drawer.draw((PolygonSpriteBatch)batch); | |
} | |
}; | |
ellipse.setSize(100, 100); | |
ellipse.setPosition(100, 100); | |
ellipse.setColor(Color.YELLOW); | |
stage.addActor(ellipse); | |
button = new TextButton("In front of the shape!", skin); | |
button.setPosition(80, 160); | |
stage.addActor(button); | |
Gdx.input.setInputProcessor(stage); | |
} | |
@Override | |
public void resize (int width, int height) { | |
stage.getViewport().update(width, height, true); | |
} | |
@Override | |
public void render () { | |
stage.act(); | |
stage.draw(); | |
} | |
public class PolygonShapeDrawer extends MeshBuilder { | |
private Texture texture; | |
public PolygonShapeDrawer () { | |
super(); | |
super.begin( | |
new VertexAttributes(new VertexAttribute(Usage.Position, 2, ShaderProgram.POSITION_ATTRIBUTE), VertexAttribute | |
.ColorPacked(), VertexAttribute.TexCoords(0)), GL20.GL_TRIANGLES); | |
} | |
@Override | |
public Mesh end () { | |
throw new GdxRuntimeException("Not supported!"); | |
} | |
@Override | |
public Mesh end (Mesh mesh) { | |
throw new GdxRuntimeException("Not supported!"); | |
} | |
public void setTextureRegion (TextureRegion region) { | |
if (getNumIndices() > 0) | |
throw new GdxRuntimeException("Cannot change the TextureRegion in while creating a shape, call draw first."); | |
texture = region.getTexture(); | |
setUVRange(region); | |
} | |
public void draw (PolygonSpriteBatch batch) { | |
if (texture == null) | |
throw new GdxRuntimeException("No texture specified, call setTextureRegion before creating the shape"); | |
batch.draw(texture, getVertices(), 0, getNumVertices() * getFloatsPerVertex(), getIndices(), 0, getNumIndices()); | |
clear(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
More info
ShapeRenderer
can be used for easily rendering 2D (and 3D) primitive shapes on the fly, e.g. for debugging. However its vertex layout is not the same as e.g.SpriteBatch
. This is becauseSpriteBatch
allows for 2D (only x and y, no z) sprites containing texture coordinates and a color, whileShapeRender
allows for 3D (x, y and z) shapes with a color but no texture coordinates. Therefor they both also use a different shader.MeshBuilder
is often used for creating basic 3D models and is often used as "create once, render many". However, it can also be used "on the fly" (create the mesh every render call) and it does allow for any combination of vertex attributes (including 2D shapes). It can therefor be used to create a mesh which is compatible withSpriteBatch
.SpriteBatch
does allow you to specify a custom mesh, but only if it consist out of quads (a multiple of four vertices with six indices).PolygonSpriteBatch
on the other hand can be used for more complex shapes and is interchangeable withSpriteBatch
. So by usingPolygonSpriteBatch
instead ofSpriteBatch
it is possible to render primitive shapes built withMeshBuilder
as part of your normal rendering (e.g. as part of your stage).