初始化后OpenGL窗口冻结

时间:2016-03-03 19:23:57

标签: java opengl lwjgl

我尝试学习LWJGL 3但是在我打开窗口之后,它在打开应用程序后立即冻结。

我尝试重新安装LWJGL并在另一台计算机上运行该应用程序,但它没有任何区别。

我的代码是错误的还是硬件问题?

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.system.MemoryUtil.*;

import org.lwjgl.opengl.GL;

public class Game implements Runnable{

    private Thread thread;
    private long window;

    private boolean running = false;

    public static void main(String[] args){
        new Game().start();
    }

    public void start(){
        running = true;
        thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        float fps = 60;
        float ns = 1000000000 / fps;
        float delta = 0;
        long last = System.nanoTime();

        init();
        while(running){
            delta += (System.nanoTime() - last) / ns;

            while(delta-- >= 1){
                update();
            }

            render();

            last = System.nanoTime();

            if(glfwWindowShouldClose(window) == GL_TRUE) running = false;
        }
    }

    public void init(){
        if(glfwInit() != GL_TRUE){
            System.exit(1);
        }

        glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);

        window = glfwCreateWindow(800, 640, "OpenGL Test", NULL, NULL);

        if(window == NULL){
            System.exit(1);
        }

        glfwMakeContextCurrent(window);
        GL.createCapabilities();

        glfwSetWindowPos(window, 300, 300);

        glfwShowWindow(window);
    }

    public void update(){
        glfwPollEvents();
    }

    public void render(){
        glClearColor(1, 1, 1, 1);
        glClear(GL_COLOR_BUFFER_BIT);
        glfwSwapBuffers(window);
    }

}

3 个答案:

答案 0 :(得分:1)

为了执行OpenGL渲染,您必须具有视口,并且必须从当前视口创建上下文。在初始化方法中,在代码末尾添加以下两行:

GLContext.createFromCurrent();

glViewport(0, 0, width, height);

答案 1 :(得分:1)

您需要让应用程序的主线程(与public static void main(String[] args)关联的线程)在循环中调用glfwPollEvents();,直到窗口关闭,以便程序向操作系统确认它是活着的,没有挂起,正常运行。这是Windows,MacOS和Linux中所有窗口API所必需的,但在许多窗口API(如Swing和AWT)中经常被抽象出来。

如果你对为什么需要这样做的语义感到好奇,你可能希望研究在c ++中的(相对)低级win32 api中创建一个窗口。

答案 2 :(得分:0)

大多数GLFW的功能只能从主线程中调用(这就是为什么它不能与AWT一起运行 - 两者都需要主线程)。虽然有一些函数可以从其他线程使用,但核心函数(如初始化和事件处理)需要主线程。

来自documentation

的引用
  

线程安全

     

大多数GLFW函数只能从主线程调用,但有些可以从任何线程调用。但是,在主线程上成功初始化GLFW之前,不能从任何其他线程调用GLFW函数,包括在初始化之前可能调用的函数。

     

每个GLFW函数的参考文档都说明它是否仅限于主线程。

     

由于一个或多个平台的限制,初始化和终止,事件处理以及窗口,上下文和游标的创建和销毁都仅限于主线程。

     

因为必须在主线程上执行事件处理,所以除了错误回调之外的所有回调都只会在该线程上调用。可以在任何线程上调用错误回调,因为任何GLFW函数都可能生成错误。

     

空事件的发布可以从任何线程完成。窗口用户指针和关闭标志也可以从任何线程访问和修改,但GLFW不同步。可以从任何线程调用以下与窗口相关的函数:

所以你必须从主线程中调用GLFW函数;他们不会使用自定义Thread的{​​{1}}方法。