如何在带有opengl支持的Java中创建新线程? [英] How do you make a new thread in java with opengl support?

查看:116
本文介绍了如何在带有opengl支持的Java中创建新线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用lwjgl制作一个新的3D Java游戏,一切进展顺利,但是我试图在不同的线程中创建一些3D对象,例如:

I'm making a new 3D java game with lwjgl, and everything's going along great, but I'm trying to create some 3D objects in a different thread, like so:

new Thread(new Runnable() {
    @Override
    public void run() {
        for(int x = 1; x < 5; x++) {
            for(int z = 1; z < 5; z++) {
                Object3D curObject = game.createGrassBlock(game.maps.get(0));
                curObject.setPosition(x, curObject.getSize().getY() / 2, z);
                curObject.defaultPosition = curObject.getPosition();
                Thread.sleep(1);
            }
        }
    }
}).start();

但是,每当我运行该代码时,都会出现以下错误:

However, whenever I run that code, I get the following error:

Exception in thread "Thread-4" java.lang.RuntimeException: No OpenGL context found in the current thread.
    at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java:124)
    at org.lwjgl.opengl.GL15.glGenBuffers(GL15.java:114)
    at com.gmail.br45entei.base.engine.rendering.Mesh.initMeshData(Mesh.java:43)
    at com.gmail.br45entei.base.engine.rendering.Mesh.<init>(Mesh.java:32)
    at com.gmail.br45entei.base.engine.rendering.Object3D.updateMeshes(Object3D.java:891)
    at com.gmail.br45entei.base.engine.rendering.Object3D.setShape(Object3D.java:942)
    at com.gmail.br45entei.base.engine.rendering.Object3D.<init>(Object3D.java:663)
    at com.gmail.br45entei.base.game.Game.createGrassBlock(Game.java:293)
    at com.gmail.br45entei.base.game.Game.access$1(Game.java:292)
    at com.gmail.br45entei.base.game.Game$1.run(Game.java:220)
    at java.lang.Thread.run(Unknown Source)

由于我确定代码可以在Game.java中正常运行(但是运行缓慢),而无需在新线程中调用它,所以我很困惑,因为我不知道为什么新线程不会具有相同的opengl上下文作为主线...有什么想法吗?感谢您的阅读!

As I am sure that the code runs fine(however laggy) in my Game.java without calling it within a new thread, I am stumped, for I don't know why a new thread wouldn't have the same opengl context as the main thread... Any ideas? Thanks for reading!

推荐答案

我不知道为什么新线程不具有与主线程相同的opengl上下文...

I don't know why a new thread wouldn't have the same opengl context as the main thread...

因为OpenGL不能那样工作. OpenGL上下文绑定到特定线程.每个上下文在任何时候都只能(最多)绑定到一个线程.而且ech线程在任何时候都只能具有一个GL上下文.

Because OpenGL does not work that way. An OpenGL context is bound to a specific thread. Each context can only be bound to (at most) one thread at any time. And ech thread can only have one GL context at any time.

如果要使用更多线程,则有几种选择:

If you want to use more threads, you have several options:

  1. 仅使用一个GL上下文.但是您需要同步对它的访问,因此当前拥有它的线程必须取消绑定它,而新线程随后必须将其绑定.这不是解决您问题的合适方法.

  1. Use just one GL context. But you need to synchronize the access to it, so the thread currently having it must unbind it and the new one has to bind it thereafter. This isn't a suitable solution for your problem.

使用不同的上下文.每个线程可以一直绑定自己的GL上下文.默认情况下,上下文将彼此独立.但是,这可以更改:您可以创建共享上下文,实际上将共享许多对象,因此线程A可以创建和操作GL对象,例如VBO,纹理,...和线程B可以直接使用它们,就好像它自己创建/操纵它们一样.请看这篇 OpenGL和多线程文章.您仍然必须使用某种同步,以便线程B知道线程A完成对象操作的时间,依此类推...注意,您不仅必须同步CPU上的线程,还需要与CPU同步. GL,还要确保在其他线程使用更新后的对象之前,GPU实际上已经完成了挂起的操作.

Use different contexts. Each thread can have its own GL context bound all the time. The contexts will be indepented of each other by default. However, this can be changed: You can create shared context, which will actually share a lot of the objects, so thread A can create and manipulate GL objects like VBOs, textures, ..., and thread B can directly use them as if it did create/manipulate them on its own. Have a look into this OpenGL and multithreading article. You still have to use some kind of synchronization so that thread B knows when thread A finished manipulationg an object and so on... Note that you do not only have to synchronize your threads on the CPU, but you also need to synchronize with the GL, too make sure that the GPU actually has finished the pending operations before the other thread should use the updated object.

可通过使用映射的缓冲区对象来实现穷人的多线程GL对象更新.只有一个GL上下文和一个处理它的线程.但是此线程可以通过 glMapBufferRange .内存映射是针对每个进程而不是每个线程,因此在进行映射时,进程中的任何线程都可以对其进行操作.传统上,GL不允许在GL中使用映射的对象,因此,在映射对象时,GL线程实际上不能将其用于绘图.在OpenGL 4.4中,引入了 ARB_buffer_storage ,甚至允许使用对象在它们被映射时-但是同步完全取决于用户.

Poor man's multithreaded GL object update can be achieved by using mapped buffer objects. There is only one GL context and one thread dealing with it. But this thread can map buffer objects to client address space via glMapBuffer/glMapBufferRange. Memory mappings are per process and not per thread, so while it is mapped, any thread of the process can manipulate it. Traditionally, GL did not allow mapped object to be used in the GL, so while the object is mapped, the GL thread can not really use it for drawing. With OpenGL 4.4, there was introduced ARB_buffer_storage, which even allows to use the objects while they are mapped - but synchronisation is completely up to the user, then.

这篇关于如何在带有opengl支持的Java中创建新线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆