Java LWJGL 3韩元';不要划清界限

Java LWJGL 3韩元';不要划清界限,java,opengl,lwjgl,Java,Opengl,Lwjgl,我想和LWJGL 3划清界限。它会编译,所有本地人都设置正确。我在Ubuntu上运行。我真的不明白问题出在哪里;窗口初始化,背景为正确的清晰颜色,但线条不会绘制。我几乎完全是从他们的新网站上找到的唯一示例中复制了代码。我不知道我做错了什么 import static org.lwjgl.glfw.GLFW.*; import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.system.MemoryUtil.NULL; impor

我想和LWJGL 3划清界限。它会编译,所有本地人都设置正确。我在Ubuntu上运行。我真的不明白问题出在哪里;窗口初始化,背景为正确的清晰颜色,但线条不会绘制。我几乎完全是从他们的新网站上找到的唯一示例中复制了代码。我不知道我做错了什么

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();
    }
}

编辑:我现在相当肯定这是我使用
glu行时的一个错误

这里有很多问题

抽签 这里有一个常见但有时很难发现的错误:

glBegin(GL_LINE);
绘制线的枚举是
GL_线
(注意后面的
S
)<另一方面,code>GL_LINE是
glPolygonMode()
的可能参数之一。所以这个电话应该是:

glBegin(GL_LINES);
Draw循环中调用的顺序 渲染循环中的调用顺序似乎错误:

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方向进行平移,作为modelview矩阵的一部分,以获取查看体积内的坐标。否则,整个几何体将被剪裁掉

例如,设置modelview矩阵时,可以添加一个
glTranslatef()
调用,该调用将几何图形放置在近平面和远平面之间:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -50.0f);

如果这个解释不够充分,您可能需要寻找一个解释OpenGL坐标系和转换的教程。

这里有很多问题

抽签 这里有一个常见但有时很难发现的错误:

glBegin(GL_LINE);
绘制线的枚举是
GL_线
(注意后面的
S
)<另一方面,code>GL_LINE是
glPolygonMode()
的可能参数之一。所以这个电话应该是:

glBegin(GL_LINES);
Draw循环中调用的顺序 渲染循环中的调用顺序似乎错误:

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方向进行平移,作为modelview矩阵的一部分,以获取查看体积内的坐标。否则,整个几何体将被剪裁掉

例如,设置modelview矩阵时,可以添加一个
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);

但是您的代码很好。

这是因为您的点不在屏幕上:

glVertex2f(10, 10);
glVertex2f(20, 20);
在这种情况下,坐标系在x和y的-1.0f到1.0f之间,屏幕的中心为0.0。 通过这样做,您应该看到:

glVertex2f(0.0f, 0.0f);
glVertex2f(1.0f, 1.0f);

但是你的代码是好的。

你的线是在近剪裁平面的前面画的(对于
glVertex2
调用,Z值是0;你的近剪裁平面是Z=0.3的平面)。如果将两个顶点的Z值都设置为1,是否有效?@immibis它不起作用。我再次不确定出了什么问题,您的线是在近剪裁平面前面绘制的(对于
glVertex2
调用,Z值为0;您的近剪裁平面是Z=0.3的平面)。如果将两个顶点的Z值都设置为1,是否有效?@immibis它不起作用。我再一次不确定到底出了什么问题,我重置了调用,将zNear设置为0,并修复了我的
glupperpspective
的纵横比中的一个错误,但我仍然没有看到任何东西。不过,我认为这是我的
GL\u行
实现的一个问题哦,是的,的确如此。我完全错过了。请参阅更新答案的开头。另外,在您之前的评论中:0对于近平面不是一个好值。我也在这一部分添加了更多细节。我重置了调用,将zNear设置为0,并修复了我的
glupperpspective
中的一个打字错误