Renderer class, Textures + VBO
#1 Members - Reputation: 353
Posted 19 March 2012 - 02:42 AM
Just got a few questions about a Render class i'm making for a game engine. The idea is to have an Abstract Renderer so i can derive opengl/directx etc from it. This means that all the opengl specific code is contained in the one class and not scattered through out the code. What i'm curious about is does this OpenGLRender class handle the loading of textures into graphics card memory too correct? So, along with all of its other functions such as draw() , clearbuffers(), swapbuffers() etc it has a loadTexture function which returns an unsigned int to the texture (which would be stored in the resource manager)? Secondly, I was wondering if i could get some tips on how the renderer class works with VBO. For example, at the start of a level all the models are loaded into an array of ModelResource's and i'd assume placed in some sort of octree tree. The renderer gets sent the visible objects from the scene graph and creates VBO for it to draw? Wouldn't this be quite slow creating vbo's every frame? Or does it work like this, after all the models are loaded in, the renderer creates vbo's for all of them, and the scene graph just tells the renderer which ones to draw? What about animated models? Do you just feed it different vertex data? Sorry for so many questions... i've got a lot on my mind at once lol.
Thanks for any suggestions!
#2 Members - Reputation: 628
Posted 20 March 2012 - 03:08 PM
IRenderer->BaseRenderer->Derived (either open gl or dx);
The IRenderer has pointers to ITextureManager, IShaderManager, IMeshManager ( I know the idea of a manager is bad, but in my code they are really just objects that handle the lifetimes of their subobjects).
The base renderer is there just to implement any shared behaviors between OGL and DX. Each derived renderer instances a derived version of the 3 interfaces above(and a few more that aren't relevant to this topic). When a mesh is loaded, all textures are passed to the texturemanager, and the id is stored in mesh::skinids vector. Shaders are handled the same way. The mesh id is stored in the game object that references it, so when it is passed to the renderer, the renderer can use the mesh id to query the meshmanager to find out what textures/shaders need to be bound. It can then(well not yet, but it is high on the priority list) sort all objects
to render in an optimum way.
#4 GDNet+ - Reputation: 1813
Posted 22 March 2012 - 01:13 AM
Yes, this is necessary to some degree. I strongly suggest against putting image loading code in the renderer, it didn't prove maintainable in my case.What i'm curious about is does this OpenGLRender class handle the loading of textures into graphics card memory too correct?
Stop with this unsigned int OpenGL nonsense. Return handles. Pointers. Whatever. Mappings only add complexity IMHO, the benefit is still not clear to me - I've been using GL for like 10 years. At the very best, please do not allow the application to generate the ints by itself.So, ... it has a loadTexture function which returns an unsigned int to the texture (which would be stored in the resource manager)?
It does not work that way. Models themselves are never drawn. Models are instanced. Unless batching is taken into account, ModelResources will be unique and the octree will be in fact a sequence of drawcalls.Secondly, I was wondering if i could get some tips on how the renderer class works with VBO. For example, at the start of a level all the models are loaded into an array of ModelResource's and i'd assume placed in some sort of octree tree.
It's not 199x anymore. Nowadays, you want static resources. Instanced models are just drawn multiple times. They are not - not anymore - batched to a single big VBO, unless necessary.The renderer gets sent the visible objects from the scene graph and creates VBO for it to draw?
Static scenery for example can be easily batched to a certain degree. It's not usually considered "models" but "world model". This is very specific context, everything is guaranteed to be known and typically not moving.
In general, dynamic resources should be used with extra care. Generic instanced models cannot be easily batched in the same way and even in case they do, there's a better way to do it, instancing.
Sure it would. Nobody says you'll have to create it every frame. Remapping it would be sufficient most of the time. I've seen some games creating buffers every once in a while, it's not a performance killer but still far from being something affordable on a per-frame basis.Wouldn't this be quite slow creating vbo's every frame?
Just think at it man. Say you need to draw two teapots. One at position p0 and one at position p1. Do you need to do all this work? No way! You just draw twice, sending the same vertex data and a different transform matrix. That's it!Or does it work like this, after all the models are loaded in, the renderer creates vbo's for all of them, and the scene graph just tells the renderer which ones to draw? What about animated models? Do you just feed it different vertex data?
I admit this becomes pretty more complicated when animation comes into the picture.
#5 Members - Reputation: 4032
Posted 22 March 2012 - 05:36 AM
It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.
#6 Members - Reputation: 353
Posted 22 March 2012 - 12:13 PM
Krohm, may i ask what you mean by "batching"?
Also, we are loading our models from .DAE format (Collada i think?) We have a separate guy doing the actual models and stuff for us... Anyway, is there any surefire way to determine if the current data your are loading in may be the same object you have already loaded just in a different position/orientation? There may be some sort of naming convention in the .DAE format that i'm unaware of (i'm not coding the loader) and i dont expect you to look it up for me, just want to know if we are going about it the correct way.
Thanks!
#7 Members - Reputation: 1789
Posted 22 March 2012 - 01:22 PM
In this case "batching" means to store the vertices of several models into a single VBO....
Krohm, may i ask what you mean by "batching"?
...
It is recommended to use Collada inside the tool chain only, but to use another format for in-game model representation.... Also, we are loading our models from .DAE format (Collada i think?) We have a separate guy doing the actual models and stuff for us...
You have to make a difference between models on disk, models in memory, and models in the scene. You load a model from disk once, resulting in a model as a game resource in memory. If you want to have that model as an entity in your scene, you instance it. This means that there is a light-weight representation with an own placement (i.e. position and orientation) and a link back to the model resource. So you need to have just a single in-memory model regardless of how often you draw it with different positions and/or orientations.... Anyway, is there any surefire way to determine if the current data your are loading in may be the same object you have already loaded just in a different position/orientation? There may be some sort of naming convention in the .DAE format that i'm unaware of (i'm not coding the loader) and i dont expect you to look it up for me, just want to know if we are going about it the correct way.
#8 Members - Reputation: 628
Posted 22 March 2012 - 02:03 PM
You have to make a difference between models on disk, models in memory, and models in the scene. You load a model from disk once, resulting in a model as a game resource in memory. If you want to have that model as an entity in your scene, you instance it. This means that there is a light-weight representation with an own placement (i.e. position and orientation) and a link back to the model resource. So you need to have just a single in-memory model regardless of how often you draw it with different positions and/or orientations.
This is what the IMeshManger does in my explaination. It is used to derive an OGL or DX MeshManager, which is instanciated by the derived renderer(ogl or dx) When a game loads a model, the MeshManager searches in it's collection for a match, and returns the ID of that mesh. If it is not found, it can load a model from disk(with a meshloader that matches the file type), build the vertex and index buffers needed, and again return an ID representing that mesh. When the game renders an object, it just passes the ID of a mesh, as well as position and orientation to the renderer.






