Is it a good or bad idea to use display lists for drawing textured rectangles?
The display list would be re-compiled only if the texture the sprite is using changes.
For drawing a single sprite, there's no real problem in doing it that way, but there's no advantage to it either, assuming you're using glRotate/glTranslate to position the sprite. Plenty of games have been written that way.
In my games, I use a vertex buffer object with GL_DYNAMIC_DRAW to store all the sprites which share each texture atlas. I update the vert positions on the CPU and send the whole batch in one draw call. I can draw many more sprites using this approach. I could do the positions in a vertex shader if I needed to draw even more.
Also, keep in mind that OpenGL ES2 doesn't support display lists, so if you're thinking of porting to an ES2 device you'd have to re-do it. (iPhone/iPad support ES1 but you can't mix and match with ES2, you can use display lists OR shaders but not both).
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 have to render large quantities of particles. These particles are simple non-textured quads (squares actually). Oh, and they're moving all the time since they're particles.
I have considered 2 options but as I'm not an OpenGL expert I don't know what's best.
Use VBOs to render them all.
Pros: faster than immediate mode.
Cons: (I don't know much about VBOs but) from what I gather the quads' coordinates need to be stored in some buffer in RAM... and all of these coordinates need to be computed by the CPU. So for particle P1(x,y) I would have to compute 4 other coordinates (P2(x-1,y-1), P3(x-1,y+1), P4(x+1,y+1), P5(x+1,y-1)) - that's a lot of work for the CPU!
Use a display list: First create a tiny display list for a single square quad. Then, to render each particle do some pushMatrix, glTranslate, callList, popMatrix.
Pros: I don't have to compute 4 coordinates manually - glTranlate does that.
Supposedly display lists are faster than VBOs.
Cons: Are they faster than VBOs when they contain just one quad?
Mind you: I'm calling OpenGL stuff from Java so there's no smooth way of transforming Java arrays to GPU arrays (everything has to be stored in intermediary FloatBuffers before transfers).
Display Lists are for static geometry. Rendering just one single quad, then changing the transformation, rinse and repeat is horribly inefficient.
Updating VBOs is better but still not optimal.
You should look into instanced rendering. Here's a tutorial:
http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html
In the case of simple quads using a geometry shader turning simple GL_POINTS into two GL_TRIANGLES would do the trick as well.
To do particle simulations i think what you are looking for is transform feedback, here is a nice demonstration with some code on how to do it http://prideout.net/blog/?tag=opengl-transform-feedback
I'm just starting OpenGL programming in Win32 C++ so don't be too hard on me :) I've been wandering along the NeHe tutorials and 'the red book' a bit now, but I'm confused. So far I've been able to set up an OpenGL window, draw some triangles etc, no problem. But now I want to build a model and view it from different angles. So do we:
Load a model into memory (saving triangles/quads coordinates in structs on the heap) and in each scene render we draw all stuff we have to the screen using glVertex3f and so on.
Load/draw the model once using glVertex3f etc and we can just change the viewing position in each scene.
Other...?
It seems to me option 1 is most plausible from all I read so far, however it seems a bit ehh.. dumb! Do we have to decide which objects are visible, and only draw those. Isn't that very slow? Option 2 might seem more attractive :)
EDIT: Thanks for all the help, I've decided to do: read my model from file, then load it into the GPU memory using glBufferData and then feed that data to the render function using glVertexPointer and glDrawArrays.
First you need to understand, that OpenGL actually doesn't understand the term "model", all what OpenGL sees is a stream of vertices coming in and depending on the current mode it uses those streams of vertices to draw triangles to the screen.
Every frame drawing iteration follows some outline like this:
clear all buffers
for each window element (main scene, HUD, minimap, etc.):
set scissor and viewport
conditionally clear depth and/or stencil
set projection matrix
set modelview matrix for initial view
for each model
apply model transformation onto matrix stack
bind model data (textures, vertices, etc.)
issue model drawing commands
swap buffers
OpenGL does not remember what's happening up there. There was (is) some facility, called Display Lists but they are not able to store all kinds of commands – also they got deprecated and removed from recent OpenGL versions. The immediate mode commands glBegin, glEnd, glVertex, glNormal and glTexCoord have been removed as well.
So the idea is to upload some data (textures, vertex arrays, etc.) into OpenGL buffer objects. However only textures are directly understood by OpenGL as what they are (images). All other kinds of buffers require you telling OpenGL how to deal with them. This is done by calls to gl{Vertex,Color,TexCoord,Normal,Attrib}Pointer to set data access parameters and glDraw{Arrays,Elements} to trigger OpenGL fetching a stream of vertices to be fed to the rasterizer.
You should upload the data to the GPU memory once, and then draw each frame using as few commands as possible.
Previously, this was done using display lists. Nowadays, it's all about vertex buffer objects (a.k.a. VBOs), so look into those.
Here's a tutorial about VBOs, written before they were only an extension, and not a core part of OpenGL.
I been working in a new game, and finally reached the point where I started to code the motion of my main character but I have a doubt about how do that.
Previously, I make two games in Allegro, so the spritesheets are kind of easy to implement, because I establish the frame and position on the image, and save every frame in a different bitmap, but I know that do that with OpenGL it's not neccesary and cost a little bit more.
So, I been thinking in how save my spritesheet and used in my program and I have only one idea.
I loaded the image and transformed in a texture, in my function that help me animate I simply grab a portion of the texture to draw instead of store every single texture in my program.
This is the best way to do that?
Thanks beforehand for the help.
You're on the right track.
Things to consider:
leave enough dead space around each sprite so that the video card does not blend in texels from adjacent sprites at small scales.
set texture min/mag filtering appropriately. GL_NEAREST is OK if you're going for the blocky look.
if you want to be fancy and save some texture memory, there's no reason that the sprites have to be laid out in a regular grid. Smaller sprites can be packed closer in the texture.
if your sprites are being rendered from 3D models, you could output normal & displacement maps from the model into another texture, then combine them in a fragment shader for some awesome lighting and self-shadowing.
You got the right idea, if you have a bunch of sprites it is much better to just stick them all in one big textures. Just draw your sprites as textured quads whose texture coordinates index into the frame of the sprite. You can do a few optimizations, but most of them revolve around trying to get the most out of your texture memory and packing the sprites closely together with out blending issues.
I know that do that with OpenGL it's not neccesary and cost a little bit more.
Why not? There are no real downsides to putting a lot of sprites into a single texture. All you need to do is change the texture coordinates to pick the region in question out of the texture.
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.