1

LWJGL でゲームを開発しようとしているときに、奇妙なちらつきの問題が発生しています。このチュートリアルで提案されているように、GL_TEXTURE_RECTANGLE_ARB を使用しようとしています: http://youtu.be/Xj_qZ3Cw08Q

問題の短いビデオを次に示します: http://youtu.be/WUr_8aqoOrk

カメラが (glTransformf() を介して) 移動すると、各タイルに描画されるスプライトが、ここで問題を引き起こしているのと同じように、隣接するテクスチャを少しだけ表示しているように思えます。ただし、MIN_FILTER と MAG_FILTER を既に GL_NEAREST に設定しているので、これは問題ではないようです。

余分な詳細を省いて問題を示すために、ゲームを可能な限り単純化しました。ここで .zip を取得できます: https://dl.dropbox.com/u/22396951/Copy%20of%20Fezless.zip

編集:これは、一目でわかるコードです。

Fezless.java

package com.mrmikeanderson.fezless;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

import de.matthiasmann.twl.utils.PNGDecoder;
import static org.lwjgl.opengl.ARBTextureRectangle.*;
import static org.lwjgl.opengl.GL11.*;

public class Fezless {

    int w, h;
    boolean running;
    final int FPS = 60;
    double t = 0.0;
    final double dt = 1.0 / 60.0;
    Sprite currentSprite;
    Player player;
    Map<String, Sprite> spriteMap;
    int tiles;
    float camX, camY, shakeX, shakeY;

    String[] tileGrid = { "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "grass", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "dirt", "air", "air", "tardis", "air", "air", "air", "air", "air", "air", "air", "air", "air", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "air", "air", "air", "air", "dirt", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "air", "air", "air", "air", "deadplant", "dirt", "air", "air", "air", "air",
            "air", "air", "plant", "air", "air", "air", "air", "air", "air", "air", "air", "stone", "dirt", "dirt", "stone", "air", "air", "air", "deadplant", "dirt", "dirt", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "grass", "air", "air", "air", "air", "air", "air", "air", "stone", "air", "air", "air", "air", "air", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "grass", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "dirt", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "dirt", "dirt", "grass", "grass", "grass", "air", "air", "air", "air", "air", "air", "deadplant", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "air", "air", "air", "air", "air", "dirt", "dirt", "dirt", "stone", "stone", "stone", "stone",
            "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "plant", "air", "air", "air", "dirt", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "grass", "grass", "air", "air", "air", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "grass", "air", "air", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "dirt", "air", "air", "dirt", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt",
            "dirt", "dirt", "air", "air", "air", "air", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "dirt", "air", "air", "air", "air", "air", "air", "stone", "stone", "stone", "stone", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "dirt", "dirt", "air", "air", "air", "air", "air", "air", "air", "air", "air", "dirt", "dirt", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "stone", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "dirt", "stone", "stone", "stone", "dirt", "stone",
            "stone", "stone", "stone", "stone", "stone", "stone", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "air", "dirt", "dirt", "dirt", "dirt", "stone", "stone", "stone", "stone", "stone", "stone" };

    public Fezless(int w, int h) {
        this.w = w;
        this.h = h;
    }

    public void start() {
        init();
        running = true;
        run();
    }

    void init() {
        initDisplay();
        initGL();
        initSprites();
        player = new Player(13f, 4f, this);
//      level = new Level(player, this);
        camX = 14f;
        camY = -6f;
        shakeX = shakeY = 0f;
    }

    void initDisplay() {
        try {
            Display.setDisplayMode(new DisplayMode(w, h));
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
        }
    }

    void initGL() {
        glMatrixMode(GL_PROJECTION);
        double w = Display.getWidth() / 8;
        double h = Display.getHeight() / 8;
        glOrtho(-w / 2, w / 2, h / 2, -h / 2, -1f, 1f);
        glClearColor(.4f, .769f, 1f, 1f);
        glEnable(GL_TEXTURE_RECTANGLE_ARB);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glMatrixMode(GL_MODELVIEW);
    }

    void initSprites() {
        spriteMap = new HashMap<String, Sprite>();
        int texture = glGenTextures();
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
        InputStream in = null;
        try {
            in = new FileInputStream("res/tiles.png");
            PNGDecoder decoder = new PNGDecoder(in);
            ByteBuffer buffer = BufferUtils.createByteBuffer(4 * decoder.getWidth() * decoder.getHeight());
            decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
            buffer.flip();
            in.close();
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
        tiles = loadSpritesheet();
        spriteMap.put("air", new Sprite("air", 0, 0, 8, 8));
        spriteMap.put("gonzo", new Sprite("gonzo", 0, 8, 8, 16));
        spriteMap.put("grass", new Sprite("grass", 8, 0, 8, 8));
        spriteMap.put("plant", new Sprite("plant", 16, 8, 8, 8));
        spriteMap.put("deadplant", new Sprite("deadplant", 16, 16, 8, 8));
        spriteMap.put("dirt", new Sprite("dirt", 8, 8, 8, 8));
        spriteMap.put("stone", new Sprite("stone", 8, 16, 8, 8));
        spriteMap.put("platform", new Sprite("platform", 24, 0, 8, 8));
        spriteMap.put("obsidian", new Sprite("obsidian", 16, 0, 8, 8));
        spriteMap.put("tardis", new Sprite("tardis", 32, 0, 16, 24));
    }

    void run() {
        while (running && !Display.isCloseRequested()) {
            shakeX = (float) Math.sin(t + 100);
            shakeY = (float) Math.cos(t);

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            glLoadIdentity();
            glTranslatef(-camX * 8 + shakeX, camY * 8 + shakeY, 0f);

            for (int x = 0; x < 25; x++) {
                for (int y = 0; y < 21; y++) {
                    drawSprite(tileGrid[x + y * 25], x, y);
                }
            }
            player.render();

            t += dt;
            Display.update();
            Display.sync(FPS);
            Display.setVSyncEnabled(true);
        }
        cleanUp(false);
    }

    public void drawSprite(String name, float x, float y) {
        x *= 8;
        y *= 8;
        currentSprite = spriteMap.get(name);
        int u = currentSprite.x;
        int v = currentSprite.y;
        int u2 = currentSprite.x2;
        int v2 = currentSprite.y2;
        int w = currentSprite.w;
        int h = currentSprite.h;
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tiles);
        glBegin(GL_QUADS);
        glTexCoord2f(u, v);
        glVertex2f(x, y);
        glTexCoord2f(u, v2);
        glVertex2f(x, y + h);
        glTexCoord2f(u2, v2);
        glVertex2f(x + w, y + h);
        glTexCoord2f(u2, v);
        glVertex2f(x + w, y);
        glEnd();
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
    }

    int loadSpritesheet() {
        int texture = glGenTextures();
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
        InputStream in = null;
        try {
            in = new FileInputStream("res/tiles.png");
            PNGDecoder decoder = new PNGDecoder(in);
            ByteBuffer buffer = BufferUtils.createByteBuffer(4 * decoder.getWidth() * decoder.getHeight());
            decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.Format.RGBA);
            buffer.flip();
            in.close();
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
        return texture;
    }

    void cleanUp(boolean error) {
        Display.destroy();
        System.exit(error ? 1 : 0);
    }

    public static void main(String[] args) {
        Fezless f = new Fezless(800, 600);
        f.start();
    }
}

Player.java

package com.mrmikeanderson.fezless;

import java.awt.Rectangle;

public class Player {

    Fezless f;
    float x, y;
    boolean falling = false;
    String sprite;
    Rectangle boundingBox;

    public Player(float x, float y, Fezless f) {
        this.x = x;
        this.y = y;
        this.f = f;
        sprite = "gonzo";
    }

    public void render() {
        f.drawSprite(sprite, x, y);
    }
}

スプライト.java

package com.mrmikeanderson.fezless;

public class Sprite {

    String name;
    int x, y, x2, y2, w, h;

    public Sprite(String name, int x, int y, int w, int h) {
        this.name = name;
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        x2 = x + w;
        y2 = y + h;
    }
}
4

1 に答える 1

0

これはおそらくZバッファの戦いです。

で Z-Tests を無効にしてみましたglDisable(GL_DEPTH_TEST);か? または、背景をさらに遠くまでクリアします (についての参照glClearDepth) ? Z バッファ テストを使用する場合は、プレイヤー フィギュアをカメラに近づける必要もあります。

于 2012-09-17T23:46:38.680 に答える