12803

Java libgdx 1.20 version texture bug

Question:

For 2 days I've been trying to fix bug with fickering and distored textures in my game. I was serching on the internet and i tried a few solutions like using scene2d, but it didn't work. What should i do ?

This screenshot shows the problem: as the character moves, one eye is sometimes bigger than the other:

<img alt="Screenshot" class="b-lazy" data-src="https://i.stack.imgur.com/2orHK.png" data-original="https://i.stack.imgur.com/2orHK.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" />

<strong>edit:</strong>

I still got the problem widthdistored eye when i use sprite.setPosition((int) sprite.getX(), (int) sprite.getY()); every time before i render my character.

When i use custom viewport from the answer i see nothing on the game window what i do wrong?

package com.mygdx.redHoodie; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Screen; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.utils.viewport.StretchViewport; public class GameScreen implements Screen { public static final int GAME_WIDTH = 800; public static final int GAME_HEIGHT= 480 ; SpriteBatch batch; Background background; public Hoodie hoodie; public PixelMultipleViewport viewport; OrthographicCamera camera; public int gameMode; // 0 normalna gra, 1 level up, 2 end game public GameScreen(){ camera= new OrthographicCamera(GAME_WIDTH,GAME_HEIGHT); viewport = new PixelMultipleViewport(GAME_WIDTH, GAME_HEIGHT, camera); viewport.update(); camera.setToOrtho(false, GAME_WIDTH, GAME_HEIGHT); batch = new SpriteBatch(); //klasy wyswietlane background= new Background(this); hoodie = new Hoodie(this); startNewGame(); } @Override public void render(float delta) { // TODO Auto-generated method stu Gdx.gl.glClearColor(1, 1, 0, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); batch.setProjectionMatrix(camera.projection); batch.setTransformMatrix(camera.view); camera.update(); //batch.setProjectionMatrix(camera.combined); this.update(delta); this.batch.begin(); toRender(delta); this.batch.end(); } public void update(float delta){ hoodie.update(delta); } public void toRender(float delta){ background.render(); hoodie.render(); } public void startNewGame(){ } public void startNevLevel(){ } @Override public void resize(int width, int height) { // TODO Auto-generated method stub viewport.update(width, height,false); } @Override public void show() { // TODO Auto-generated method stub } @Override public void hide() { // TODO Auto-generated method stub } @Override public void pause() { // TODO Auto-generated method stub } @Override public void resume() { // TODO Auto-generated method stub } @Override public void dispose() { // TODO Auto-generated method stub } }

Answer1:

When loading your texture, use linear filtering and mip-mapping. The default filter is Nearest/Nearest, which will cause the issue you're seeing.

Texture myTexture = new Texture("textureFilename", true); //must enable mip-mapping in constructor myTexture.setFilter(TextureFilter.MipMapLinearNearest, TextureFilter.Linear);

<strong>EDIT:</strong>

I realize now, looking at your screenshot, that you are doing pixelated graphics in a larger window. In order to do this, yes you need to keep the Nearest/Nearest filtering, instead of what I suggested.

To avoid having the some of the pixels vary in size, you must round off character movement and camera movement to the nearest world unit. When your character is partway between pixels, the size of the sprite pixels varies because they don't line up with the screen pixels.

You have your world scaled so one unit equals one of your large pixels. So whenever you draw anything, you need to first round its position to the nearest integer in the x and the y, as well as the camera position. So after you move the camera or the sprites, you must do something like this:

sprite.position.set((int)sprite.position.x,(int)sprite.position.y,sprite.position.z);

As far as your Viewport goes, if you don't want any black bars, you will probably need a custom Viewport class that tries to match your desired resolution as closely as possible and then extends it outwards to avoid distortion. ExtendViewport does something similar, but the difference with pixellated graphics is that you need the world resolution to be an integer multiple of the screen's resolution so the edges of pixels look crisp rather than fuzzy.

I think this will do what you want. It takes your desired screen resolution and shrinks it to fit where the size of each of your pixels in screen pixels is an integer. Then it extends the view beyond your desired resolution to avoid distortion and black bars. This class makes the assumption that all screen dimensions are always a multiple of 4. I <em>think</em> that's true. If you want to get fancy, you could use OpenGL scissoring to round down the viewport size to the nearest multiples of 4, to be safe. At most you would be having 2 pixels of black bar, which I don't think would be noticeable.

public class PixelMultipleViewport extends Viewport { private int minWorldWidth, minWorldHeight; public PixelMultipleViewport (int minWorldWidth, int minWorldHeight, Camera camera) { this.minWorldHeight = minWorldHeight; this.minWorldWidth = minWorldWidth; this.camera = camera; } @Override public void update (int screenWidth, int screenHeight, boolean centerCamera) { viewportWidth = screenWidth; viewportHeight = screenHeight; int maxHorizontalMultiple = screenWidth / minWorldWidth; int maxVerticalMultiple = screenHeight / minWorldHeight; int pixelSize = Math.min(maxHorizontalMultiple, maxVerticalMultiple); worldWidth = (float)screenWidth/(float)pixelSize; worldHeight = (float)screenHeight/(float)pixelSize; super.update(screenWidth, screenHeight, centerCamera); } }

Answer2:

Here's a different option I just came across. This is a way to draw your scene at the scale you like without black bars, at any resolution.

The visual quality will be slightly worse than in my other answer (where you draw at an integer multiple of your desired scene scale), but significantly better than using straight nearest filtering like in your screenshot.

The basic idea is to draw everything to a small FrameBuffer at the scale you want, and then draw the FrameBuffer's color texture to the screen using an upscaling shader that (unlike linear filtering) interpolates pixel colors only along the edges of sprite pixels.

The explanation <a href="https://www.allegro.cc/forums/thread/612318" rel="nofollow">is here</a>. I have not ported this to Libgdx or tested it. And I'm not sure how well this shader would run on mobile. It involves running four dependent texture look-ups per screen fragment.

Recommend

  • How to stop drawing a SpriteBatch animation in libgdx?
  • opengl+glut glutPostRedisplay where?
  • Sprite not moving properly. libgdx
  • Is there a difference between glClearColor(0.0,0.0,0.0,0.0) and glClear(COLOR_BUFFER_BIT)?
  • GLUT is working fine but OpenGL is not doing anything
  • GLUT + OpenGL multisampling anti aliasing (MSAA)
  • Multiple Windows OpenGL/Glut
  • How to use dispatch_async in glkview?
  • OpenGL transparency not working
  • Can't map textures with OpenGL ES on real devices
  • Rendering .obj files with OpenGL
  • Black stripes in LIBGDX
  • Diffuse shader for OpenGL ES 2.0: Light changes with camera movement (Vuforia on Android)
  • OpenGL gimbal lock
  • First person camera weird behaviour on moving the eye
  • LibGDX: Android SpriteBatch not drawing
  • Linker error with glew and Visual Studio on windows 7
  • ggplot2: Plotting regression lines with different intercepts but with same slope
  • Issues with wmode=“opaque” and issues with wmmode=“window”
  • Recreate Apple Watch fitness tracker ‘progress’ bar - gradient on CAShapeLayer stroke
  • opengl window freezing during move/resize
  • Gerrit will not push. Error: No common ancestry
  • how can I key rotate for google cloud storage service account?
  • I don't get what's the difference between format() and … (python)
  • Fragment gives me an error while inflating 1
  • How to define an array of floats in Shader properties?
  • XOR with Neural Networks (Matlab)
  • Scala: Function returning an unknown type
  • Correct implementation of List Iterator methods
  • Problems compiling files using JOGL
  • How to avoid particles glitching together in an elastic particle collision simulator?
  • Update CALayer sublayers immediately
  • JFileChooser in front of fullscreen Swing application
  • Opengl-es onTouchEvents problem or a draw problem? [closed]
  • Trying to switch camera back to front but getting exception
  • unknown Exception android
  • EntityFramework adding new object to nested object collection
  • Checking variable from a different class in C#
  • failed to connect to specific WiFi in android programmatically
  • How can I use threading to 'tick' a timer to be accessed by other threads?