You can get Voxel Farm now. For more information click here.

Monday, October 17, 2016

Slaying the LOD monster

LOD, or Levels of Detail, is a technique for managing very large and dense scenes like we have today in open world games. The general idea is you can have multiple copies of the same content at different resolutions. Then you switch which copy to use depending on how much detail is necessary for the scene.

LOD switches can be implemented as plain swaps, morphing between states as shown in this earlier post, or even as completely adaptive mesh representations, as shown here.

Sometimes we get fixated on LOD swaps and we drift away devising tricks to make them harder to see. I feel this is not the right angle to look at this problem. While LOD swapping techniques are very important, and progressive swaps are much nicer, etc., the real goal is to have as much detail as possible in the first place. If you find yourself masquerading LOD swaps, it is probably because your scenes still include levels of detail that are too coarse.

How much detail do you need? Just enough to make LOD transitions close to being sub-pixel. Once LOD swaps are sub-pixel, it does not matter what swapping technique you use. It also means your rendering of the content is as detailed as the screen resolution will allow.

This sounds like a Holy Grail, is it feasible with the current hardware generation? We believe it is. Take a look at the following video:



As you can see in the video, buildings preserve their detail, even when viewed from afar. LOD changes, while they do happen, are virtually impossible to detect. All this while keeping interactive frame-rates.

It turns out the same techniques that prevent buildings in the distance from looking like melted crayons also give you smooth LOD transitions. I will be covering how all this works in my next post.

21 comments:

  1. Dude, I've been following your blog for a few years now, and every time I come back your voxel engine is even more impressive. Hoping to see a lot of games using voxel farm in the future.

    I have one question. How general purpose is voxel farm? All your examples until now have been RPGish scenarios. You do have UE4 integration so that gives me hope.

    ReplyDelete
    Replies
    1. Thanks, just remember this has been a team's effort since 2013.

      We designed Voxel Farm for any type of game world, not just large open worlds with lots of content in them. But these are maybe the most complex game worlds you can aspire to create, if we can do them well it provides a good idea of the range of the engine.

      Delete
    2. Wow, congratulations!
      It's absolutely seamless.

      What's your next big goal?
      (animation, l-system integration, more procedural integration)

      Delete
    3. There is a lot of room for improvement here. This technique relies on early occlusion culling, which can be improved. I will be covering this in the next post.

      The immediate goal is to bring all this into the Unity and Unreal Engine integrations.

      I'll keep a lid on the major big goals for now. Not making any promises, but we have a couple of really cool things going on at the moment.

      Delete
  2. Good stuff! For those of us who are impatient and can't wait for your next post, are you perhaps doing view-dependent deformation of voxel shapes prior to polygonalization?
    eg, if a chunk lies far away, primarily in the x direction, convert the voxels to long, narrow boxes that are fat in x and thin in y and z. It seems you could preserve one-pixel accuracy while still getting reduced distant geometry that way.

    ReplyDelete
    Replies
    1. It sounds an interesting idea, but we do not do anything like that. We do use a view-dependent criteria to remove complexity, there was a post a while ago about it: http://procworld.blogspot.ca/2016/02/improving-building-lod.html

      Delete
  3. Good stuff! Is screen space ambient oclusion also coming soon? I see you raytrace...? the shadows, but my point is the shadows are all the same intensity. Its all the same grey color, making the scene a little bit grey. maybe you can test a shadow technique where you count the length of the shadow ray and cast draw a darker shadow if the ray is short and more grey if the shadowray becomes longer. Its based on real life where the shadow of your hand close to the table is darker then the shadow of your hand far above the table. I think your scene would look much better and realistic that way. I think your scene has not as much depth if you understand what i mean, because the shadows all just make the scene more grey and less "dark". Do you understand what im saying and what do you think about the shadows.

    ReplyDelete
    Replies
    1. We do not raytrace. This is rendered using polygons and using traditional shadowing algorithms.

      We are working on global illumination solutions, but you could also apply any third party solution. In fact the second part of the video uses UE4's screen space ambient occlusion.

      Delete
    2. To clarify a bit more. When there is a large shadow, this shadow makes the scene dark. Say there is a large building blocking the sun then the townsquare is covered in shadows. But if there is a player on the towssquare, then there should be a second shadow coming from the player which makes the townsquare even darker. Your engine doest do this. when the player walks into a shadow his own shadow disapears into the shadow on the ground. This shadow isnt add up with the shadow on the ground. The ground just get the same darker output whether it has 2, 3 or 4 objects in front of him blocking the sun. Its the most notable when walking in a house, where everything has the same lighting. Everything looks as if there is no shadow at all. As if you used ambient lighting with a dark grey color. What do you think about this. Will this ever change or is this a technical limitation where you just stop raytracing the first oclusion you hit, assuming you raytrace the shadows, or something else?

      Delete
    3. I think it is important to think about shadows not as if they were stencils to darken the surroundings, but to think of light in general. The shade beside the trunk of a big leafy tree will be darker than the shade of a dead tree. This is because the sky itself is a light source, the more of that light source a given space gets the brighter it will be. Same goes for the shadow your hand casts. The further from your hand the more light will be shining upon the surface. Unless of course you are in a windowless room with a singular point source and black walls except for one... this last scenario will produce extremely detailed shadows even at a distance.

      Delete
    4. Yes, Global Illumination is thinking about light, how it bounces off objects and has its properties changed, like color. So far realtime GI methods are not very practical, but we'll get there. Meanwhile there are multiple degrees of hackery, like using screen-space ambient occlusion.

      Delete
    5. For realtime GI do they involve LOD and occlusion methods, or more importantly, can they tie in to what you are doing with your LOD methodology as seen above?

      Delete
  4. It appears that some of your geometry bounding boxes might be too small, as the screen clipping is happening too early on some polygons near the beginning.

    ReplyDelete
    Replies
    1. Very good guess. It is the frustum culling. It is testing using spheres and they all should be 1.4142135623730950488016887242097 times larger.

      Delete
    2. Well that was kind of silly now, hey! ;)

      Delete
  5. Is all of the LOD/decimation still done in a post-process as was described *hundreds* of posts ago?

    I was skimming the VoxelFarm docs on extensions and noticed that the voxels were positions without normals. While it made it a lot clearer how you get such smooth edit results (dodging DC's constant wobbly verts) and some of the nifty tools, sure left me baffled about how an octree could be collapsed with just that until I came across the farm/dispatch post.

    ReplyDelete
    Replies
    1. Surface mesh simplification happens in real time. The blog posts you mentioned are about Voxel Farm version 1, which was doing everything offline in a server farm. With Voxel Farm 2 and 3, this happens on the fly, often in the user's machine.

      For the LOD optimization described here, however, there is a new occlusion filtering that happens offline.

      Like you said, we do not store normals in voxels. The wobbly effect in DC is caused by the octree/mesh simplification. Since there is always an error threshold involved, you may have multiple surface configurations that meet this threshold. The more lenient you are with the allowed simplification error, the more allowed possible configurations you will have. Switching from one configuration to the next is what is perceived a wobbling.

      Delete
  6. I disagree. All videos so far show very noticeable LOD swapping. Not much in this one, only noticeable in the way shadows change. I suspect what isn't noticeable is the density. I doubt even rendering a scene with 4 times more triangles in each LOD would make much difference.
    Biggest LOD issues aren't related to geometry, like foliage getting reorganized here: https://youtu.be/LPWtNRkpqZo?t=2m20s

    ReplyDelete
    Replies
    1. Well this is the one video where we claim no noticeable geometry LOD popping. Like you say there are some noticeable swaps in illumination, but this is not coming from voxel content and it can be easily avoided. In fact, did you notice any of this in the second part of the video, which is using UE4 rendering?

      Vegetation LOD is managed by UE4, it depends largely on how you configure your assets. The particular pop in you linked in the video was caused by a bug in our instance tracking system, it is not really a LOD pop in. Note it is not the same objects changing LOD, this bug caused entire instances to disappear or appear. It has been fixed since.

      Delete
    2. Here it may be also illumination, hard to tell (mountains on the left): https://youtu.be/D6Uuoy4G-Dw?t=46s

      Delete

There was an error in this gadget