LIBGDX Framebuffer is drawn as a black box - libgdx

We figured out the issue. I was disposing the framebuffer before using it.
I recently queried about how to use the Libgdx Framebuffer correctly.
Summed up, i am making a tile-based game and i wanted to understand how to setup and use a
framebuffer object to eventually start experimenting with shaders. I wanted to exclude the
"water tiles" from the normal draw cycle and instead have them be rendered to a framebuffer.
Then render the framebuffer to the screen.
(I am not using any "Scene2d" or "Tiled" classes)
Link to previous question: How to use LIBGDX FrameBuffer correctly.
Even though the answer i accepted did not work in my particular program, it did work
when i tried it out on a smaller more contained program (shown below).
This works:
public void render() {
float dt = Gdx.graphics.getDeltaTime();
Cam.instance.getCamera().translate(direction.x*speed*dt, direction.y*speed*dt,0);
Cam.instance.update();
// clear the screen, set batch's projection matrix
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(Cam.instance.getCamera().combined);
// draw texture as layer 0
batch.begin();
batch.draw(green,606,306);
batch.flush(); // No need to call batch.end() / batch.begin()
// Storing the original values of the batch before changing it.
originalMatrixTemp.set(batch.getProjectionMatrix());
int originalBlendSrcFunc = batch.getBlendSrcFunc();
int originalBlendDstFunc = batch.getBlendDstFunc();
// Sorcery as far as i am concerned. "Ensures alpha is preserved in case of overlapping translucent sprites"
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);
frameBuffer.begin(); // initialize framebuffer
// clear the colors of the batch
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.draw(red,256,0); // Draw another texture, now unto the framebuffer texture
batch.flush(); // flush batch
frameBuffer.end(); // end framebuffer
// "Ensure we're drawing the frame buffer texture without modifying its color"
batch.setColor(Color.WHITE);
// I think we are setting the projection to "default" (-1,1,2,-2)
batch.setProjectionMatrix(IDENTITY);
// draw the framebuffers texture across all the screen (layer 1)
batch.draw(frameBuffer.getColorBufferTexture(),-1, 1, 2, -2);
batch.flush();
// restoring the original state
batch.setProjectionMatrix(originalMatrixTemp);
batch.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);
// drawing arbitrary layer 2
batch.draw(green,300,300);
batch.end(); // end of cycle
}
and it shows (Red square is the framebuffer texture):
The cycle is: Begin -> Draw something -> Draw, using buffer -> Draw something -> end.
So my question is then, why does this not work:
private void renderFbo(int layer) {
batch.flush();
originalMatrixTemp.set(batch.getProjectionMatrix());
int originalBlendSrcFunc = batch.getBlendSrcFunc();
int originalBlendDstFunc = batch.getBlendDstFunc();
batch.setBlendFunctionSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE);
fbo.begin();
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// Drawing the layer unto the framebuffer:
for (DrwDat dat: layers.get(layer)) { dat.draw(batch); }
batch.flush();
fbo.end();
batch.setColor(Color.WHITE);
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
batch.setProjectionMatrix(IDENTITY);
// Halving the output texture to see the issue clearer. whole screen: (-1, 1, 2, -2)
batch.draw(fbo.getColorBufferTexture(), -0.5f, 0.5f, 1f, -1f);
batch.flush();
batch.setProjectionMatrix(originalMatrixTemp);
batch.setBlendFunction(originalBlendSrcFunc, originalBlendDstFunc);
}
With this being the immediate context:
public void draw() {
Gdx.gl.glClearColor(1, 1, 1, 1); // clearing with WHITE to see the framebuffer texture
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (int i = 0; i < NUM_LAYERS; i++) {
if (RENDER[i]) {
if (SORT[i]) Collections.sort(layers.get(i));
//for (DrwDat dat: layers.get(i)) { dat.draw(batch);}
if (i==1) { renderFbo(i); } // calling the framebuffer-using method for "water layer"
else{
for (DrwDat dat: layers.get(i)) {
dat.draw(batch);
}
}
}
}
Instance variables in the "draw class" :
public class DrwHandler {
private static final String TAG = DrwHandler.class.getName();
public static DrwHandler instance = new DrwHandler();
private final Matrix4 originalMatrixTemp = new Matrix4();
private static final Matrix4 IDENTITY = new Matrix4();
private Map<Integer, ArrayList<DrwDat>> layers;
private OrthographicCamera camera;
private FrameBuffer fbo;
private SpriteBatch batch;
private static final int NUM_LAYERS = 8;
private static final boolean[] RENDER = new boolean[NUM_LAYERS];
private static final boolean[] SORT = new boolean[NUM_LAYERS];
private DrwHandler() {
fbo = new FrameBuffer(Pixmap.Format.RGBA8888, Settings.SCREEN_W,Settings.SCREEN_H,false);
batch = new SpriteBatch();
layers = new HashMap<>();
layers.put(0,new ArrayList<>());
layers.put(1,new ArrayList<>());
layers.put(2,new ArrayList<>());
layers.put(3,new ArrayList<>());
layers.put(4,new ArrayList<>());
layers.put(5,new ArrayList<>());
layers.put(6,new ArrayList<>());
layers.put(7,new ArrayList<>());
}
It shows:
The "black box" is the framebuffer texture (redused in size). The white background is the clear color.
and the green is a foreground layer.
It is black regardless of changing the Gdx.gl.glClearColor(0, 0, 0, 0) within the context of the framebuffer rendering to some other color.
without the renderFbo() method, it renders normally like this:
Now i have heard Static references can cause issues with OpenGL-related objects:
"If you will be building for Android, never use static references to any OpenGL-related objects unless you have an expert understanding of the LibGDX lifecycle. Even then, it is an error-prone practice. People come on here to ask about black textures pretty frequently and 99% of the time it has to do with some static reference being used incorrectly."
I am not building for android. And since my previous question i have removed static objects.
just to be sure.
But i do use statics in a few select classes like this (example):
public class Cam {
public static Cam instance = new Cam();
private OrthographicCamera camera;
private Cam() {
camera = new OrthographicCamera(Settings.SCREEN_W, Settings.SCREEN_H);
}
(including my Assets class and Draw class):
Trying to think about what else.. I guess we will try with this first. Se if something sticks out to you.
Really could need some help right about now. Been banging my head against the wall for a while. Thank you.
Here is a link to some source files that could be relevant:
Source

Related

Lwjgl3Application drawing perf degrades from 1.9.10 to 1.9.11

Hi I have a game that was using Lwjgl3Application with 1.9.10, after updating to 1.10.0 the drawing is noticeably worse on my 2014 macbook pro. You can tell the difference even when drawing a single texture. When texture are drawn, it looks like they are drawn in horizontal chunks, giving the illusion that drawing is lagging. The framerate via Gdx.graphics.getFramesPerSecond() is still ~60. On larger scenes, the weirdness in drawing is very apparent as large horizontal bands of artifacts going across the screen.
I used the project generator tool to make a scratch project to try and narrow it down, it looks like the degradation happens between 1.9.10 and 1.9.11.
In comparison, using LwjglApplication works just as well as before.
Below is the code, if running on a mac make sure to add the -XstartOnFirstThread VM arg to the desktop launcher otherwise it won't start.
public class DesktopLauncher {
public static void main (String[] arg) {
final Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration();
new Lwjgl3Application(new MyGdxGame(), config);
}
}
public class MyGdxGame extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
int posX, posY;
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, posX, posY);
batch.end();
// make texture move around a bit
posX++;
posY++;
if (posX >= Gdx.graphics.getWidth() - img.getWidth()) {
posX = 0;
posY = 0;
}
}
#Override
public void dispose () {
batch.dispose();
img.dispose();
}
}
Thanks

LibGDX making a rectangle move on its own

public class gameMain implements Screen {
final main game;
SpriteBatch batch;
Texture img;
private Texture alexTexture;
private Rectangle alex;
private Texture cTex;
private Texture dropper;
private Texture ender;
private Texture partsImg;
private Texture toy;
private OrthographicCamera camera;
private Array<Rectangle> part; // ******
private long lastDropTime;
private int beltSpeed = 100; // ******
//Score Keeper
private int score;
private String scoreName;
//basically a create method
public gameMain(final main gam){
this.game = gam;
// load images into memory
dropper = new Texture("android/assets/dropper.png");
ender = new Texture("android/assets/endOfBelt.png");
partsImg = new Texture("android/assets/unmadeToyParts.png");
toy = new Texture("android/assets/toymade.png");
cTex = new Texture("android/assets/conveyerBeltBackground.png");
alexTexture = new Texture(Gdx.files.internal("android/assets/alexAlpha2.png"));
// set the game window resolution
camera = new OrthographicCamera();
camera.setToOrtho(false, 1080,720);
// Alex's position / hitbox
alex = new Rectangle();
alex.x = 250;
alex.y = 150;
alex.width = 126;
alex.height = 75;
// part stuff
part = new Array<Rectangle>();
spawnPart();
// score handler
score = 0;
scoreName = "Toys Made: ";
}
private void spawnPart(){ // *******
Rectangle parts = new Rectangle();
parts.x = 0;
parts.y = 210;
parts.width = 52;
parts.height = 60;
part.add(parts);
lastDropTime = TimeUtils.nanoTime();
} //********
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
// load alex sprite
game.batch.setProjectionMatrix(camera.combined);
// begin drawing to screen
game.batch.begin();
batch.draw(cTex, -5, 200); // draw conveyer background
batch.draw(dropper, 0, 210); // draw the dropper
batch.draw(ender, 600, 200); // draw the ender
game.batch.draw(alexTexture, alex.x, alex.y); // draw alex
for(Rectangle parts: part){
game.batch.draw(partsImg, parts.x, parts.y); // draw part
}
game.font.draw(game.batch, scoreName, 25, 100); // draw scoreboard
game.batch.end(); // end drawing to screen
//******************************************************************************
//HERE IS WHERE I AM TRYING TO PUT IT
part.x += beltspeed;
if (part.rectangle overlaps ender.rectangle){
despawn part;
}
//******************************************************************************
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void dispose() {
}
}
Hello I am very new to LibGDX, and after doing some research I decided to make a game where you are a factory worker named Alex and you build toys. I will gladly take any feedback you have to make my code more orginized or work better. I highlighted everything I believe to be relevant to my question with some asterisks.
But my question is: How do you make a 'rectangle' such as my 'part' move on its own. I added a beltspeed and a spawn zone, and once the hitbox for it goes over the 'ender' hitbox I would like to despawn it.
Also I haven't gotten this far yet, but when the 'part' hitbox passes over 'Alex' hitbox I would like a little minigame to appear where you have to press up, down, left, right (randomly) to build the toy. If you have any suggestions on how I should handle that, I would be very appreciative.
"C:\Program Files\Java\jdk1.7.0_79\jre\bin\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\desktop;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\core;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx\1.9.2\e641cb91bec06bc64d9ddf7a7d7062caceec73cd\gdx-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d\1.9.2\b78eaa90aaaf7830e6dffff587ea6e859c2787b2\gdx-box2d-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype\1.9.2\3609253d14edb1b3ca5aacff4e06989edde75be4\gdx-freetype-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-lwjgl\1.9.2\d710a8704ed584ec2ba9ca52e3a6a5885dd759cc\gdx-backend-lwjgl-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-platform\1.9.2\dde4cf7e9ce61c24042f512203aed87657496639\gdx-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d-platform\1.9.2\497cbfbf81e7e8b1e8433b19291c5af4bbc2ec66\gdx-box2d-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-tools\1.9.2\37d8e3009ae0febdf93717b21980c67c8cadac07\gdx-tools-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype-platform\1.9.2\1e1afb0b6c9e8aeb7d495cb8f55c353d3da58cf0\gdx-freetype-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl\2.9.2\a9d80fe5935c7a9149f6584d9777cfd471f65489\lwjgl-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl_util\2.9.2\4b9e37300a87799856e0bd15ed81663cdb6b0947\lwjgl_util-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.jlayer\jlayer\1.0.1-gdx\7cca83cec5c1b2f011362f4d85aabd71a73b049d\jlayer-1.0.1-gdx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.jcraft\jorbis\0.0.17\8872d22b293e8f5d7d56ff92be966e6dc28ebdc6\jorbis-0.0.17.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-headless\1.9.2\813e6020de85cd831f02cb5e9060fd7ea8cb208e\gdx-backend-headless-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\510c7d317f5e9e700b9cfaac5fd38bdebf0702e0\lwjgl-platform-2.9.2-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d276cdf61fe2b516c7b7f4aa1b8dea91dbdc8d56\lwjgl-platform-2.9.2-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d55b46b40b40249d627a83a7f7f22649709d70c3\lwjgl-platform-2.9.2-natives-osx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput\2.0.5\39c7796b469a600f72380316f6b1f11db6c2c7c4\jinput-2.0.5.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jutils\jutils\1.0.0\e12fe1fda814bd348c1579329c86943d2cd3c6a6\jutils-1.0.0.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\7ff832a6eb9ab6a767f1ade2b548092d0fa64795\jinput-platform-2.0.5-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\385ee093e01f587f30ee1c8a2ee7d408fd732e16\jinput-platform-2.0.5-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\53f9c919f34d2ca9de8c51fc4e1e8282029a9232\jinput-platform-2.0.5-natives-osx.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.rafiredog.game.desktop.DesktopLauncher
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.rafiredog.game.gameMain.render(gameMain.java:97)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.rafiredog.game.main.render(main.java:45)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:223)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
Process finished with exit code 0
Lastly, I am now getting this error. I moved some code around near the 'batch.draw'. However that might not be the cause of the error? I am a little lost right now. But I will gladly screenshot what I have of the game now once the errors are resolved.
Thank you for any insight you have on fixing up this game.
You need to do game updates and then rendering on each cycle of the game loop. The game update part of your code can iterate through your objects to do stuff to them.
For example, your render method would look like this. You need to explicitly use an Iterator for your for loop because you otherwise could not remove items from the list while iterating.
#Override
public void render(float delta) {
//Update game
Iterator<Rectangle> iterator = parts.iterator();
while (iterator.hasNext()){
Rectangle part = iterator.next();
part.x += beltSpeed * delta; //distance = speed * time
if (part.rectangle.overlaps(ender.rectangle)){
iterator.remove(); //removes rectangle from the list
}
}
//This is also where you would update movement for anything else,
//such as a character jumping, or counting down a timer and spawning
//something when it reaches zero, for example.
//Draw everything
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
//...
game.batch.end();
}
If you spawn and "despawn" a lot of objects, you will probably need to use pooling to avoid stutters from memory deallocation. You can do this by replacing new Rectangle() with Pools.obtain(Rectangle.class) and adding the line Pools.free(part) right after iterator.remove().
I also noticed you have counter-intuitive usage of the words "part" and "parts" by swapping plural and singular. Make sure that doesn't trip you up.
As for your NullPointerException, read here.
Piggy backing onto Tenfour04's answer and attempting to answer your question in the comments. I'd suggest looking at this link: https://github.com/libgdx/libgdx/wiki/The-life-cycle

render to FrameBuffer not working in combination with ShapeRenderer in a custom Actor (libgdx)

I try to implement a custom Actor which displays contents of a FrameBuffer by extending Image. Inside I'd like to draw using a ShapeRenderer.
public class CustomActor extends Image {
private FrameBuffer frameBuffer = null;
private ShapeRenderer shapeRenderer = new ShapeRenderer();
private int width;
private int height;
public CustomActor() {
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
shapeRenderer.setAutoShapeType(true);
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (frameBuffer == null) {
frameBuffer = new FrameBuffer(Pixmap.Format.RGB565, width / 2, height / 2, false);
TextureRegion textureRegion = new TextureRegion(frameBuffer.getColorBufferTexture());
textureRegion.flip(false, true);
setDrawable(new TextureRegionDrawable(textureRegion));
}
frameBuffer.begin();
// render content
Gdx.gl.glClearColor(0, 1, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setColor(Color.WHITE);
shapeRenderer.rect(0, 0, frameBuffer.getWidth() / 2, frameBuffer.getHeight() / 2);
shapeRenderer.end();
if (frameBuffer != null) {
frameBuffer.end();
}
super.draw(batch, parentAlpha);
}
}
When deleting the ShapeRenderer part I can see the green background in the scene. But as soon as I use the ShapeRenderer the content is black. There is no white rectangle visible.
Any ideas what I am doing wrong?
Just found out that using my own SpriteBatch (with begin() and end()) after the FrameBuffer end() it works. So the problem seems to have to do with the calling order of the FrameBuffers methods and the SpriteBatches methods. Ending the given actor batch before beginning the FrameBuffer and "re"-beginning it to draw the actor is also working (see comment above).

How is it possible to fade-out a TextButton after it has been pressed?

I simply want to fade-out (opacity = completely transparent) a button after I've pressed it... the following code has the unexplainable effect of fading the background image (a totally different actor!) to black !
What am I doing wrong ?
Skin skin = new Skin();
TextureAtlas buttonAtlas = new TextureAtlas(Gdx.files.internal("gfx/menu_buttons.pack"));
skin.addRegions(buttonAtlas);
TextButtonStyle textButtonStyle = new TextButtonStyle();
textButtonStyle.font = mButtonSpacefont;
textButtonStyle.up = skin.getDrawable("menu_button_background_top");
textButtonStyle.down = skin.getDrawable("menu_button_background_bottom");
mButtonStartGame = new TextButton("Play", textButtonStyle);
mButtonStartGame.setPosition(game.getIdealWidth()/2 - mButtonStartGame.getWidth()/2,
game.getIdealHeight()/2 - mButtonStartGame.getHeight()/2);
mButtonStartGame.addListener(new ChangeListener()
{
#Override
public void changed (ChangeEvent event, Actor actor)
{
//triggers when button is pressed and let go
mButtonStartGame.addAction(Actions.fadeOut( 1.0f ));
}
});
// add actors to stage
mStage.addActor(backgroundActor);//background
mStage.addActor(titleActor);//ontop of background
mStage.addActor(mButtonStartGame);//ontop of background
UPDATE 1:
I've discovered that the TextButton is faded out - BUT - so is the actor that contains the background image backgroundActor ! Why would the backgroundActor be faded when the code doesn't even call backgroundActor.addAction(Actions.fadeOut( 1.0f )); ??
UPDATE 2:
The render() method seems to play a part... when I call Gdx.gl.glClearColor(0, 0, 0, 0); the whole screen (except for the titleActor!) turns black due to the fadeOut action. When I call Gdx.gl.glClearColor(1, 1, 1, 1); the whole screen (except for the titleActor!) turns white.
#Override
public void render(float delta)
{
Gdx.gl.glClearColor(0, 0, 0, 0);//clear the screen black
//Gdx.gl.glEnable(GL20.GL_BLEND);// no effect, so commented out
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
// update the actors
mStage.act(Gdx.graphics.getDeltaTime());
// draw the actors
mStage.draw();
}
The solution was that all of my actor's need to take into consideration the parentAlpha and set the color with batch.setColor().
Since my background was an actor, and I wasn't setting the batch color, the background was screwed up.
for example:
public class ActorBackground extends Actor
{
// Member Variables
private Texture mTexture;
// Constructor
public ActorBackground(GFXLoader gfxloader)
{
mTexture = new Texture(gfxloader.loadGraphic("menu_background"));// returns Gdx.files.internal(file.path())
//setBounds(getX(), getY(), mTexture.getWidth(), mTexture.getHeight());
setWidth(mTexture.getWidth());
setHeight(mTexture.getHeight());
}
#Override
public void draw(Batch batch, float parentAlpha)
{
// needed to make actions work
super.act(Gdx.graphics.getDeltaTime());
// needed to make fade work
Color color = new Color(this.getColor().r, this.getColor().g, this.getColor().b, this.getColor().a * parentAlpha);
batch.setColor(color);
// show it
batch.draw(mTexture, getX(), getY(), getWidth(), getHeight());
}
}

Distance field font in libgdx

I'm trying to rendering smooth scalable bitmap fonts. After checking this question one of the answers mentioned using distance field fonts.
I'm doing exactly as mentioned in LibGDX wiki article about distance filed fonts. However I can't get it working. Fonts are rendered hazy.
Here's the code I used to generate this output
public class FontRenderTest implements ApplicationListener {
private Texture texture;
private SpriteBatch spriteBatch;
private BitmapFont font;
#Override
public void create() {
spriteBatch = new SpriteBatch();
Texture texture = new Texture(Gdx.files.internal("Raleway.png"), true); // true enables mipmaps
texture.setFilter(TextureFilter.MipMapLinearNearest, TextureFilter.Linear); // linear filtering in nearest mipmap image
font = new BitmapFont(Gdx.files.internal("Raleway.fnt"), new TextureRegion(texture), false);
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
font.draw(spriteBatch, "This is hazy !!", 100, 150);
spriteBatch.end();
}
}
I'm not sure if I properly understand the function of distance field font. If anyone could explain how to render font smooth.
I think it needs a shader and if I recall right the shaders require GL20. As it said in the wiki you would need .frag and .vert files. I modified your code with the help from this Libgdx test: http://git.io/-yAmNg .
It looks like this with different smoothing.
public class FontRenderTest implements ApplicationListener {
private Texture texture;
private SpriteBatch spriteBatch;
private BitmapFont font;
private DistanceFieldShader distanceFieldShader;
private static class DistanceFieldShader extends ShaderProgram {
public DistanceFieldShader () {
// The vert and frag files are copied from http://git.io/yK63lQ (vert) and http://git.io/hAcw9Q (the frag)
super(Gdx.files.internal("data/shaders/distancefield.vert"), Gdx.files.internal("data/shaders/distancefield.frag"));
if (!isCompiled()) {
throw new RuntimeException("Shader compilation failed:\n" + getLog());
}
}
/** #param smoothing a value between 0 and 1 */
public void setSmoothing (float smoothing) {
float delta = 0.5f * MathUtils.clamp(smoothing, 0, 1);
setUniformf("u_lower", 0.5f - delta);
setUniformf("u_upper", 0.5f + delta);
}
}
#Override
public void create() {
spriteBatch = new SpriteBatch();
Texture texture = new Texture(Gdx.files.internal("hiero.png"), true); // true enables mipmaps
texture.setFilter(TextureFilter.MipMapLinearNearest, TextureFilter.Linear); // linear filtering in nearest mipmap image
font = new BitmapFont(Gdx.files.internal("hiero.fnt"), new TextureRegion(texture), false);
distanceFieldShader = new DistanceFieldShader();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
spriteBatch.setShader(distanceFieldShader);
font.draw(spriteBatch, "This is pretty sharp !!", 100, 120);
distanceFieldShader.setSmoothing(0f);
spriteBatch.setShader(distanceFieldShader);
font.draw(spriteBatch, "This is hazy !!", 100, 150);
distanceFieldShader.setSmoothing(1f);
spriteBatch.setShader(distanceFieldShader);
font.draw(spriteBatch, "This is pretty smooth !!", 100, 180);
distanceFieldShader.setSmoothing(1/2f);
spriteBatch.end();
}
Use the shader created by DistanceFieldFont.createDistanceFieldShader.