【问题标题】:Java libgdx 1.20 version texture bugJava libgdx 1.20 版本纹理错误
【发布时间】:2019-04-05 04:30:34
【问题描述】:

两天来,我一直在尝试修复我的游戏中纹理变形和扭曲的错误。我在互联网上搜索并尝试了一些解决方案,例如使用 scene2d,但没有奏效。我该怎么办?

这个截图显示了问题:随着角色移动,有时一只眼睛比另一只眼睛大:

编辑:

当我使用 sprite.setPosition((int) sprite.getX(), (int) sprite.getY());每次在我渲染我的角色之前。

当我使用答案中的自定义视口时,我在游戏窗口上什么也看不到我做错了什么?

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

    }

}

【问题讨论】:

  • 在不知道如何加载纹理的情况下很难计算。你能提供代码吗?可能引入了错误,或者您以意想不到的方式使用纹理。从 libgdx 社区论坛看,这似乎不是一个普遍的问题,因为那里没有人抱怨过。
  • 当我在本教程theinvader360.blogspot.co.uk/2013/05/… 中进行相同的项目时,我遇到了这个错误,但当我从这个stackoverflow 问题复制粘贴解决方案时:stackoverflow.com/questions/18997013/…
  • 也许您可以更详细地描述闪烁和失真的含义,因为这些术语对不同的人意味着不同的东西。例如,您刚刚链接的另一个问题似乎与精灵从一个位置到另一个位置的抖动有关,这不是我所说的闪烁。
  • 我的角色有黑色的长方形小眼睛,在视口的一些线中,一只眼睛比另一只眼睛大。在 1.0 中我没有这个问题。
  • 这可能与相机设置和纹理过滤模式的某种组合有关。如果您显示您的代码,也许我们可以解决。

标签: libgdx textures


【解决方案1】:

加载纹理时,请使用线性过滤和 mip 映射。默认过滤器是 Nearest/Nearest,这将导致您看到的问题。

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

编辑:

我现在意识到,看着你的截图,你正在一个更大的窗口中做像素化的图形。为了做到这一点,是的,您需要保留最近/最近过滤,而不是我建议的。

为避免某些像素的大小发生变化,您必须将角色移动和摄像机移动四舍五入到最近的世界单位。当您的角色位于像素之间时,精灵像素的大小会发生变化,因为它们不会与屏幕像素对齐。

您的世界已缩放,因此一个单位等于您的大像素之一。因此,无论何时绘制任何东西,都需要先将其位置四舍五入到 x 和 y 中最接近的整数,以及相机位置。因此,在您移动相机或精灵之后,您必须执行以下操作:

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

就您的视口而言,如果您不想要任何黑条,您可能需要一个自定义视口类,该类会尝试尽可能地匹配您所需的分辨率,然后将其向外扩展以避免失真。 ExtendViewport 做了类似的事情,但与像素化图形的不同之处在于,您需要将世界分辨率设为屏幕分辨率的整数倍,这样像素的边缘才会看起来清晰而不是模糊。

我认为这会满足您的需求。它采用您想要的屏幕分辨率并将其缩小以适应屏幕像素中每个像素的大小为整数的情况。然后它将视图扩展到您想要的分辨率之外,以避免失真和黑条。此类假设所有屏幕尺寸始终是 4 的倍数。我认为确实如此。如果你想变得花哨,你可以使用 OpenGL 剪裁将视口大小四舍五入到最接近的 4 倍数,以确保安全。最多你会有 2 个像素的黑条,我认为这不会很明显。

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);
    }
}

【讨论】:

  • 使用这个纹理过滤器效果更好,但现在眼睛看起来像在迷雾后面。 snag.gy/2hBqV.jpg
  • 我刚刚检查过,在拉伸视口中我仍然遇到同样的问题。
  • 当我使用 FitViewport 时更好。反正有没有黑条和没有扭曲的纹理?
  • 好的,我知道如何解决它...我会改变这个答案。
  • 我仍然遇到像素失真的问题,当我使用这个 wiev 端口时,我在游戏窗口上看不到黑屏。查看我的问题更新。
【解决方案2】:

这是我刚刚遇到的另一个选项。这是一种在任何分辨率下以您喜欢的比例绘制场景的方法,没有黑条。

视觉质量会比我的其他答案(您以所需场景比例的整数倍绘制)稍差,但比使用屏幕截图中的直接最近过滤要好得多。

基本思想是将所有内容以您想要的比例绘制到一个小的 FrameBuffer 中,然后使用升级着色器(与线性过滤不同)仅沿精灵像素的边缘插入像素颜色,将 FrameBuffer 的颜色纹理绘制到屏幕上.

解释is here。我还没有将它移植到 Libgdx 或对其进行测试。而且我不确定这个着色器在移动设备上的运行效果如何。它涉及每个屏幕片段运行四个相关的纹理查找。

【讨论】:

    【解决方案3】:

    我知道这个话题很老了,但由于我的搜索将我带到了这里,未来可能会有更多的人关注。我遇到了同样的像素撕裂问题,但仅限于我的 iOS 9 iPhone 4S。它在我的 Android 9 Pixel 2 上渲染得很好。尝试了很多东西(尤其是四舍五入到全像素),但即使使用未缩放的全屏正交相机,它也会受到伪影的影响。

    强制我的纹理为 POT(2 的幂)解决了这个问题!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 2023-04-01
      • 1970-01-01
      相关资源
      最近更新 更多