A bug was mentioned on the IRC today regarding terrain. Basically, if you make a TerrainBlock size 256 performance turns down to about 1 frame every once in awhile (i.e. so bad you can't calculate how bad it is ). This is without CLOD, with CLOD I quit waiting for it to load after about 5 minutes (Galun, who reported it, waited 10 before quittting). So, we obviously have some issues in the Terrain world.
The triangle count with 256x256 heightmap was around 150k. Where I can run other non-terrain demos with tri at 250k at 25 FPS.
I bring this up here, rather than just posting an issue, because I believe this is a good chance if anyone has ideas to improve the terrain. It's honestly, not that great, so if someone has ideas of where he'd like to see the terrain go, here's your opportunity. Otherwise, I'll just add the issue and we'll fix the performance problem.
Do you have the test somewhere so I can see if the problem exists on my machine as well?
Just modify TestTerrain to load a heightmap of 256 (change from 128) and turn off CLOD (last parameter turned to false), and you *should* see the problem.
I would certainly be interested in what you have implemented so far. The performance of the existing terrain in both rendering speed and memory consumption has been poor for awhile, and I'm open to any others.
My fix seems to have actually solved the problem. It ran fine for me (100+ FPS, 50+ for size 512). When I "unfixed" my code, I didn't even get to the terrain. So update CVS and try again.
Apperently mixing non-VBO normals with VBO vertices is a problem somehow?
And CLOD gives me an OutOfMemoryError pretty quickly. I assume the CLOD stuff was touched during the switch to NIO buffers… maybe something went wrong there? Or is the algorithm just bad for this type of mesh? It takes long and seems to eat a lot of memory (would have to do a proper profiling to confirm the latter) even for a size 16 mesh. Anyway, don't know about others but CLOD never looked good combined with terrain here, and it was always slow for me. Though I don't remember it being this slow, and that was on a lot less powerfull computer even.
As for making terrain as fast as possible, I think the key is in good LOD practises optimized for terrain, and I have some ideas on that I'll hopefully implement. Apart from that it could benefit a lot from some form of occlusion culling. When I "walk" on my test terrains, I often find there's huge terrain being rendered behind a mountain range or something that I don't see anything of.
Yep, the VBO issue fixed it, and it runs SIGNIFICANTLY better with that fix. I created a 512x512 terrain which is over 500k triangles, and was getting 30+ FPS. Very nice, I no longer feel so bad about the terrain blocks, hehe.
What we probably need regarding CLOD is a way to prebuild the VET table and load it from a file. Generating the table takes a significant amount of time. I also talked with Renanse about not having Terrain extend ClodMesh, but be able to become one if desired. This would take some of the overhead out if you don't want to use CLOD.
Occulusion culling would also be great but if you could make it general enough, we could also remove the houses and goblins that are hidden behind the same hill.
500k tris - 100fps here (170fps with no lighting) It's nice to see us pushing 50million tps.
As for CLOD, there is some extra overhead for TerrainBlock… 3 floats, 2 ints and a null pointer if you set using clod to false. I'm not sure it's major enough for a revamp, especially if we are considering other terrain options.
I'm not sure it's major enough for a revamp, especially if we are considering other terrain options.
Well, it wouldn't be a major revamp it would be as simple as: Terrain extends AreaClodMesh changing to Terrain extends TriMesh.
This would be necessary for other terrain algorithms as it could get in the way. If someone were to build a GeomipmapTerrain for instance that built a grid of TerrainBlocks, they would be manipulating the index buffer directly for the mipmap LOD algorithm, so having CLOD there could create problems (if someone were to turn it on).
CLOD performance with terrain is poor enough that it's not a very viable option anyways (IMO).
Poor as in start time? Or poor as in results? If just start time, we could fix this for most cases by saving the clod records in the .jme format thus only generating them once in development and not on the user's machine. If it's the results that you consider poor, well we only currently have one usage of CLOD, which is Screen Area based. If we extend ClodMesh and have record picking done in a way that is more appropriate to Terrain, that could help a lot.
As for changing it to extend TriMesh, we certainly could do that… Then if you did want to use CLOD though as it stands, it would have to remake itself as another Spatial and plug itself back into the scenegraph. If we did other techniques, I'd almost see that as a rewrite of Terrain rather than trying to shoehorn it into the current classes.
My two cents on it though, not really defending anything here.
Poor as in both. Start time is very poor but as you mention it can be saved and loaded later. But on all my machines I lose ~10 FPS using CLOD rather than without it. The CPU overhead is just too great. There are so many Terrain LOD algorithms that are superior that it doesn't seem worth using to me.
This is not related to models using CLOD, it's still very useful in this case because model data is not uniform like a heightmap. But the unifomity of the heightmap grid allows for much faster LOD techniques (geomipmapping, ROAM, SOAR, etc).
Cool… We may want to architect something more open for Terrain then… I've no idea if all of those algs use quad-tree for example?
Yes, agreed. That's why I was so excited to see TerrainBlock performing well. As it can be the basis for a number of different terrain algorithms (i.e. the algorithm just manipulates a collection of TerrainBlocks). While it won't be appropriate for all algorithms (ROAM uses Diamonds for split/merging), but many can use it (Geomipmapping just affects the indices).
TerrainPage can stay as just a simple Quad-Tree implementation (and perhaps should have it's name changed to better represent that).
Anyways, the VBO fix helped things out enough that this is put in the "feature" bin rather than the "OH MY GOD, FIX!" bin. So, we can discuss ideas at leasure.
I'm very interested to see Llama's dynamic page loading scheme though.
Shall I go ahead and nix CLOD then? (i mean as a superclass to TerrainBlock)
let's leave it there until another LOD scheme is ready to take its place.
One of the last bit I'm finishing now before releasing now is actually is a Terrain LOD manager, where the user can set criteria, based on which a LOD method will be chosen and applied. At first I'll implement just one very simple geomipmapping-like method.
If anything, my terrain stuff will be good for experimenting on. Maybe some day it can fully match the features of the current terrain.
Normals are also not needed in a lot of situations, we can use the simple Slope Lighting algorithm to build a lightmap.
However, I want to put this on the back burner and not distract too much from the real 0.10 items. With that bug fixed, it has longer staying power, and there are higher priority issues and features from 0.10.
One thing we do need to look into (llama your implementation may already take care of this), is the memory usage of TerrainPage. Building a TerrainPage of 1025x1025 causes an out of memory error. I increased the max mem size of the JVM as much as I could (1GB). I'd like 1024x1024 to be a goal to reach (and perhaps go beyond if possible).
Well I just did a quick test with something almost as big (the terrain actually loads in a circle around the camera position so it's not exact) with ~1.500.000 vertices and memory and VM size is almost exactly 100.000 K.
However, I assume you're using textures on TerrainPage or something? It really is a lot to texture with procedural textures. Even John Carmack proudly proclaimed he uses 3000x3000 textures for terrain. I think you're going over that with 1024x1024, 3000x3000 textures would mean only 9 pixels per "cell". Volitile images for texuring would help, but no card can hold them all either. ProceduralTextureGenerator is a really really brute force method. Eg. it might be a lot faster to use normal base textures, and generate an alpha map (smaller and faster) to blend in a snow textures over a mountain top, or transitions between grass and rock, etc.
Texture is 512x512
pt.createTexture(512);
Assuming you agaain took the default test and only changed the size: it doesn't even reach the PTG here by default.
However, even with
-Xms75m -Xmx75m
it runs here.
Lots of memory going in the fact we have two sets of texture coordinates. And as mentioned before every block has it's own indices buffer. However it's the texture-cos that really eat away memory (for every vertex, 4 extra floats.) The two coordinate sets are the same expect that every coordinate is multiplied with the detail level. You'd think there's a way to use the same buffer twice, and solve it with scaling instead?
Agreed. I think the current terrain is useful as it is, eg look at "WolkenStein" in user showcase.