LWJGL / Slick-Util - 仅在某些情况下显示绘制线

时间:2016-06-21 00:14:05

标签: java opengl lwjgl slick2d

我正在尝试了解有关显示和与图形和GUI元素交互的更多信息。作为其中的一部分,我一直在关注使用LWJGL和Slick-Util的塔防教程:https://www.youtube.com/watch?v=rfR09erJu7U&list=PLFUqwj4q1Zr8GHs6bO4d6gxMGUh_2pcNg

我自己扩展了一些东西,我试图用纹理形状绘制一些基本的无纹理形状。我可以得到一条2d线来绘制,但是,它仅在绘制某些纹理形状后绘制时出现,但在绘制其他纹理形状后不会出现。我想知道我不明白导致这种不同的行为。

这是我的主要类LineTest.java:

package main;

import static helpers.Artist.BeginSession;
import static helpers.Artist.DrawQuadTex;
import static helpers.Artist.QuickLoad;
import static helpers.Artist.drawLine;

import org.lwjgl.opengl.Display;
import org.newdawn.slick.opengl.Texture;

import helpers.Artist;

public class LineTest {

    public LineTest() {
        BeginSession();
        Texture bg = QuickLoad("bg");
        //Texture bg = QuickLoad("exitbutton");

        while(!Display.isCloseRequested()) {
            DrawQuadTex(bg,0,0,Artist.WIDTH,Artist.HEIGHT);
            drawLine(0,0,800,800);

            Display.update();
            Display.sync(60);
        }
        Display.destroy();
    }

    public static void main(String[] args) {
        new LineTest();
    }
}

我的助手类,Artist.java:

package helpers;

import static org.lwjgl.opengl.GL11.GL_BLEND;
import static org.lwjgl.opengl.GL11.GL_LINES;
import static org.lwjgl.opengl.GL11.GL_MODELVIEW;
import static org.lwjgl.opengl.GL11.GL_ONE_MINUS_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_PROJECTION;
import static org.lwjgl.opengl.GL11.GL_QUADS;
import static org.lwjgl.opengl.GL11.GL_SRC_ALPHA;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glBlendFunc;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glClearDepth;
import static org.lwjgl.opengl.GL11.glColor4f;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glLoadIdentity;
import static org.lwjgl.opengl.GL11.glMatrixMode;
import static org.lwjgl.opengl.GL11.glOrtho;
import static org.lwjgl.opengl.GL11.glTexCoord2f;
import static org.lwjgl.opengl.GL11.glTranslatef;
import static org.lwjgl.opengl.GL11.glVertex2f;

import java.io.IOException;
import java.io.InputStream;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

public class Artist {

    public static final int WIDTH = 640, HEIGHT = 480;

    public static void BeginSession() {
        Display.setTitle("Line Test");
        try {
            Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
        }

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, WIDTH, HEIGHT, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
        glEnable(GL_TEXTURE_2D);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClearDepth(1);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    public static void drawLine(int x1, int y1, int x2, int y2) {
        glColor4f(0.0f, 1.0f, 0.2f, 1.0f);
        glBegin(GL_LINES);
        glVertex2f((float) x1, (float) y1);
        glVertex2f((float) x2, (float) y2);
        glEnd();
        glColor4f(1f,1f,1f,1f);
    }   
    public static void DrawQuadTex(Texture tex, float x, float y, float width, float height) {
        tex.bind();
        glTranslatef(x, y, 0);
        glBegin(GL_QUADS);
        glTexCoord2f(0, 0);
        glVertex2f(0, 0);
        glTexCoord2f(1, 0);
        glVertex2f(width, 0);
        glTexCoord2f(1, 1);
        glVertex2f(width, height);
        glTexCoord2f(0,1);
        glVertex2f(0, height);
        glEnd();
        glLoadIdentity();
    }
    public static Texture LoadTexture(String path, String fileType) {
        Texture tex = null;
        InputStream in = ResourceLoader.getResourceAsStream(path);
        try {
            tex = TextureLoader.getTexture(fileType, in);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return tex;
    }

    public static Texture QuickLoad(String name) {
        Texture tex = null;
        tex = LoadTexture(name + ".png", "PNG");
        return tex;
    }
}

我的问题的重要部分是在主要课程内,就在这里:

Texture bg = QuickLoad("bg");
//Texture bg = QuickLoad("exitbutton");

while(!Display.isCloseRequested()) {
    DrawQuadTex(bg,0,0,Artist.WIDTH,Artist.HEIGHT);
    drawLine(0,0,800,800);

当我的Texture bg获取我的'bg'图形(纯黑色PNG文件)时,drawLine函数似乎实际上没有画线。但是,如果我更改我的Texture bg以获取我的'exitbutton'图形(蓝色方块中写有“Exit”,仍然是PNG文件),drawLine函数会创建一条可见线。

此imgur相册包含两者的输出:Texture bg = QuickLoad("bg");& Texture bg = QuickLoad("exitbutton");

http://imgur.com/a/OVOzD

如果有必要,我还可以上传我使用的两个PNG文件,但我目前在我的问题中不能包含2个以上的链接。 bg.png是单声道黑色64x64 PNG。 exitbutton.png是512x512。

只是想了解导致这种情况的原因。谢谢!

1 个答案:

答案 0 :(得分:0)

问题很可能是您在BeginSession()方法中启用了纹理,然后为整个渲染启用了它:

glEnable(GL_TEXTURE_2D);

这意味着您的线条会被纹理化。现在,您可以说:"但是......我没有指定线条的纹理坐标!"那不重要。 OpenGL中的立即模式渲染API是基于状态的,因此最后指定的纹理坐标是使用的那些。由于您在DrawQuadTex()之前致电drawLine(),因此在绘制线条时DrawQuadTex()中指定的最后一个纹理坐标将是您当前的纹理坐标:

glTexCoord2f(0,1);

因此,该线的颜色将是当前绑定纹理的位置(0,1)处的纹素,使用为该行指定的颜色进行调制:

glColor4f(0.0f, 1.0f, 0.2f, 1.0f);

如果两种颜色相乘则会产生黑色,例如因为给定的纹素是黑色的,结果将是黑色背景上的黑线。这看起来很像根本不渲染任何东西。

最干净的解决方案是仅在绘制要纹理的基元时启用纹理,然后禁用它。例如,在DrawQuadTex()方法中:

public static void DrawQuadTex(Texture tex, float x, float y, float width, float height) {
    tex.bind();
    glEnable(GL_TEXTURE_2D);
    ...
    glDisable(GL_TEXTURE_2D);
}

关于如何追踪这些类型的问题或完全避免它们的一些提示:

  1. 在开发过程中将清晰颜色设置为黑色以外的颜色。然后,您可以轻松判断您是否渲染黑色几何体,或者根本不知道。
  2. 使用基于着色器的渲染。固定功能管道最初可能看起来更容易,但事实并非如此。使用着色器时,生成的颜色正是您实现的颜色,而不是基于一堆固定状态的一些神奇的值组合。
  3. 当您处于此状态时,您可能还想避免使用立即模式渲染。虽然没有直接导致这个问题,但它与使用固定功能管道一样过时。