Distance field font in libgdx - 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.

Related

LIBGDX Framebuffer is drawn as a black box

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

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).

LibGDX Scaling down

I've tried to scale down a 512 x 256 image of a rocket by setting the width and height directly. When I launch it the rocket image is pixely and very bad quality even though it is supposed a crisp vector image. I wanted to know how I would properly scale this down to still retain the quality.
public GameScreen(){
cam = new OrthographicCamera();
cam.setToOrtho(false, 600, 800);
batch = new SpriteBatch();
img = new Texture(Gdx.files.internal("data/rocket.png"));
batch.setProjectionMatrix(cam.combined);
}
#Override
public void show() {
}
#Override
public void render(float delta) {
cam.update();
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img,10, 10, 100, 60);
batch.end();
}
As Tenfour04 mentioned in comments you need to initialize Texture class with mipmaps enabled. Then set texture filters using setFilter method.
img = new Texture(Gdx.files.internal("data/rocket.png"), true);
img.setFilter(Texture.TextureFilter.MipMapLinearNearest, Texture.TextureFilter.Nearest);

LibGDX - How do I correctly add ExtendViewports?

I'm new to LibGDX and I am trying to get my screen resolution sizes set up first before I get into the actual game itself. Before I added extendViewport I had an orthographic Camera and an Image that displayed. But when I got rid of the orthographic camera and added the Viewport the image disappeared. Here is the code i have for the the screen.
public class GameScreen implements Screen {
SlingshotSteve game;
private ExtendViewport viewport;
PerspectiveCamera camera;
public void Menu(SlingshotSteve game){
this.game = game;
}
SpriteBatch batch;
TextureRegion backgroundTexture;
Texture texture;
GameScreen(final SlingshotSteve gam) {
this.game = gam;
batch = new SpriteBatch();
Texture texture = new Texture(Gdx.files.internal("background.jpg"));
backgroundTexture = new TextureRegion(texture, 0, 0, 500, 500);
Music mp3Sound = Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));
mp3Sound.setLooping(true);
mp3Sound.play();
}
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(backgroundTexture, 0, 0, SlingshotSteve.WIDTH, SlingshotSteve.HEIGHT);
batch.end();
}
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
#Override
public void dispose() {
batch.dispose();
texture.dispose();
}
#Override
public void show() {
camera = new PerspectiveCamera();
viewport = new ExtendViewport(800, 480, camera);
}
}
The other question I have is that this screen is the main game screen where Level 1 is going to occur. Since I added a main menu I had to switch from the "Application Listener" to the "Implement Screen". Is this correct, or do I have to go back to the Application Listener to get the Create() method? I'm not completely sure what everything means so If someone could please explain this to me that would be great!