opengl纹理无法正确渲染

时间:2011-08-12 18:52:20

标签: java opengl graphics textures

我遇到的问题是我无法让我的纹理以正确的比例渲染,并且由于某种原因,纹理也会重复自身,中间有一个空格。

这是使用的纹理(我正在用这种纹理填充屏幕):

Texture

渲染时看起来像这样(红色轮廓是整个屏幕,纹理用1像素边框渲染):

screenshot

这是代码:

package game;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.Timer;
import org.lwjgl.util.glu.GLU;
import org.newdawn.slick.opengl.TextureLoader;

public class WarZone {

private boolean done = false;
private String windowTitle = "War Zone";
private DisplayMode displayMode;
private Timer timer;
private float dt;

public static void main(String[] args) {
    new WarZone().run(false);
}

public void run(boolean fullscreen) {
    try {
        init();
        switchToOrtho();
        while (!done) {
            timer.tick();
            update();
            render();
            Display.update();
        }
        cleanup();
    } catch (Exception e) {
        e.printStackTrace();
        System.exit(0);
    }
}

private void update() {
    // Exit if Escape is pressed or window is closed
    if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) || Display.isCloseRequested()) {
        done = true;
        return;
    }
}

private boolean render() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);  // Clear the screen and the depth buffer
    GL11.glLoadIdentity();                                              // Reset the current modelview matrix

    int w = displayMode.getWidth();
    int h = displayMode.getHeight();

    GL11.glColor3f(1, 0, 0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
    GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex2i(0, 0);
        GL11.glVertex2i(w, 0);
        GL11.glVertex2i(w, h);
        GL11.glVertex2i(0, h);
    GL11.glEnd();
    //if(true)return false;
    GL11.glColor3f(0, 1, 1);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 1);
    GL11.glBegin(GL11.GL_QUADS);
        GL11.glTexCoord2f(0, 0);
        GL11.glVertex2i(1, 1);
        GL11.glTexCoord2f(1, 0);
        GL11.glVertex2i(w - 1, 1);
        GL11.glTexCoord2f(1, 1);
        GL11.glVertex2i(w - 1, h - 1);
        GL11.glTexCoord2f(0, 1);
        GL11.glVertex2i(1, h - 1);
    GL11.glEnd();

    return true;                                                        // Rendered correctly
}

public static void switchToOrtho() {
    GL11.glDisable(GL11.GL_DEPTH_TEST);
    GL11.glDisable(GL11.GL_LIGHTING);
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glPushMatrix();
    GL11.glLoadIdentity();
    GL11.glOrtho(0, Display.getDisplayMode().getWidth(), 0, Display.getDisplayMode().getHeight(), -1, 1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
}

public static void switchToFrustum() {
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glEnable(GL11.GL_LIGHTING);
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glPopMatrix();
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
}

private void init() throws Exception {
    createWindow();
    initGL();
    load();
}

private void load() throws FileNotFoundException, IOException {
    TextureLoader.getTexture("BMP", new FileInputStream("res/temp/Main_Menu_Play_Button.bmp"), true).getTextureID();
}

private void createWindow() throws Exception {
    DisplayMode availibleDisplayModes[] = Display.getAvailableDisplayModes();
    for (DisplayMode d:availibleDisplayModes) {
        if (d.getWidth() == 640 && d.getHeight() == 480 && d.getBitsPerPixel() == 32) {
            displayMode = d;
            break;
        }
    }
    Display.setDisplayMode(displayMode);
    Display.setTitle(windowTitle);
    Display.create();
}

private void initGL() {
    GL11.glEnable(GL11.GL_TEXTURE_2D);          // Enable texture mapping
    GL11.glShadeModel(GL11.GL_SMOOTH);          // Enable smooth shading
    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  // Black background
    GL11.glClearDepth(1.0f);                    // Depth buffer setup
    GL11.glEnable(GL11.GL_DEPTH_TEST);          // Enables depth testing
    GL11.glDepthFunc(GL11.GL_LEQUAL);           // Type of depth testing

    GL11.glMatrixMode(GL11.GL_PROJECTION);      // Select projection matrix
    GL11.glLoadIdentity();                      // Reset the projection matrix

    // Calculate the aspect ratio of the window
    GLU.gluPerspective(45.0f, (float)displayMode.getWidth() / (float)displayMode.getHeight(), 0.1f, 100.0f);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);// Select the modelview matrix
    GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);// Most precise perspective calculations
}

public void requestFinish() {
    done = true;
}

private void cleanup() {
    Display.destroy();
}

}
如果有人能告诉我自己做错了什么,我会很感激。

2 个答案:

答案 0 :(得分:5)

首先,我不知道TextureLoadernewdawn.slick.opengl是什么,因此我只能提供有限的信息。

但是,纹理加载代码很可能不知道如何处理非二次幂纹理。这意味着它可能会将纹理的大小填充到最接近的2的幂。

更重要的是:

GL11.glColor3f(0, 1, 1);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 1);
GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex2i(1, 1);
    GL11.glTexCoord2f(1, 0);
    GL11.glVertex2i(w - 1, 1);
    GL11.glTexCoord2f(1, 1);
    GL11.glVertex2i(w - 1, h - 1);
    GL11.glTexCoord2f(0, 1);
    GL11.glVertex2i(1, h - 1);
GL11.glEnd();

这将绘制一个屏幕大小的四边形(假设wh是屏幕尺寸)。此四边形将纹理的整个区域映射到此四边形。 OpenGL只执行你告诉它要做的事情:获取纹理并将其映射到四边形。

如果要绘制像素精度(1:1纹素到像素)的纹理,则需要为顶点位置提供等于纹理大小的宽度和高度,不是屏幕尺寸。

此外,您将颜色设置为(0,1,1)。默认纹理环境将每顶点颜色乘以从纹理获取的纹素值。因此,您应该将颜色设置为白色,或更改纹理环境。

答案 1 :(得分:0)

OpenGL如果我记得的话,不喜欢不是2的力量的纹理。高度和宽度的纹理是2的幂吗?

http://www.gamedev.net/topic/466904-opengl-textures-only-power-of-two/