add color to VBOs - best practices - opengl

I am working on a visualisation engine (simple CAD style) (with python and pyopengl bindings) that will display and animate up to 10-20 bodies simultaneously.
I am using VBO data objects to store vertex data and to display each body. I would like to know what is the best (most practical, easiest and less expensive-GPU) method to assign color to a VBO. Each body has uniform color and the appearance can be set to transparent - optional. As I know this can be done with the following methods (I tested method 1 and 2):
glColorf(R, G, B, A)
glMaterialfv(GL_FRONT_AND_BACK, , [R, G, B, A])
assign color to each vertex and create interleaved VBO
Are there any other methods? And which one is most suited for the job?
I would also like to ask how many vertices per VBO are recomended for one VBO and how many vertices have, lets say; small, medium and large VBOs? Just to give me more knowledge about size of the displayed objects.

The coloring part depends on which version of OpenGL you are using now, which version in the future, and whether or not you want lighting.
If you are using OpenGL 2.1, perhaps because you like having a built in matrix stack and gluPerspective, then glColor4f is the easiest way to set the uniform color for a non-lit object. If you want to use lighting, add a glColorMaterial call as well. Or for lighting you could use glMaterial.
As Andon points out, these will stop working if you have to move to OpenGL 3 or 4. So if this program is going to be updated in the future, or you have plans to add extra capabilities based on programmable GPU shaders, grab a copy of the OpenGL SuperBible 6th ed and start coding. The easiest way will be to add another VBO with per-vertex colors, or interleave colors with VBO as you've already discovered. In theory this is wasting space because a single color gets duplicated many times, but if you're not changing the color every frame, so what? (Gigabyte graphics cards are wonderful.)
OK, the recommended number of vertexes per VBO. Again, do you care? You say you have 10 - 20 objects to be rendered. That's not an excessive number of OpenGL calls per frame. Perhaps if you needed to render thousands of objects per frame it would be worth thinking about, but my advice is always to do the simplest thing that works first, because very often that's fast enough.
To get maximum performance from OpenGL you generally need to minimise the number of calls per frame. So if you have too many individual OpenGL calls, it doesn't really matter whether the data is one big VBO or lots of little ones. Stuffing more data into big VBOs (read up on primitive restart) usually does allow you to reduce the number of calls, and modern graphics cards let you store megabytes or even gigabytes per VBO. Read Real-Time Rendering by Moller and Haines, or the indirect drawing section of the SuperBible for more detail.
Hope this helps.

Related

OpenGL - How to render many different models?

I'm currently struggling with finding a good approach to render many (thousands) slightly different models. The model itself is a simple cube with some vertex offset, think of a skewed quad face. Each 'block' has a different offset of its vertices, so basically I have a voxel engine on steroids as each block is not a perfect cube but rather a skewed cuboid. To render this shape 48 vertices are needed but can be cut to 24 vertices as only 3 faces are visible. With indexing we are at 12 vertices (4 for each face).
But, now that I have the vertices for each block in the world, how do I render them?
What I've tried:
Instanced Rendering. Sounds good, doesn't work as my models are not the same.
I could simplify distant blocks to a cube and render them with glDrawArraysInstanced/glDrawElementsInstanced.
Put everything in one giant VBO. This has a better performance than rendering each cube individually, but has the downside of having one large mesh. This is not desireable as I need every cube to have different textures, lighting, etc... Selecting a single cube within that huge mesh is not possible.
I am aware of frustum culling and occlusion culling, but I already have problems with some cubes in front of me (tested with a 128x128 world).
My requirements:
Draw some thousand models.
Each model has vertices offsets to make the block less cubic, stored in another VBO.
Each block has to be an individual object, as you should be able to place/remove blocks.
Any good performance advices?
This is not desireable as I need every cube to have different textures, lighting, etc... Selecting a single cube within that huge mesh is not possible.
Programmers should avoid declaring that something is "impossible"; it limits your thinking.
Giving each face of these cubes different textures has many solutions. The Minecraft approach uses texture atlases. Each "texture" is really just a sub-section of one large texture, and you use texture coordinates to select which sub-section a particular face uses. But you can get more complex.
Array textures allow for a more direct way to solve this problem. Here, the texture coordinates would be the same, but you use a per-vertex integer to select the correct texture for a face. All of the vertices for a particular face would have an index. And if you're clever, you don't even really need texture coordinates. You can generate them in your vertex shader, based on per-vertex values like gl_VertexID and the like.
Lighting parameters would work the same way: use some per-vertex data to select parameters from a UBO or SSBO.
As for the "individual object" bit, that's merely a matter of how you're thinking about the problem. Do not confuse what happens in the player's mind with what happens in your code. Games are an elaborate illusion; just because something appears to the user to be an "individual object" doesn't mean it is one to your rendering engine.
What you need is the ability to modify your world's data to remove and add new blocks. And if you need to show a block as "selected" or something, then you simply need another per-block value (like the lighting parameters and index for the texture) which tells you whether to draw it as a "selected" block or as an "unselected" one. Or you can just redraw that specific selected block. There are many ways of handling it.
Any decent graphics card (since about 2010) is able to render a few millions vertices in a blinking.
The approach is different depending on how many changes per frame. In other words, how many data must be transferred to the GPU per frame.
For the case of small number of changes, storing the data in one big VBO or many smaller VBOs (and their VAOs), sending the changes by uniforms, and calling several glDraw***, shows similar performance. Different hardwares behave with little difference. Indexed data may improve the speed.
When most of the data changes in every frame and these changes are hard or impossible to do in the shaders, then your app is memory-transfer bound. Streaming is a good advise.

C++ OpenGL array of coordinates to draw lines/borders and filled rectangles?

I'm working on a simple GUI for my application on OpenGL and all I need is to draw a bunch of rectangles and a 1px border arround them. Instead of going with glBegin and glEnd for each widget that has to draw (which can reduce performance). I need to know if this can be done with some sort of arrays/lists (batch data) of coordinates and their color.
Requirements:
Rectangles are simple filled with one color for every corner or each corner with a color. (mainly to form gradients)
Lines/borders are simple with one color and 1px thick, but they may not always closed (do not form a loop).
Use of textures/images is excluded. Only geometry data.
Must be compatible with older OpenGL versions (down to version 1.3)
Is there a way to achieve this with some sort of arrays and not glBegin and glEnd? I'm not sure how to do this for lines/borders.
I've seen this kind of implementation in Gwen GUI but it uses textures.
Example: jQuery EasyUI Metro Theme
In any case in modern OpenGL you should restrain to use old fashion API calls like glBegin and the likes. You should use the purer approach that has been introduced with core contexts from OpenGL 3.0. The philosophy behind it is to become much closer to actual way of modern hardware functionning. DiretX10 took this approach, somehow OpenGL ES also.
It means no more lists, no more immediate mode, no more glVertex or glTexCoord. In any case the drivers were already constructing VBOs behind this API because the hardware only understands that. So the OpenGL core "initiative" is to reduce OpenGL implementation complexity in order to let the vendors focus on hardware and stop producing bad drivers with buggy support.
Considering that, you should go with VBO, so you make an interleaved or multiple separated buffer data to store positions and color information, then you bind to attributes and use a shader combination to render the whole. The attributes you declare in the vertex shader are the attributes you bound using glBindVertexBuffer.
good explanation here:
http://www.opengl.org/wiki/Vertex_Specification
The recommended way is then to make one vertex buffer for the whole GUI and every element should just be put one after another in the buffer, then you can render your whole GUI in one draw call. This is how you will get the best performance.
Then if your GUI has dynamic elements this is no longer possible exept if using glUpdateBufferSubData or the likes but it has complex performance implications. You are better to cut your vertex buffer in as many buffers that are necessary to compose the independent parts, then you can render with uniforms modified between each draw call at will to configure the change of looks that is necessary in the dynamic part.

Is it possible to reuse glsl vertex shader output later?

I have a huge mesh(100k triangles) that needs to be drawn a few times and blend together every frame. Is it possible to reuse the vertex shader output of the first pass of mesh, and skip the vertex stage on later passes? I am hoping to save some cost on the vertex pipeline and rasterization.
Targeted OpenGL 3.0, can use features like transform feedback.
I'll answer your basic question first, then answer your real question.
Yes, you can store the output of vertex transformation for later use. This is called Transform Feedback. It requires OpenGL 3.x-class hardware or better (aka: DX10-hardware).
The way it works is in two stages. First, you have to set your program up to have feedback-based varyings. You do this with glTransformFeedbackVaryings. This must be done before linking the program, in a similar way to things like glBindAttribLocation.
Once that's done, you need to bind buffers (given how you set up your transform feedback varyings) to GL_TRANSFORM_FEEDBACK_BUFFER with glBindBufferRange, thus setting up which buffers the data are written into. Then you start your feedback operation with glBeginTransformFeedback and proceed as normal. You can use a primitive query object to get the number of primitives written (so that you can draw it later with glDrawArrays), or if you have 4.x-class hardware (or AMD 3.x hardware, all of which supports ARB_transform_feedback2), you can render without querying the number of primitives. That would save time.
Now for your actual question: it's probably not going to help buy you any real performance.
You're drawing terrain. And terrain doesn't really get any transformation. Typically you have a matrix multiplication or two, possibly with normals (though if you're rendering for shadow maps, you don't even have that). That's it.
Odds are very good that if you shove 100,000 vertices down the GPU with such a simple shader, you've probably saturated the GPU's ability to render them all. You'll likely bottleneck on primitive assembly/setup, and that's not getting any faster.
So you're probably not going to get much out of this. Feedback is generally used for either generating triangle data for later use (effectively pseudo-compute shaders), or for preserving the results from complex transformations like matrix palette skinning with dual-quaternions and so forth. A simple matrix multiply-and-go will barely be a blip on the radar.
You can try it if you like. But odds are you won't have any problems. Generally, the best solution is to employ some form of deferred rendering, so that you only have to render an object once + X for every shadow it casts (where X is determined by the shadow mapping algorithm). And since shadow maps require different transforms, you wouldn't gain anything from feedback anyway.

Using Vertex Buffer Objects for a tile-based game and texture atlases

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.

How do I use Vertex Buffer Objects to render many different circles?

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.