Question

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)

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!

Était-ce utile?

La solution

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

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. 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.

  2. 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.

  3. 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top