Hi everybody,
I’m quite new to jogl and try to implement my first project.
I came across the problem, that I would like to start the program and while running loading further textures. I know that OpenGL originally isn’t intended for multi threading, but there has to be a solution. I believe many games load additional textures when entering other world regions.
I use a very simple texture loader with a static method:
public static synchronized Texture getTexture(String fileName) {
if (textures.containsKey(fileName)) {
return textures.get(fileName);
} else {
Texture text = null;
try {
text = TextureIO.newTexture(new File(fileName), true);
text.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
text.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_NEAREST);
text.setTexParameteri(GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
text.setTexParameteri(GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
text.disable();
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println("Error loading texture " + fileName);
}
textures.put(fileName, text);
return text;
}
}
now i tried to load the textures somewhere like this:
new Thread(new Runnable() {
public void run() {
for (String pic : pics) {
add(TextureLoader.getTexture("textures/" + pic));
}
loaded = true;
}
}).start();
which fails because “No OpenGL context current on this thread”:
TextureIO.newTexture() -> newTexture() -> Texture() -> GLU.getCurrentGL() which calls GLContext.getCurrent()
Then I thought about setting the current context of the new thread to the one from the old one. Unfortunately setCurrent of GLContext is not public. With the following hack I set it to public:
final GLContext cont = GLContext.getCurrent();
new Thread(new Runnable() {
public void run() {
try {
Class glcontClass = Class.forName("javax.media.opengl.GLContext");
for(Method m:glcontClass.getDeclaredMethods()){
if(m.getName().equals("setCurrent")){
m.setAccessible(true);
m.invoke(null, cont);
}
}
} catch (Exception e) {
e.printStackTrace();
}
for (String pic : pics) {
add(TextureLoader.getTexture("textures/" + pic));
}
loaded = true;
}
}).start();
I know that this is quite bad style but at first it seemed to be working. Then I got the following Error “May not call this between glBegin and glEnd”. I think this comes from a gl.glGenTextures() or some other function which cannot be called while drawing.
Now I consider implementing some kind of semaphore mechanism which prevents drawing and texture loading at the same time. But this means there would be some frame rate drops unless the texture can be loaded between two frames.
As you can see this doesn’t seem to be a very satisfying approach…
Any Ideas? Or is there any example of how this is done in “reality”?
Thanks for your help/suggestions.
p90