Jump to content
  • Advertisement
Sign in to follow this  
rocklobster

Renderer class, Textures + VBO

This topic is 2399 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Guys,

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!

Share this post


Link to post
Share on other sites
Advertisement
I can only speak of what I've done, but here it is

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.

Share this post


Link to post
Share on other sites
What i'm curious about is does this OpenGLRender class handle the loading of textures into graphics card memory too correct?
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.
So, ... it has a loadTexture function which returns an unsigned int to the texture (which would be stored in the resource manager)?
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.

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 does not work that way. Models themselves are never drawn. Models are instanced. Unless batching is taken into account, [font=courier new,courier,monospace]ModelResource[/font]s will be unique and the octree will be in fact a sequence of drawcalls.

The renderer gets sent the visible objects from the scene graph and creates VBO for it to draw?
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.
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.
Wouldn't this be quite slow creating vbo's every frame?
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.
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?
Just think at it man. Say you need to draw two teapots. One at position p[sub]0[/sub] and one at position p[sub]1[/sub]. 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!
I admit this becomes pretty more complicated when animation comes into the picture.

Share this post


Link to post
Share on other sites
Animation is easy. If you're doing keyframes you just use two vertex streams each with a different offset into the same VBO - one for previous frame, one for current frame - and a blend factor as a shader uniform. If you're doing skeletal you upload your bone matrixes into constant buffers/UBOs and animate from those. Vertex data remains completely static and nothing needs to be rebuilt on a per-frame basis. Doing this kind of stuff on the CPU is very 20th century - aside from the overhead of rebuilding vertex buffer data every frame (or multiple times per frame if you're reusing the same model for more than one object in your scene) it won't run as fast as a GPU solution anyway.

Share this post


Link to post
Share on other sites
Thanks for the input guys, my first game engine, its a lot to take in and get my head around. I've done some more research into VBO's since my post and it is much more clear now. I've also encapsulated my OpenGLRenderer in a graphics manager class which can handle the texture loading and VBO loading etc.

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!

Share this post


Link to post
Share on other sites

...
Krohm, may i ask what you mean by "batching"?
...

In this case "batching" means to store the vertices of several models into a single VBO.


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

It is recommended to use Collada inside the tool chain only, but to use another format for in-game model representation.


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

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!