I'm having issues with the libGDX FrameBuffer and Alpha. Below are two images of the expected result and the actual result. Can someone please tell me what I am doing wrong and how can I correct it. Here is the code:
FrameBuffer buffer;
Sprite sprite;
SpriteBatch batch;
Texture texture1;
Texture texture2;
Texture texture3;
Sprite texture2Sprite;
#Override
public void create () {
batch = new SpriteBatch();
texture1 = new Texture("1.png");
texture2 = new Texture("2.png");
texture3 = new Texture("3.png");
texture2Sprite = new Sprite(texture2);
texture2Sprite.setAlpha(0.5f);
texture2Sprite.setPosition(100, 100);
buffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
sprite = new Sprite(buffer.getColorBufferTexture());
sprite.flip(false, true);
}
public void createFBO()
{
buffer.begin();
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(texture1, 0f, 0f);
texture2Sprite.draw(batch);
batch.end();
buffer.end();
}
#Override
public void render () {
createFBO();
Gdx.gl.glClearColor(0f, 0f, 1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.enableBlending();
batch.draw(texture3, 200, 200);
sprite.draw(batch);
batch.end();
}
Expected Result
Actual Result
I had pretty much the same issue with semi-transparent colours in the FrameBuffer, the problem and solution you can find on my badlogic forum topic here.
Basically, you need to draw to your FrameBuffer in a pre-multiplied alpha state. You do this by creating a custom fragment shader (my full code is on the topic). Then you set your blending mode to match (GL_ONE, GL_ONE_MINUS_SRC_ALPHA).
Then draw your sprite using the same blend function but default shader. You should end up with something like this;
public void createFBO(){
buffer.begin();
batch.begin();
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setShader(pmaShaderProgram); //pre-multiplied alpha ShaderProgram
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
batch.draw(texture1, 0f, 0f);
texture2Sprite.draw(batch);
batch.setShader(null); //default ShaderProgram
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); //default blend mode
batch.end();
buffer.end();
}
#Override
public void render () {
createFBO();
batch.begin();
batch.enableBlending();
Gdx.gl.glClearColor(0f, 0f, 1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.draw(texture3, 200, 200);
batch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);
sprite.draw(batch);
batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
batch.end();
}
Related
the code below keeps rendering a black screen...any ideas why? I put the base.tmx in the desktop folder and created it using tiled. did i put the .tmx in the wrong folder? its driving me nuts.
public class GameScreen extends ScreenAdapter {
OrthographicCamera camera;
TiledMap tiledmap;
TiledMapRenderer tiledMapRenderer;
public void show()
{
camera=new OrthographicCamera();
camera.setToOrtho(false);
camera.update();
tiledmap= new TmxMapLoader().load("base.tmx");
tiledMapRenderer=new OrthogonalTiledMapRenderer(tiledmap);
}
public void render()
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
tiledMapRenderer.setView(camera);
tiledMapRenderer.render();
}
}
You are not setting width and height of your camera. Also you should override render method of ScreenAdapter correctly with delta parameter. This is the updated version of your code :
public class GameScreen extends ScreenAdapter {
OrthographicCamera camera;
TiledMap tiledmap;
TiledMapRenderer tiledMapRenderer;
public void show()
{
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
camera=new OrthographicCamera();
camera.setToOrtho(false,w,h);
camera.update();
tiledmap= new TmxMapLoader().load("base.tmx");
tiledMapRenderer=new OrthogonalTiledMapRenderer(tiledmap);
}
public void render(float delta)
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
tiledMapRenderer.setView(camera);
tiledMapRenderer.render();
}
}
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).
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);
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.
I am trying to draw some lines for debugging using libgdx but I failed. this is my code
public class MainMenu extends Screen implements InputProcessor {
private OrthographicCamera camera;
SpriteBatch myBatch;
ShapeRenderer shapeDebugger;
public MainMenu(Game game) {
super(game);
camera= new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
myBatch.begin();
stage.draw();
Gdx.gl10.glLineWidth(10);
shapeDebugger.setProjectionMatrix(camera.combined);
shapeDebugger.begin(ShapeType.Line);
shapeDebugger.setColor(1, 1, 1, 1);
shapeDebugger.line(2, 2, 5, 5);
myBatch.end();
}
}
I get an error from line
shapeDebugger.setProjectionMatrix(camera.combined);
#Pranav008
thank you very much. I didn't expect that I need to initiate it. but I've got a true problem. I draw the line to center of the game screen like this.
Gdx.gl10.glLineWidth(2);
shapeDebugger.setProjectionMatrix(camera.combined);
shapeDebugger.begin(ShapeType.Line);
shapeDebugger.setColor(1, 1, 1, 1);
shapeDebugger.line(Gdx.graphics.getWidth()/2, 0,Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight());
shapeDebugger.end();
when I try to resize the screen it doesn't update the to center it goes far away to right.
You must have got nullpointerException because you haven't made any object of ShapeRenderer.
Insert this line in your constructor.
shapeDebugger=new ShapeRenderer();
Remember that nesting Shaperender with a SpriteBatch may cause problems.
Check this link.
My answer is mayby too late for you, but for people how have the same positioning problems.
Your second question about the position after a resize is because the viewport did not change.
Aldo your window size changed your application stil is using the same pixel size set on create by the function camera.setToOrtho
Update the view port on a resize!
//-----------------------------------------------------------------
#Override
public void resize (int width, int height) {
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();
}
Define & initialize ShapeRenderer
ShapeRenderer shapeDebugger;
#Override
public void create() {
shapeDebugger = new ShapeRenderer();
...
Draw line in render callback
#Override
public void render() {
//render scene
Gdx.gl.glClearColor(69f / 255, 90f / 255, 100f / 255, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
...
shapeDebugger.setProjectionMatrix(camera.combined);
shapeDebugger.begin(ShapeRenderer.ShapeType.Line);
Gdx.gl.glLineWidth(10 / camera.zoom);
shapeDebugger.setColor(1, 0, 0, 1);
shapeDebugger.line(screenWidth / 2, 0, screenWidth / 2, screenHeight);
shapeDebugger.line(0, screenHeight / 2, screenWidth, screenHeight / 2);
shapeDebugger.end();