After creating textures in Android OpenGL ES, do I have to explicitly delete these textures later using glDeleteTextures()? If so, how would I set up a callback to do this?
Thanks in advance
If you are no longer using a texture, then you should call glDeleteTextures() so that the underlying hardware resources can be freed up.
But as EboMike said, you have to be careful about using a texture that was created from a previous context instance; to expand on that answer, I like to create a texture-wrangling class which wraps the texture's ID and which calls glDeleteTextures() from its finalize() method, but then also have an app-static int named "contextId" which gets incremented every time the GL context is created (i.e. in onSurfaceCreated); the texture wrangler should track the value of contextId when it's instantiated, and if the value changes on it, that means it should reload its textures (keeping in mind that the old texture IDs were already discarded along with the old context).
No, they are automatically deleted once you move away from your app. The greater pitfall actually is to disregard the texture IDs if your app becomes active again - keep that in mind when your onSurfaceChanged is called again.
Related
Talking in context of a game based on openGL renderer :
Lets assume there are two threads :
that updates the gameLogic and physics etc. for the in game objects
that makes openGL draw calls for each game object based on data in the game objects (that thread 1 keeps updating)
Unless you have two copies of each game object in the current state of the game you'll have to pause Thread 1 while Thread 2 makes the draw calls otherwise the game objects will get updated in the middle of a draw call for that object ! which is undesirable!
but stopping thread 1 to safely make draw calls from thread 2 kills the whole purpose of multithreading/cocurrency
Is there a better approach for this other than using hundreds or thousands or sync objects/fences so that the multicore architecture can be exploited for performance?
I know I can still use multiThreading for loading texture and compiling shaders for the objects which are yet to be the part of the current game state but how do I do it for the active/visible objects without causing conflict with draw and update?
The usual approach is that the simulation thread after completing a game step commits the state into an intermediary buffer and then signals the renderer thread. Since OpenGL executes asynchronously the render thread should complete rather quickly, thereby releasing the intermediary buffer for the next state.
You shouldn't render directly from the game state anyway, since what the renderer needs to do its works and what the simulation produces not always are the same things. So some mapping may be necessary anyway.
This is quite a general question you're asking. If you ask 10 different people, you'll probably get 10 different answers. In the past I implemented something similar, and here's what I did (after a long series of optimisation cycles).
Your model-update loop which runs on a background thread should look something like this:
while(true)
{
updateAllModels()
}
As you said, this will cause an issue when the GL thread kicks in, since it may very well render a view based on a model which is half way through being rendered, which can cause UI glitches at the best case.
The straight-forward way for dealing with this would be synchronising the update:
while (true)
{
synchronized(...)
{
updateAllModels();
}
}
Where the object you synchronize with here is the same object you'll use to synchronize the drawing method.
Now we have an improved method which won't cause glitches in the UI, but the overall rendering will probably take a very severe performance hit, since all rendering needs to wait until all model updates are finished, or vise versa - the models update will need to wait until all drawing is finished.
Now, lets think for a moment - what do we really need to be synchronizing?
In my app (a space game), when updating the models, I needed to calculate vectors, check for collisions and update all the object's positions, rotations, scale, etc.
Out of all these things, the only things the view cares about is the position, rotation, scale and a few other small considerations which the UI needs to know in order to correctly render the game world. The rendering process doesn't care about a game object's vector, the AI code, collision tests, etc. Considering this, I altered my update code to look something like this:
while (true)
{
synchronized(...)
{
updateVisibleChanges(); // sets all visible changes - positions, rotations, etc
}
updateInvisibleChanges(); // alters vectors, AI calculations, collision tests, etc
}
Same as before, we're synchronising the update and the draw methods, but this time, the critical section is much smaller than before. Essentially, the only things which should be set in the updateVisibleChanges method are things which pertain to the position, rotation, scale, etc of the objects which should be rendered. All other calculations (which are usually the most exhaustive ones) are performed afterwards, and do not stop the rendering from occurring.
An added bonus from this method - when you're performing your invisible changes, you can be sure that all objects are in the position they need to be (which is very useful for accurate collision tests). For example, in the method before the last one, object A moves, then object A tests a collision against object B which hasn't moved yet. It is possible that had object B moved before object A tested a collision, there would be a different result.
Of course, the last example I showed isn't perfect - you will still need to hang the rendering method and/or the updateVisible method to avoid clashes, but I fear that this will always be a problem, and the key is minimizing the amount of work you're doing in either thread sensitive method.
Hope this helps :)
I'm working in an Android game using libGDX framework while a learn from their wiki and Learning Libgdx Game Development book. The author of the book defines an Assets class to load game assets using an AssetManager. Every time the game is resumed the assets need to be reloaded so he use a call to Assets.intance.init(new AssetManager()) what reload the assets and create new objects to store textures references.
When I do this in my game, after resume, all I have are black boxes where I had nice textures so I suppose that the problem here is that I'm using the old references. I put here part of the code from the book:
AssetManager#init
public void init(AssetManager assetManager) {
/* Dispose previous asset manager */
if (this.assetManager != null) {
this.assetManager.dispose();
}
this.assetManager = assetManager;
assetManager.setErrorListener(this);
assetManager.load(Constants.TEXTURE_ATLAS, TextureAtlas.class);
/* Start loading assets and wait until finished */
assetManager.finishLoading();
Array<String> assetNames = assetManager.getAssetNames();
Gdx.app.debug(TAG, "Assets loaded: " + assetNames.size);
for (String assetName : assetNames) {
Gdx.app.debug(TAG, "Asset: " + assetName);
}
TextureAtlas atlas = assetManager.get(Constants.TEXTURE_ATLAS);
/* Create game resource objects. Here I get what I need from the atlas */
player = new AssetPlayer(atlas);
enemy = new AssetEnemy(atlas);
}
When I create my game objets I use Assets.instance.player and Assets.instance.enemy to store a reference to textures as the author of the book does so this could be the problem. The thing is that aftere re-read the book, I don't see how he solve this problem.
I'm pretty sure that I can solve the problem changing references in my game objects but all is becoming so messy. My real question is, how should I manage game assets in my game? I've been searching a lot for game examples but most of them don't use an AssetManager but instead static variables to textures.
Should I keep references of textures in game objects? It is really necessary to reload assets on resume? How could I reload textures in my game objects when all the objects are inside a worldController that don't know when a game is being resumed?
You're doing it correctly, as far as I can tell, at this level. You really do need to reload the textures, as your OpenGL context was lost, and all "pointers" into OpenGL-internal state are stale.
As you point out, because your AssetManager.player property points to a new object, anything that cached an old pointer is stale after a restart, and that is probably the source of your problems. (Though its hard to say for certain.)
If you look at the Libgdx SuperJump demo, they also cache all their asset pointers in static fields, but notice that the render calls effectively look up the texture every call. See WorldRenderer.renderBob(). One alternative would be to do a pass over your objects after (re)-loading assets to have them "refresh" their pointers the assets they use.
Have you tried not to call Assets.intance.init(new AssetManager()) on resume method (and also not to call Assets.intance.dispose() on pause method)?
Please read this link:
https://github.com/libgdx/libgdx/wiki/Managing-your-assets
At the end (Resuming with a Loading Screen) it says:
On Android your app can be paused and resumed. Managed OpenGL resources like Textures
need to be reloaded in that case, which can take a bit of time. If you want to
display a loading screen on resume, you can do the following after you created your
AssetManager.
Texture.setAssetManager(manager);
In your ApplicationListener.resume() method you can then switch to your loading screen and call AssetManager.update() again until everything is back to normal.
If you don't set the AssetManager as shown in the last snippet, the usual managed texture mechanism will kick in, so you don't have to worry about anything.
So, I believe that the author's approach is no longer necessary.
You only need to call Assets.intance.dispose() on dispose method in your "Game" class (I mean, the class that implements ApplicationListener).
Hi Android Developers,
What is the best way to interrupt a current rendering phase of GLSurfaceView and start a new one when mode is equal to "Render_when_dirty"? I artificially stop rendering in "onDraw" method by checking a flag and returning from actual rendering method which is called in "onDraw" method; then, in main thread's context i call "requestRender()" to refresh the scene. However, due to a reason that i am not aware of, some of the intermediary old frames are displayed for a very very short period of time(on the other hand, they endure for so long period of time that users can realize the transition); before actual scene is rendered by opengl es 2.x engine. It doesn't affect anything at all; but troublesome to be fixed. What do you suggest?
P.S. Throwing InterruptedException within onDraw method is useless due to the destruction of actual rendering thread of GLSurfaveView.
Kind Regards.
When you say some of the old frames are drawn - do you mean part of the frame that is drawn is old or multiple calls of onDraw() still lead to some of the old information being shown on the display.
There are a few things I can see happening here. If you have a onDraw() like this:
onDrawFrame(){
... stuff ...
if (stateVariableSet)
return;
... stuff ...
my understanding is that when the function is done being run, that the back/front buffer get swapped and drawn. One thing that could be happening here is that you see a few calls of onDrawFrame() being rendered while you try to update the state/State variable.
On the other hand, if you have something like this:
onDrawFrame(){
... stuff..
semaphore.acquire(); // lock the thread waiting for the state to update
... stuff ...
then the things that have been drawn before the lock will be stale (for that frame only though - at least that's what I'd anticipate).
Also are you running on a multi-core system?
I am developing a game in Android using AndEngine GLES-2. I am facing a problem while resetting a scene after player has completed a level. When I reset the scene, all the sprites lose their positions and tend to appear in each other's positions i.e. they swap their positions.
I have tried all the things like setting all the sprites etc. to null and calling methods like clearUpdateHandlers() and clearEventModifiers() etc. but no success yet.
I found out after a lot of googling that engineOptions.getRenderOptions().disableExtensionVertexBufferObjects(); method can fix this problem. So I am trying to invoke it but compiler gives error saying that this method in not defined for RenderOptions class.
I checked the RenderOptions class in org.andengine.engine.options package and the method really does not exist in that class. Am I missing any plug-in or is there any other problem? Please help, I am stuck.
you need to manually restart the scene, for example:
To restart a Scene you can Finish the activity and Start again but different level with SharedPreferences, or Tag's in intents, or you can set position of each Sprite and cler the Scene with:
//detachChild this Sprites that you do not use
Scene.detachChild(SpriteX);
//clear the space of memory of each sprite that you do not use
SpriteX.dispose();
//unload the bitmaps that you do not use
BitMapsX.unload();
this method have a seconds to run, but you can use a elegant "hud" in you game, and while charging set in the hud a logo or animation with "loading", best regards
I'm trying to load all the game data at the same time, in my game scene's constructor. But it fails, because texture loading works only in an opengl context, like if load method called from draw frame or surfacechanged. But i think it's ugly to load textures when the drawframe first called or something similar. So is it possible somehow to separate my loading part from opengl functions?
I have exactly the same problem.
My solution is using the proxy textures. It means that when you're creating textures using some data from memory or file you're creating the dummy texture that holds the copy of that memory data or the file path (you can preload the data into memory for faster loading).
After that the next time my renderer calls bind() (which is something like glBindTexture) I check whether there is data to load and if it exists I just create the new texture and load the data.
This approach fits best to me, because in my case textures could be created from any thread and any time.
But if you want to preload all textures you can just do that in onSurfaceCreated or onSurfaceChanged
The same applies to buffers.
Another approach is using the native activity (check the NDK example). In this case you can handle context manually but it requires API level 9.
But i think it's ugly to load textures when the drawframe first called or something similar.
Actually deferred texture loading is the most elegant methods. It's one of the key ingredients for games that allow for traveling the world without interrupting loading screens. Just don't try to load the whole world at once, but load things, as soon they are about to become visible. Use Pixel Buffer Objects to do things asynchronously.