LWJGL 3 不会划线
LWJGL 3 Won't Draw A Line
我正在尝试与 LWJGL 3 划清界线。它编译并且所有本地设置都正确。我 运行 Ubuntu。我真的不明白问题出在哪里; window 初始化并且背景是正确的清晰颜色,但线条不会绘制。我几乎完全从我在他们的新网站上找到的唯一示例中复制了代码。我不知道我做错了什么。
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
import java.awt.DisplayMode;
import java.nio.ByteBuffer;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.Display;
import org.lwjgl.util.glu.GLU;
public class Main {
// We need to strongly reference callback instances.
private static GLFWErrorCallback errorCallback;
private static GLFWKeyCallback keyCallback;
static final int INIT_WIDTH = 300;
static final int INIT_HEIGHT = 300;
// The window handle
private static long window;
public static boolean verbose = true;
public static void init() {
final String WINDOW_TITLE = "WINDOW";
vPrint("Initializing GLFW...");
if (glfwInit() != GL11.GL_TRUE) {
throw new IllegalStateException("Unable to initialize GLFW");
}
vPrint("Done!\n");
//Window will be hidden after creation
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
//Window will be resizable
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
vPrint("Creating window...");
window = glfwCreateWindow(INIT_WIDTH, INIT_HEIGHT, WINDOW_TITLE, NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
} else {
vPrint("Done!\n");
}
//Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
@Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, GL_TRUE); // We will detect this in our rendering loop
}
});
// Get the resolution of the primary monitor
ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center our window
glfwSetWindowPos(
window,
(GLFWvidmode.width(vidmode) - INIT_WIDTH) / 2,
(GLFWvidmode.height(vidmode) - INIT_HEIGHT) / 2
);
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
GLContext.createFromCurrent();
//Set window clear color
glClearColor(0.5f, 0.0f, 0.0f, 0.0f);
initOpenGL();
}
public static void main(String[] args) {
try {
init();
loop();
glfwDestroyWindow(window);
keyCallback.release();
} finally {
glfwTerminate();
errorCallback.release();
}
}
public static void loop() {
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glfwSwapBuffers(window); // swap the color buffers
render();
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
private static void vPrint(String str) {
if (verbose) {
System.out.print(str);
}
}
private static void render() {
glColor3f(1, 1, 1);
glBegin(GL_LINE);
glVertex2f(10, 10);
glVertex2f(20, 20);
glEnd();
}
private static void initOpenGL() {
glViewport(0, 0, INIT_WIDTH, INIT_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(30.0f, (float)INIT_HEIGHT / (float)INIT_HEIGHT, 0.3f, 200.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
}
编辑: 我现在相当确定这是我使用 GL_LINE
;
的错误
这里有很多问题。
绘图调用
这里有一个常见但有时很难发现的错误:
glBegin(GL_LINE);
绘制线条的枚举是 GL_LINES
(注意尾随 S
)。另一方面,GL_LINE
是 glPolygonMode()
的可能参数之一。所以这个调用应该是:
glBegin(GL_LINES);
绘制循环中的调用顺序
渲染循环中的调用顺序看起来不对:
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSwapBuffers(window);
render();
glfwPollEvents();
}
glfwSwapBuffers()
调用指定您已完成渲染,并准备好呈现您渲染的内容。由于您是在调用 render()
之前进行调用,因此显示的只是已清除的缓冲区。
或者换个角度看,如果您单步执行循环结束和开始之间的调用序列,并忽略 glfwPollEvents() 调用,您的 render()
调用后紧跟 glClear()
。所以渲染的结果在它有机会被呈现之前就被清除了。
正确的调用顺序是:
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
render();
glfwSwapBuffers(window);
glfwPollEvents();
}
这将允许在 glfwSwapBuffers()
调用显示结果之前执行渲染。
坐标范围
您需要注意变换和坐标范围。当你只设置一个透视变换时,它会假设你的坐标在从原点向下看负 z 轴的近平面范围和远平面范围之间。作为模型视图矩阵的一部分,您需要在负 z 方向上进行平移,以便在查看体积内获取坐标。否则整个几何体将被剪掉。
例如,您可以在设置模型视图矩阵时添加一个 glTranslatef()
调用,这会将您的几何体放置在近平面和远平面之间:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -50.0f);
如果此解释不够充分,您可能需要查找解释 OpenGL 坐标系和变换的教程。
那是因为你的点数没有显示在屏幕上:
glVertex2f(10, 10);
glVertex2f(20, 20);
在这种情况下,坐标系在 x 和 y 中从 -1.0f 到 1.0f,屏幕中心为 0.0。
通过这样做你应该看到一些东西:
glVertex2f(0.0f, 0.0f);
glVertex2f(1.0f, 1.0f);
但是你的代码很好。
我正在尝试与 LWJGL 3 划清界线。它编译并且所有本地设置都正确。我 运行 Ubuntu。我真的不明白问题出在哪里; window 初始化并且背景是正确的清晰颜色,但线条不会绘制。我几乎完全从我在他们的新网站上找到的唯一示例中复制了代码。我不知道我做错了什么。
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.NULL;
import java.awt.DisplayMode;
import java.nio.ByteBuffer;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWKeyCallback;
import org.lwjgl.glfw.GLFWvidmode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.util.Display;
import org.lwjgl.util.glu.GLU;
public class Main {
// We need to strongly reference callback instances.
private static GLFWErrorCallback errorCallback;
private static GLFWKeyCallback keyCallback;
static final int INIT_WIDTH = 300;
static final int INIT_HEIGHT = 300;
// The window handle
private static long window;
public static boolean verbose = true;
public static void init() {
final String WINDOW_TITLE = "WINDOW";
vPrint("Initializing GLFW...");
if (glfwInit() != GL11.GL_TRUE) {
throw new IllegalStateException("Unable to initialize GLFW");
}
vPrint("Done!\n");
//Window will be hidden after creation
glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
//Window will be resizable
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
vPrint("Creating window...");
window = glfwCreateWindow(INIT_WIDTH, INIT_HEIGHT, WINDOW_TITLE, NULL, NULL);
if (window == NULL) {
throw new RuntimeException("Failed to create the GLFW window");
} else {
vPrint("Done!\n");
}
//Setup a key callback. It will be called every time a key is pressed, repeated or released.
glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback() {
@Override
public void invoke(long window, int key, int scancode, int action, int mods) {
if ( key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE )
glfwSetWindowShouldClose(window, GL_TRUE); // We will detect this in our rendering loop
}
});
// Get the resolution of the primary monitor
ByteBuffer vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
// Center our window
glfwSetWindowPos(
window,
(GLFWvidmode.width(vidmode) - INIT_WIDTH) / 2,
(GLFWvidmode.height(vidmode) - INIT_HEIGHT) / 2
);
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
// Make the window visible
glfwShowWindow(window);
GLContext.createFromCurrent();
//Set window clear color
glClearColor(0.5f, 0.0f, 0.0f, 0.0f);
initOpenGL();
}
public static void main(String[] args) {
try {
init();
loop();
glfwDestroyWindow(window);
keyCallback.release();
} finally {
glfwTerminate();
errorCallback.release();
}
}
public static void loop() {
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
glfwSwapBuffers(window); // swap the color buffers
render();
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
private static void vPrint(String str) {
if (verbose) {
System.out.print(str);
}
}
private static void render() {
glColor3f(1, 1, 1);
glBegin(GL_LINE);
glVertex2f(10, 10);
glVertex2f(20, 20);
glEnd();
}
private static void initOpenGL() {
glViewport(0, 0, INIT_WIDTH, INIT_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Calculate The Aspect Ratio Of The Window
GLU.gluPerspective(30.0f, (float)INIT_HEIGHT / (float)INIT_HEIGHT, 0.3f, 200.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
}
编辑: 我现在相当确定这是我使用 GL_LINE
;
这里有很多问题。
绘图调用
这里有一个常见但有时很难发现的错误:
glBegin(GL_LINE);
绘制线条的枚举是 GL_LINES
(注意尾随 S
)。另一方面,GL_LINE
是 glPolygonMode()
的可能参数之一。所以这个调用应该是:
glBegin(GL_LINES);
绘制循环中的调用顺序
渲染循环中的调用顺序看起来不对:
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwSwapBuffers(window);
render();
glfwPollEvents();
}
glfwSwapBuffers()
调用指定您已完成渲染,并准备好呈现您渲染的内容。由于您是在调用 render()
之前进行调用,因此显示的只是已清除的缓冲区。
或者换个角度看,如果您单步执行循环结束和开始之间的调用序列,并忽略 glfwPollEvents() 调用,您的 render()
调用后紧跟 glClear()
。所以渲染的结果在它有机会被呈现之前就被清除了。
正确的调用顺序是:
while ( glfwWindowShouldClose(window) == GL_FALSE ) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
render();
glfwSwapBuffers(window);
glfwPollEvents();
}
这将允许在 glfwSwapBuffers()
调用显示结果之前执行渲染。
坐标范围
您需要注意变换和坐标范围。当你只设置一个透视变换时,它会假设你的坐标在从原点向下看负 z 轴的近平面范围和远平面范围之间。作为模型视图矩阵的一部分,您需要在负 z 方向上进行平移,以便在查看体积内获取坐标。否则整个几何体将被剪掉。
例如,您可以在设置模型视图矩阵时添加一个 glTranslatef()
调用,这会将您的几何体放置在近平面和远平面之间:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -50.0f);
如果此解释不够充分,您可能需要查找解释 OpenGL 坐标系和变换的教程。
那是因为你的点数没有显示在屏幕上:
glVertex2f(10, 10);
glVertex2f(20, 20);
在这种情况下,坐标系在 x 和 y 中从 -1.0f 到 1.0f,屏幕中心为 0.0。 通过这样做你应该看到一些东西:
glVertex2f(0.0f, 0.0f);
glVertex2f(1.0f, 1.0f);
但是你的代码很好。