[Question] Rendering large objects (3D map) + Textures

Started by zevrix, February 04, 2014, 03:42:29

Previous topic - Next topic

zevrix

Okay so I have efficiency related questions relating to maps with the lwjgl library.

first off what is the preferred method of rendering a map? sofar the methods I know of:

  • Immediate mode
  • Display List
  • Vertex Array
  • Vertex Buffer Object

I have a good understanding of how to use Immediate mode, but i have been having a lot of problems with vbo's..

what mode would be best for loading a large static mesh likely in OBJ format
(due to simplicity of parsing and loading, vertices ect) ?

assuming this is a fairly large map (ex: 500Mb of vertices and normals) would it be better to split the map up into sections that are smaller?
I'm not thinking about RAM usage with this. I intend for the entire map to be in RAM once initialized.  I'm more focused of performance of the rendering.

if I tell OpenGL to render all these vertices outside of the actual display I would assume that it it would take forever to produce a single frame, correct?

I also what to know how to apply a texture to this map.. not a static texture throughout the entire map. is there a way to apply a different texture to a specific area or set of vertices? and some sort of blending between them?
(so a grass texture can blend with a sand texture)

also if anyone has any solid tutorials on VBO please link them..
thanks.

Cornix

I hope you realize, that of the 4 "ways" of rendering you listed 3 are deprecated and discouraged?
Immediate mode is slow, display lists are not flexible, vertex arrays are the same as VBO's but less efficient.

Nowadays you render everything with VBO's. If you want high performance you more or less have no other choice.

zevrix

I know that they are deprecated. but i would still be comfortable using them if it didn't damage performance significantly in the end.

Cornix

But they will. Thats why they are deprecated in the first place.
As a rule of thumb: the more openGL-calls you have to make the slower will your application be.
And no matter what procedure you use, you still have to move the same kind of data. So there are absolutely no benefits of using a different method then VBO's, while there are plenty of problems when not using VBO's.

zevrix

alright, I have spent most of my morning working on a vbo rendering engine, not too far though. it can render a predefined triangle so far.

I think I am starting to understand vbo a bit more but I am going to need to make some changes to macro the process of adding objects.

quew8

Quotewould it be better to split the map up into sections that are smaller?

Yes. My advice for what it is worth: split the map into very simple cuboids. Each cuboid has its own VBO. Do a simple frustrum cull check against each cuboid and immediately you will only have to render 2 - 3 of them at a time. It sounds like you're dealing with terrain sort of data. If so and if it is arranged in regular grids then make sure you make each cuboid something like 128x128 that way you get nicely sized VBOs and OpenGL will purr for you.

Quoteis there a way to apply a different texture to a specific area or set of vertices? and some sort of blending between them?

Probably the easiest way is to have a texture for each cuboid (cuboid as per above) which is the terrain for that section (ie it looks like a birds eye view of the terrain) then you sample that texture in the shader based on the vertex's position relative to the section.

In terms of blending textures - the above method means that is not needed but even if you don't do that I would recommend using a "bridging" texture (eg for grass -> sand it would start of with just grass then have a few sand clumps then mostly sand with a few grass clumps then full sand) purely because it will look better than blending.

If you're set on blending then you need to use two texture units then interpolate between them in the fragment shader.

zevrix

Thanks! and I am by no means stuck on blending the textures, I can make transition textures no problem. would it be problematic to save all this data in VBO's though? cuz were talking a relatively large map. (to put into perspective I am going for a grid of 128X128 being relatively 5 sq meters 16.4 feet) and approximately 100 of these just across. let alone top to bottom (around 75).  this would leave me with 122,880,000 * 3 floating point numbers loaded into the graphics card.  unless I am misreading, you are telling me to load them all then display them by their cuboids as they come into view? is there a way to dynamically load and unload them from the graphics card?

we are talking 1.4 GB stored in the graphics card (give or take a fairly large number seeing as the map is not completed yet)... that is, well alot.. lol, the map resolution can definitely be reduced but id prefer to keep it higher if possible.

these numbers do seem very large but my target audience is for higher end computers in order to keep the project up to date as better tech becomes cheaper.  

quew8

It is definitely possible. Delete a VBO and its memory will be freed. Better yet reuse the same VBO and just replace the data in it. This will work well if, as you seem to be suggesting, your terrain is regular in terms of resolution since you don't have to resize the VBOs \ have unused space. My advice is to load the 3x3/5x5 square around the player. The actual size of course depends on how big the cuboids are and how large the players view distance is.

Whatever your target hardware is, some kind of compromise can normally be reached.

zevrix

so i have looked into using glBufferSubData to update the VBO data.  

I am using this to replace the data, where 'vertices' is an array of vertices,
this is a fixed size for every update:

glBufferSubData(GL_ARRAY_BUFFER, 0, Util.createFlippedBuffer(vertices));

I have read you can also swap the data using glMapBuffer but I don't know if it is any better.

my questions are: is this the correct parameters that i am passing to the function? and
is this the only call that I have to make to update the vertex stored in the VBO?

apologies for all the questions. I am new to OpenGL and have found it difficult to find informative material.. Alot of tutorials and examples are vague, and do not explain how they work.  they are more geard towards showing a large block of code and explaining it as a whole...

Cornix

Looks correct to me.
The second parameter, the 0 in your example, indicates where to start with the overwrite in the VBO. If you start at 0 and your vertices-array has the same size then the VBO then all data from the VBO will be overwritten.
Please note that it looks like you are currently creating a totally new ByteBuffer every single time you call this function. If this function is called very often I would suggest you keep one persistent buffer and only fill it as necessary. Keep in mind you can use the buffers position and limit to indicate what portion of the ByteBuffer you want to use in OpenGL calls.