LWJGL/Slick-Util -- 画线仅在某些情况下显示
LWJGL/Slick-Util -- Draw Line displays only in some cases
我正在尝试学习更多关于图形和 GUI 元素的显示和交互的知识。作为其中的一部分,我一直在关注使用 LWJGL 和 Slick-Util 的塔防教程:https://www.youtube.com/watch?v=rfR09erJu7U&list=PLFUqwj4q1Zr8GHs6bO4d6gxMGUh_2pcNg
我自己扩展了一些东西,我正在尝试绘制一些带有纹理形状的基本无纹理形状。我可以绘制一条二维线,但是,它仅在绘制某些纹理形状后才出现,但在绘制其他纹理形状后不会出现。我想知道我不明白是什么导致了这种不同的行为。
这是我的主要class,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();
}
}
还有我的帮手class,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;
}
}
我的问题的重要部分在主要 class 内,就在这里:
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");
如有必要,我还可以上传我使用的两个 PNG 文件,但目前我的问题中不能包含超过 2 个链接。 bg.png 是单黑色 64x64 PNG。 exitbutton.png 是 512x512。
只是想了解造成这种情况的原因。谢谢!
问题很可能是您在 BeginSession()
方法中启用了纹理,然后在整个渲染过程中保持启用:
glEnable(GL_TEXTURE_2D);
这意味着您的线条将带有纹理。现在,你可能会说:"But... I'm not specifying texture coordinates for the lines!" 那没关系。 OpenGL 中的即时模式渲染 API 是基于状态的,因此最后指定的纹理坐标将被使用。由于你在drawLine()
之前调用了DrawQuadTex()
,所以在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);
}
关于如何追踪或完全避免此类问题的一些提示:
- 在开发过程中将清除颜色设置为黑色以外的颜色。然后您可以轻松判断您是在渲染黑色几何体,还是什么都不渲染。
- 使用基于着色器的渲染。固定功能管道乍一看可能更容易,但实际上并非如此。使用着色器,生成的颜色正是您实现的颜色,而不是基于一堆固定状态的值的一些神奇组合。
- 当您使用它时,您可能还想避免使用即时模式渲染。虽然不会直接导致此问题,但它与使用固定功能管道一样过时。
我正在尝试学习更多关于图形和 GUI 元素的显示和交互的知识。作为其中的一部分,我一直在关注使用 LWJGL 和 Slick-Util 的塔防教程:https://www.youtube.com/watch?v=rfR09erJu7U&list=PLFUqwj4q1Zr8GHs6bO4d6gxMGUh_2pcNg
我自己扩展了一些东西,我正在尝试绘制一些带有纹理形状的基本无纹理形状。我可以绘制一条二维线,但是,它仅在绘制某些纹理形状后才出现,但在绘制其他纹理形状后不会出现。我想知道我不明白是什么导致了这种不同的行为。
这是我的主要class,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();
}
}
还有我的帮手class,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;
}
}
我的问题的重要部分在主要 class 内,就在这里:
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");
如有必要,我还可以上传我使用的两个 PNG 文件,但目前我的问题中不能包含超过 2 个链接。 bg.png 是单黑色 64x64 PNG。 exitbutton.png 是 512x512。
只是想了解造成这种情况的原因。谢谢!
问题很可能是您在 BeginSession()
方法中启用了纹理,然后在整个渲染过程中保持启用:
glEnable(GL_TEXTURE_2D);
这意味着您的线条将带有纹理。现在,你可能会说:"But... I'm not specifying texture coordinates for the lines!" 那没关系。 OpenGL 中的即时模式渲染 API 是基于状态的,因此最后指定的纹理坐标将被使用。由于你在drawLine()
之前调用了DrawQuadTex()
,所以在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);
}
关于如何追踪或完全避免此类问题的一些提示:
- 在开发过程中将清除颜色设置为黑色以外的颜色。然后您可以轻松判断您是在渲染黑色几何体,还是什么都不渲染。
- 使用基于着色器的渲染。固定功能管道乍一看可能更容易,但实际上并非如此。使用着色器,生成的颜色正是您实现的颜色,而不是基于一堆固定状态的值的一些神奇组合。
- 当您使用它时,您可能还想避免使用即时模式渲染。虽然不会直接导致此问题,但它与使用固定功能管道一样过时。