SDL Textures and CPU\Memory issues - c++

I developed a game with SDL2.00 and c++. I seemed to be having memory and CPU issues. CPU usage goes up to 40% and memory usage goes up by 5mg a second.
So I think the reason is the way Im handling Textures\Sprites.
My question is should I create a different/new sprite/texture for every instance ?
For example, I have a class called Enemy which contains all the variable and methods related to enemy monsters such as HP, damage, location , image(Texture) etc. This class contains its own texture to be rendered onto the renderer.
Is this the right way? Or should I create a Sprite/Texture for all the images before hand and render them as needed?
and I'm wondering if this will render two different images onto the renderer:
RenderCopy(renderer, image);
image->SetPosition(X,Y);
RenderCopy(renderer,image);
or is it going to move the sprite to the new position?
I think my issues are caused my overloading the renderer and/or having too many textures being loaded.
Let me know what you think .

OpenGL is not a scene graph. It's a drawing API. So everytime you're allocating a new texture you're creating a new data object that consumes memory. You should reuse and share resources where possible.

My question is should I create a different/new sprite/texture for
every instance ?
No, not unless every instance of the sprite uses different textures, otherwise you should reuse them, ie only load them once and store a pointer to the texture the sprite uses.
and I'm wondering if this will render two different images onto the
renderer:
RenderCopy(renderer, image);
image->SetPosition(X,Y);
RenderCopy(renderer,image);
or is it going to move the sprite to the new position?
This will copy the image twice. First at the old position and then at the new. What you will get is a trailing image. You should probably either clear the previous position or render the background at that position (or whatever should be there).

Related

Vertex buffer not clearing properly

Context
I'm a beginner in 3D graphics and I'm starting out with Vulkan, which I already know it's not recommended save it please, currently working on a university project to develop the base of a 3D computer graphics engine based on the Vulkan API.
The problem
Example of running the app to render the classic 2D triangle
Drawing a 3D mesh after having drawn the triangle
So as you can see in the images above I want to be able to:
Run the engine.
Choose an object to be drawn.
Close the window.
Choose another object to be drawn.
Open the same window back up with only the last object chosen visible.
And the way I have been doing this is by essentially cleaning up the whole swap chain and recreating it from scratch once the window is closed and a new object has been chosen. Now I'm aware this probably sounds like terrorism for any computer graphics engineer but the reason I'm doing this is because I don't know a better way, I have just finished the vulkan tutorial.
Solutions tried
I have checked that I do a vkDestroyBuffer and vkFreeMemory on the current vertex buffer before recreating it again once I choose a different object.
I have disabled depth testing entirely in case it had something to do with it, it doesn't.
Note: The code is extensive and I really don't have a clue of which part of it could be relevant to the problem, so I opted for not cluttering the question, if there is an specific part you think it might help you find the solution please request it.
Thank you for taking the time to read my question.
A comment by user369070 ended up drawing my attention to the function I use to read OBJ files which made me realize that this function wasn't cleaning a data structure I use to store the vertices of the object chosen to be drawn before passing them to the vertex buffer.
I just had to add vertices = {}; at the top of the function to solve it.

How to render multiple different items in an efficient way with OpenGL

I am making a simple STG engine with OpenGL (To be exact, with LWJGL3).In this game, there can be several different types of items(called bullet) in one frame, and each type can have 10-20 instances.I hope to find an efficient way to render it.
I have read some books about modern OpenGL and find a method called "Instanced Rendering", but it seems only to work with same instances.Should I use for-loop to draw all items directly for my case?
Another question is about memory.Should I create an VBO for each frame, since the number of items is always changing?
Not the easiest question to answer but I'll try my best anyways.
An important property of OpenGL is that the OpenGL context is always bound to a single thread. So every OpenGL-method has to be called within that thread. A common way of dealing with this is using Queuing.
Example:
We are using Model-View-Controller architecture.
We have 3 threads; One to read input, one to handle received messages and one to render the scene.
Here OpenGL context is bound to rendering thread.
The first thread receives a message "Add model to position x". First thread has no time to handle the message, because there might be another message coming right after and we don't want to delay it. So we just give this message for the second thread to handle by adding it to second thread's queue.
Second thread reads the message and performs the required tasks as far as it can before OpenGL context is required. Like reads the Wavefront (.obj)-file from the memory and creates arrays from the received data.
Our second thread then queues this data to our OpenGL thread to handle. OpenGL thread generates VBOs and VAO and stores the data in there.
Back to your question
OpenGL generated Objects stay in the context memory until they are manually deleted or the context is destroyed. So it works kind of like C, where you have to manually allocate memory and free it after it's no more used. So you should not create new Objects for each frame, but reuse the data that stays unchanged. Also when you have multiple objects that use the same model or texture, you should just load that model once and apply all object specific differences on shaders.
Example:
You have an environment with 10 rocks that all share the same rock model.
You load the data, store it in VBOs and attach those VBOs into a VAO. So now you have a VAO defining a rock.
You generate 10 rock entities that all have position, rotation and scale. When rendering, you first bind the shader, then bind the model and texture, then loop through the stone entities and for each stone entity you bind that entity's position, rotation and scale (usually stored in a transformationMatrix) and render.
bind shader
load values to shader's uniform variables that don't change between entities.
bind model and texture (as those stay the same for each rock)
for(each rock in rocks){
load values to shader's uniform variables that do change between each rock, like the transformation.
render
}
unbind shader
Note: You don't need to unbind/bind shader each frame if you only use one shader. Same goes for VAO's and every other OpenGL object as well. So the binding will also stay over each rendering cycle.
Hope this will help you when getting started. Altho I would recommend some tutorial that might have a bit more context to it.
I have read some books about modern OpenGL and find a method called
"Instanced Rendering", but it seems only to work with same
instances.Should I use for-loop to draw all items directly for my
case?
Another question is about memory.Should I create an VBO for each
frame, since the number of items is always changing?
These both depend on the amount of bullets you plan on having. If you think you will have less than a thousand bullets, you can almost certainly push all of them to a VBO each frame and upload and your end users will not notice. If you plan on some obscene amount, then don't do this.
I would say that you should write everything each frame because it's the simplest to do right now, and if you start noticing performance issues then you need to look into instancing or some other method. When you get to "later" you should be more comfortable with OpenGL and find out ways to optimize it that won't be over your head (not saying it is over your head right now, but more experience can only help make it less complex later on).
Culling bullets not on the screen either should be on your radar.
If you plan on having a ridiculous amount of bullets on screen, then you should say so and we can talk about more advanced methods, however my guess is that if you ever reach that limit on today's hardware then you have a large ambitious game with a zoomed out camera and a significant amount of entities on screen, or you are zoomed up and likely have a mess on your screen anyways.
20 objects is nothing. Your program will be plenty fast no matter how you draw them.
When you have 10000 objects, then you'll want to ask for an efficient way.
Until then, draw them whichever way is most convenient. This probably means a separate draw call per object.

Cocos2dx - Clearing specific textures from the cache

I am getting crashes on iPhone 4s due to "memory pressure." My game is set up like this:
Main scene sprite sheet that always stays in memory.
Individual game scene levels load from individual textures (not sprite sheets).
When a level is done and we return to the main scene, I would like those cached game scene textures to get dumped. What ends up happening is that when you play through 3-4 levels, it crashes as it runs out of memory as it never releases this memory after a level. I don't want the level textures to be cached past the lifespan of the game scene. When returning to the main scene, it needs to release this memory.
I have tried removing all of the game scene children which does nothing to memory. I have tried looking for a specific way to clear just these textures I have loaded in this game scene from the cache.
Any suggestions?
Are you using cocos2d v2? You probably have memory leaks since unused textures are removed when necessary. Try profiling your app to see if you have leaks and where they are at.
You also can call these methods yourself at the appropriate time, although I doubt you'd have to:
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
But again what you describe sounds more like memory leaks. When your application receives a memory warning the cached data is purged. During this purge the remove unused textures method is called on the texture cache, among other things. If you have 3/4 levels of data still lurking around long after you've exited those scenes, that sounds like a memory leak.
I'm assuming this only happens after visiting multiple scenes and the problem just isn't that your 4th scene is simply trying to load more data than the device can handle.
You can remove specific textures calling:
In cocos2D-x v3.x :
Director::getInstance()->getTextureCache()->removeTextureForKey(ImageKeyName)
In cocos2D-x v2.x :
CCTextureCache::sharedTextureCache()->removeTextureForKey(ImageKeyName);
Where ImageKeyName is just the path of the image (the same you used to load the texture)

Using CCSpriteFrameCache without CCSpriteBatchNode

I want to know if there is any benefiting caching a sprite sheet and accessing the sprite by frame without using the CCSpriteBatchNode?
In some parts of my game the sprite batch node is useful because there is a lot on the screen, however on another part its not, because there are just a few things, and there are requirements for layers so CCSpriteBatchNode wouldn't be useful. However, for the sake of consistency I would like to use Sprite Sheets for all my sprites, and so was beginning to wonder if I would still receive any benefit from it? (Or worse that it could some how be slower...)
There is defiantly a benefit to putting all your sprites into a texture atlas or sprite sheet as you called it. Textures are stored in memory in power of 2 dimensions. So if you have a sprite that is 129px by 132px it is stored in memory as 256px by 256px which is the nearest power of 2 size. If you have many sprites that is quite a lot of extra memory used up.
By using a texture atlas you only have one texture in memory and then it pulls the pieces out of it that it needs for your sprites. These sprites can be whatever size you want without having to worry about power of 2 sizes.
You can read more details about it on this tutorial
http://www.raywenderlich.com/2361/how-to-create-and-optimize-sprite-sheets-in-cocos2d-with-texture-packer-and-pixel-formats

Is it ok to use a Random texture ID?

Instead of using glGenTextures() to get an unused texture ID. Can I randomly choose a number, say, 99999 and use it?
I will, of course, query:
glIsTexture( m_texture )
and make sure it's false before proceeding.
Here's some background:
I am developing an image slideshow app for the mac. Previewing the slideshow is flawless. To save the slideshow, I am rendering to an FBO. I create an AGL context, instantiate a texture with glGenTextures() and render to a frame buffer. All's well except for a minor issue.
After I've saved the slideshow and return to the main window, all my image thumbnails are grey, i.e. the textures have been cleared.
I have investigated it and found out that the image thumbnails and my FBO texture somehow have the same texture ID. When I delete my FBO texture at the end of the slideshow saving operation, the thumbnail textures are also lost. This is weird because I have an AGL context during saving, and the main UI has another AGL context, presumably created in the background by Core Image and which I have no control on.
So my options, as I see it now, is to:
Not delete the FBO texture.
Randomly choose a high texture ID in the hopes that the main UI will not be using it.
Actually I read that you do not necessarily need to delete your texture if you are deleting the AGL opengl context. Because deleting your openGL context automatically deletes all associated textures. Is this true? If yes, option 1 makes more sense.
I do realize that there are funny things happening here that I can't really explain. For example, after I've saved my image slideshow to an .mov file, I delete the context, which was created in the same class. By right, it should not affect textures created in another context. But it does, and I seriously can't explain that.
Allow me to answer your basic question first: yes, it is legal in OpenGL 2.1 to simply pick a texture name arbitrarily and use it as a texture. Note that it is not legal in 3.2 core. The fact that the OpenGL ARB removed this ability should help illustrate whether it is a good idea or not.
Now, you seem to have run into an odd bug. glGenTextures should never return a texture name that is already in use. After all that is what it is for. You appear to somehow be getting textures that are already in use. I don't know how that happens.
An OpenGL context, when destroyed, will delete all resources specific to that context. If you have created a second context that shares resources with the first, deleting the second context will not delete the shared resources (textures, buffers, etc). It will delete un-shared resources (VAOs, etc), but everything else will remain.
I would suggest not creating and deleting the FBO texture constantly. Just create it on application startup. Worst-case, you'll have to reallocate storage for the object as needed (via glTexImage2D), if you need a different size or something.
To anybody who has this problem, make sure your context is fully initialized; until it is glGenTextures will always return 0. I didn't realize what was happening at first because it seems 0 is still a valid texture ID.