I'm trying to write a game that deals with many circles (well, Triangle Fans, but you get the idea). Each circle will have an x position, a y position, and a mass property. Every circle's mass property will be different. Also, I want to color some groups of circles different, while keeping a transparent circle center, and fading to opaque along the perimeter of the circles.
I was told to use VBOs, and have been Googling all day. I would like a full example on how I would draw these circles and an explanation as to how VBOs work, while keeping that explanation simple.
I have not implemented VBOs myself yet, but from what I understand, they work similar to texture objects. In fact, when I am reminding myself and explaining to others what VBOs are, I like to incorrectly call texture objects 'texture buffer objects', to reinforce the conceptual similarity.
(Not to be mixed with buffer textures from NVIDIA-specified extension GL_EXT_texture_buffer_object.)
So let's think: what are texture objects? They are objects you generate using glGenTextures(). glGenBuffersARB() does similar thing. An analogy applies with glBindTexture() and glBindBufferARB().
(As of OpenGL 1.5, functions glGenBuffers() and glBindBuffer() have entered core OpenGL, so you can use them in place of the extension equivalents.)
But what exactly are these 'texture objects', and what do they do? Well, consider that you can, actually, use glTexture2D() in each frame to set up a texture. Texture objects only serve to reduce traffic between GPU and main memory; instead of sending entire pixel array, you send just the "OpenGL name" (that is, an integer identifier) of the texture object which you know to be static.
VBOs serve similar purpose. Instead of sending the vertex array over and over, you upload the array once using glBufferData() and then send just the "OpenGL name" of the object. They are great for static objects, and not so great for dynamic objects. In fact, many generic 3D engines such as Ogre3D provide you with a way to specify if a mesh is dynamic or static, quite probably in order to let you decide between VBOs and vertex arrays.
For your purposes, VBOs are not the right answer. You want numerous simple objects that are continuously morphing and changing. By simple, I mean those with less than 200 vertices. Unless you intend to write a very smart and complex vertex shader, VBOs are not for you. You want to use vertex arrays, which you can easily manipulate from main CPU and update them each frame without making special calls to graphics card to reupload the entire VBO onto the graphics card (which may turn out slower than just sending vertex arrays).
Here's a quite good letscallit "man page" from nVidia about VBO API. Read it for further info!
good vbo tutorial
What you're doing looks like particles, you might want to google "particle rendering" just in case.
Related
I'm trying to use modern OpenGL and shaders, instead of the immediate mode I have been using so far. I recently learned about VBOs and VAO, and I'm still trying to get my head round them, but I know that a VBO takes an array of floats that are vertices, which it then passes to the GPU etc
What is the best way to draw multiple objects (which are all identical) but in different positions, using VBOs. Will I have to draw one, then modify the array passed in beforehand, and then draw it again and modify and draw and modify and so on... for all blocks in the screen every frame? Or is there a better way?
I'm trying to achieve this: http://imgur.com/cBgJ0sK
Any help is appreciated - I don't want to learn bad (deprecated, old) immediate mode habits, when I could be learning a more modern way!
You should not modify the vertices in your program, that should be done in the shaders. For this, you will create a matrix that represents the transformation and will use that matrix in the vertex shader.
The main idea is:
You create a VAO holding the information of your VBO (vertices, normals, texture coordinates, tangent information, etc.)
Then, for every different object, you generate a model matrix that holds the information of the position, orientation and scale (and other homogeneous tranformations) and send that to your shader to make the transformations.
The idea is that you bind your VAO just once and then draw all the different objects just sending the information that change (model matrix, may be textures) and draw the objects.
To learn about how to use the model matrix, read tutorials like this:
http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html
There are even better ways to do this, but you can start from here.
Other information that would be good for your case is using instancing.
http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html
Later, you can move on indirect drawing for even better performance. Later...
I've been using XNA for essentialy all of my programming so far and would like to move on to OpenGL (along with SFML for IO, creating the window etc.) with C++ . For starters I'd like to create a tile-based game and I've mostly looked at LazyFoo's tutorials.
I just have a two questions:
How should I draw the tiles? Should I use immediate drawing, arrays, VBOs or what? VBOs feel like overkill for this but I'm not sure. It's very tempting to use immediate drawing but apparently it's deprecated. Maybe it's fine for this purpose since it's 2D and only for a bunch of quads.
I'd like a lot of different tiles and thus all of my tiles will not fit into a single texture without making it massive. I've read that using bindTexture isn't very cheap and thus I should avoid as many calls as I can. I thought that maybe I can create a manager for my textures and stitch them all together into one big texture and bind that but then the dimensions of that is an issue.
Don't use immediate mode! It's cumbersome to work with and has been removed from recent OpenGL versions. Use Vertex Arrays, ideally through VBOs. In the end they're much easier to use, believe me.
Regarding that switching of textures. We're talking about optimizing the texture switch patterns in very complex scenes. In your case it will hardly matter at all.
Update
Right now you worry abount things without having even used them. That's worse than premature optimization. I suggest you first get a good grip on OpenGL, then start worrying about state switch management.
With regards to the texture atlas; this is usually done by stitching textures into groups of power-of-two sized textures. For example in a tile-based game you might have a particular tile set (say, tiles for an ice world) grouped together on 2 or 3 textures. When you want to render them you would determine what tiles are visible, then you bind each texture once and render the tiles from that texture for any tiles that are visible on screen.
This requires quite a lot of set-up time to get right; you need keep information on each sub-texture of the atlas so you can find the right texture and render the appropriate region of that texture whenever a tile is referenced. You also need a good way of grouping rendering operations so that they occur when the appropriate texture is bound.
Like datenwolf said, I wouldn't focus too much on complicated texture systems early on; eager binding of textures will be plenty fast enough until you get further down the road.
I'm making a 2D game in openGL and I have a list of static objects. Thus far I'm looping through them and drawing them into the room, however in some large rooms there are up to 2000 of them and speed is critical so I'd like to find a way to "bake" them all together and never update them in the draw loop after that.
How can I do this and what's the best way in terms of performance, memory usage, gpu ram usage etc?
I'd prefer to use oGL 2, but I'm considering oGL 3+.
The simplest way is to move all the data of those objects to the GPU so that rendering commands will fetch memory directly from GPU memory. It can be done by simply using VBO or even DisplayList (in 'old' OpenGL 2.0 and before).
Probably the DisplayList solution wll be the most efficient because you can 'pack' all the commands inside... with VBO you can pack only the geometry data, the materials need to be setup every frame.
Related topic: instacing (but you will have to use GL 3+).
Another way is to render them to textures... and display them as simple Sprits. This technique is called 'impostors', here is some info: True Impostors.
Another option: render the environment to a Cube Map. It could work for objects that are far away from the camera (like hills, tries, etc...) but in a room it could look strange.
First option: make single mesh for objects. For example, you may dynamically update index array with objects that are visible. Very important in this case that textures you use should be in an atlas. If you can't share shader and textures there is no much effect from this technique. You may combine this method, grouping by material an texture and using single draw call to render. For example, first draw call - render 100 trees with one texture, and than render 600 apples on them and after 100 clouds.
Another option, if your objects are static you may render all of them into texture using FBO. This may be applied if your objects like background. For example, your render random stars (1000) in space for your galaxy.
I'm doing a 2D turn based RTS game with 32x32 tiles (400-500 tiles per frame). I could use a VBO for this, but I may have to change almost all the VBO data each frame, as the background is a scrolling one and the visible tiles will change every time the map scrolls. Will using VBOs rather than client side vertex arrays still yield a performance benefit here? Also if using VBOs which data format is most efficient (float, or int16, or ...)?
If you are simply scrolling, you can use the vertex shader to manipulate the position rather than update the vertices themselves. Pass in a 'scroll' value as a uniform to your background and simply add that value to the x (or y, or whatever applies to your case) value of each vertex.
Update:
If you intend to modify the VBO often, you can tell the driver this using the usage param of glBufferData. This page has a good description of how that works: http://www.opengl.org/wiki/Vertex_Buffer_Object, under Accessing VBOs. In your case, it looks like you should specify GL_DYNAMIC_DRAW to glBufferData so that the driver puts your VBO in the best place in memory for your application.
The regular approach is to move the camera and perform culling instead of updating the content of the VBOs. For a 2d game culling will use simple rectangle intersection algorithm, which you will need anyway for unit selection in the game. As a bonus, manipulating the camera will allow to rate the camera and zoom in and zoom out. Also you could combine several tiles (4, 9 or 16) into one VBO.
I would strongly advise against writing logic to move the tiles instead of the camera. It will take you longer, have more bugs, and be less flexible.
The format will depend on what data you are storing in the VBOs. When in doubt, just use uint8 for color and float32 for everything else. Though for a 2d game your VBOs or vertex array are going to be very small compared to 3d applications, so it's highly unlikely VBO will make any difference.
I'm creating a tile-based game in C# with OpenGL and I'm trying to optimize my code as best as possible.
I've read several articles and sections in books and all come to the same conclusion (as you may know) that use of VBOs greatly increases performance.
I'm not quite sure, however, how they work exactly.
My game will have tiles on the screen, some will change and some will stay the same. To use a VBO for this, I would need to add the coordinates of each tile to an array, correct?
Also, to texture these tiles, I would have to create a separate VBO for this?
I'm not quite sure what the code would look like for tiling these coordinates if I've got tiles that are animated and tiles that will be static on the screen.
Could anyone give me a quick rundown of this?
I plan on using a texture atlas of all of my tiles. I'm not sure where to begin to use this atlas for the textured tiles.
Would I need to compute the coordinates of the tile in the atlas to be applied? Is there any way I could simply use the coordinates of the atlas to apply a texture?
If anyone could clear up these questions it would be greatly appreciated. I could even possibly reimburse someone for their time & help if wanted.
Thanks,
Greg
OK, so let's split this into parts. You didn't specify which version of OpenGL you want to use - I'll assume GL 3.3.
VBO
Vertex buffer objects, when considered as an alternative to client vertex arrays, mostly save the GPU bandwidth. A tile map is not really a lot of geometry. However, in recent GL versions the vertex buffer objects are the only way of specifying the vertices (which makes a lot of sense), so we cannot really talked about "increasing performance" here. If you mean "compared to deprecated vertex specification methods like immediate mode or client-side arrays", then yes, you'll get a performance boost, but you'd probably only feel it with 10k+ vertices per frame, I suppose.
Texture atlases
The texture atlases are indeed a nice feature to save on texture switching. However, on GL3 (and DX10)-enabled GPUs you can save yourself a LOT of trouble characteristic to this technique, because a more modern and convenient approach is available. Check the GL reference docs for TEXTURE_2D_ARRAY - you'll like it. If GL3 cards are your target, forget texture atlases. If not, have a google which older cards support texture arrays as an extension, I'm not familiar with the details.
Rendering
So how to draw a tile map efficiently? Let's focus on the data. There are lots of tiles and each tile has the following infromation:
grid position (x,y)
material (let's call it "material" not "texture" because as you said the image might be animated and change in time; the "material" would then be interpreted as "one texture or set of textures which change in time" or anything you want).
That should be all the "per-tile" data you'd need to send to the GPU. You want to render each tile as a quad or triangle strip, so you have two alternatives:
send 4 vertices (x,y),(x+w,y),(x+w,y+h),(x,y+h) instead of (x,y) per tile,
use a geometry shader to calculate the 4 points along with texture coords for every 1 point sent.
Pick your favourite. Also note that directly corresponds to what your VBO is going to contain - the latter solution would make it 4x smaller.
For the material, you can pass it as a symbolic integer, and in your fragment shader - basing on current time (passed as an uniform variable) and the material ID for a given tile - you can decide on the texture ID from the texture array to use. In this way you can make a simple texture animation.