XNA Creators Club Online
Page 2 of 5 (105 items) < Previous 1 2 3 4 5 Next >
Sort Posts: Previous Next

Terrain LOD Again

Last post 8/12/2009 11:20 AM by csharp1024. 104 replies.
  • 5/26/2008 4:48 AM In reply to

    Re: Terrain LOD Again

    Why do you have to recreate index buffers each frame? And how does that help fix your problem?

    Not being able to display 1024x1024 at any given time should not be a big problem, with proper LOD and a quad-tree for view frustum culling, you can eliminate a good portion of vertices. Additionally, I use terrain scaling in the QuickStart Engine, and I noticed the newest Collision Sample with Normals from the XNA Team also uses terrain scaling. This means that a 1024x1024 terrain can easily be the size of a 4096x4096 terrain. The benefit here is that your farplane will now cull out many more vertices than before.

    I'm also confused why your code snipped has 'maxIndices' being given by MaxVertexIndex. I would think MaxVertexIndex would give you max Vertices, although I could be wrong. If your card supports index buffers larger than 16-bit, then it can hold many more indices than you'll likely ever use.

    Running the same code snippet I also get just over 1 million indices available. However, that means just over 1 million PER index buffer. Unless you're placing 1024x1024 in EACH index buffer, this won't be a problem. I've found quad-tree node sizes of 128x128 or 256x256 to be the most optimal. Anything smaller causes too much overhead on checking too many bounding boxes against the frustum, and anything too large causes too few triangles to be culled,

    XNA QuickStart Engine (3D Game Engine for XNA) | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 5/26/2008 10:44 PM In reply to

    Re: Terrain LOD Again

    It appears I didn't explain myself very well. Apologies. :)

    Lord Ikon:
    Why do you have to recreate index buffers each frame? And how does that help fix your problem?

    I don't recreate the index arrays: I put all the data in my precompiled index arrays (for each quadnode if leafnode == true) to a single array. My problem was caused by drawing 8 million primitives in one draw call, 7.9 million of which were 0,0,0. By creating a new array of the correct size and adding all the data to it, I only need to render the 100 000 or less primatives that are the result after the LOD is applied. When I finally get to frustrum culling, this number should halve again :).

    Lord Ikon:
    If there's a better way to do this (buffer objects?), let me know.Not being able to display 1024x1024 at any given time should not be a big problem, with proper LOD and a quad-tree for view frustum culling, you can eliminate a good portion of vertices.

    By doing this I eliminate a good portion of the indices, but the vertex buffer remains the same size. LOD takes good care of the indices: but unless I start modifying the vertex buffer, or using several of them, I'm going to suffer from software vertex processing.

    I've already implemented Terrain scale... it was a part of the project from the start. ;)

    QuadTerrain myTerrain = new QuadTerrain(Texture2D Heightmap, int LODSquareSize, float xyScale, float heightScale);  

    I only want large heightmaps for close detail (for people with supercomputers, like me :) ), and versatility (for people who get pissed off when a function doesn't do everything+1. Like me ;) ).

    Lord Ikon:
    I'm also confused why your code snipped has 'maxIndices' being given by MaxVertexIndex

    Whoops. That's just what Riemer posted: I fixed it when I ran my tests. I'm aware of what each of those represents. In reality, I used that one as maxVertices and the other as maxPrimitives (maxIndices/3).

    Lord Ikon:
    Running the same code snippet I also get just over 1 million indices available.

    Yay! My graphics card isn't defective! ;)

    Lord Ikon:
    However, that means just over 1 million PER index buffer. Unless you're placing 1024x1024 in EACH index buffer, this won't be a problem.

    Ah, that's where our misunderstanding was. I'm not performing a draw call on each index array: I've heard that draw calls take a lot of overhead, and so should be kept to a minimum (although I don't know how valid that is). Instead, I'm compiling them to a single array, which I then perform a single draw call on. Because I recently made this array dynamically resize itself, it's no longer a problem: the LOD takes the number of indices down drastically (although I'm still open to ways to do it better. I really need to look into buffer objects).

    I realise I'm going to have to use more than 1 index array if I ever get to rediculously sized terrains that the LOD can't keep up with (8192x8192, anyone?), but right now the vertex buffer is a more pressing problem: software vertex processing is evil. I've only had two idea's for that, and both sound difficult: either try to dynamically cut vertices out of the array based on the quadtree (compile it much the same way we compile the index array), or use a seperate array for every 513x513 square in the heightmap, as well as a another one for quadnodes above that size. That's 5 VB's for a 1024, 17 for a 2048, etc... but the dynamic idea re-arranges the indices, which has it's own problems...

  • 5/27/2008 2:06 AM In reply to

    Re: Terrain LOD Again

    I guess I'm confused on how you're getting this exact problem. If we have the same restrictions why haven't I ever ran into this issue with vertex buffers and 1024x1024 terrains? How are you ending up with 8 million primitives? 1024x1024 is around 1 million primitives correct?

    Draw calls do have some overhead, but the question is, is it any more efficient to create index buffers each frame than to make a few extra draw calls? I'm still curious about this software vertex processing, as far as I know I've never run into it.

    XNA QuickStart Engine (3D Game Engine for XNA) | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 5/27/2008 3:20 AM In reply to

    Re: Terrain LOD Again

    I'm not sure why I put 8 million primitives. Even adding all the primitives for all the quadnodes and taking into account that it might have been refering to indices doesn't result in that many ... I'll go home and re-run that algorithm... let you know tomorrow.

    Lord Ikon:
    Draw calls do have some overhead, but the question is, is it any more efficient to create index buffers each frame than to make a few extra draw calls?

    Well, I'm only creating the one index buffer/array/thing from all the smaller ones... but in reality, I don't have any idea. Using CopyMemory rather than CopyTo should speed things up when I get around to it, but I was just running on the assumption that draw calls are bad. I'll try rendering each node-buffer in sequence, and see whether that affects my FPS...

    Lord Ikon:
    I'm still curious about this software vertex processing, as far as I know I've never run into it.

    Read the tooltip underneath MaxVertexIndex. I can't remember the exact wording, but I believe it says something similar to"This is the maximum number of vertices that are supported by hardware vertex processing".

    Since when I use more than that number in a single Vertex buffer in a single DrawUserIndexedPrimitives my computer lags awfully, I assumed it was caused by what I termed "Software Vertex Processing".  I didn't have the FPS counter when I last tried it, but I'd say it dropped to around 10 FPS .I suppose it could be caused by something to do with my quadtree, but I tried increasing the LOD square size (which is a good way to free up more CPU) and nothing changed.

    Thanks for all the help, by the way. I couldn't have got this far without it.

  • 5/27/2008 6:41 PM In reply to

    Re: Terrain LOD Again

    No problem at all. :)

    I was under the assumption if you went past the amount of supported vertices you would either crash, or fail silently, which would cause you not to see anything.

    For example, 0.182b of the QuickStart Engine doesn't support 16-bit index buffers, which means if you use an older card that only has 16-bit index buffers you will crash when trying to run it. However, I've never tried going past the limit on a card, so I can't say exactly what will happen.

    I too get an extremely low framerate at 1024x1024 if I'm displaying the entire terrain at full LOD, but that is because I'm displaying over 1 million polys per frame just for terrain, so that is somewhat to be expected IMO.

    XNA QuickStart Engine (3D Game Engine for XNA) | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 5/27/2008 9:54 PM In reply to

    Re: Terrain LOD Again

    Lord Ikon:
    I was under the assumption if you went past the amount of supported vertices you would either crash, or fail silently, which would cause you not to see anything.

    Apparently not. Here's the exact wording of the tooltip unde MaxVertexIndices: "Gets the maximum size of indices supported for hardware vertex processing". Hence my invention of the term "software vertex processing".

    It sort of makes sense: If the GPU can't handle more than 1 million vertices in a buffer, and XNA is aware of this fact, it can automatically shove the processing onto the CPU rather than risk a crash.

    Of course, that might well be a load of sh**, but it fits the evidence. ;)

    Lord Ikon:
    I too get an extremely low framerate at 1024x1024 if I'm displaying the entire terrain at full LOD, but that is because I'm displaying over 1 million polys per frame just for terrain, so that is somewhat to be expected IMO.

    Well that no longer applies to my solution: the dynamic LOD takes care of it. Despite this it still suffers the worst lag I've had since I tried to run STALKER on my old computer (that was hilarious :D).

    I checked that stuff I said I'd check, so I'll got through them in order:

    First: 8 million primitives. Should have been 8 million indices... I believe the logic behind it was putting the indices from the root node in, then the indices of the childnodes, then the indices of their childnodes, and leaving non-rendering quad nodes and strings of 0's in compilation. The value was calculated like this:

    allIndices = new int[allQuadNodes.Count * ((squareSize - 1) * (squareSize - 1) * 6)]; 

    In any case, it's no longer relevant: the allIndices array is created after it is decided which quadnodes will render. :)

    Second: I underestimated how much my computer lags when I suffer "software vertex processing". 3 FPS, and that's being generous.

    Third: Comparing "Draw-Each-Node" methodology to "Compile-into-single-index-buffer" methodology. This test gained me one of the strangest results I've ever seen.

    The easy one first: Draw-Each-Node. At LOD 5 we get a steady 60FPS. By the time we hit LOD 7, we're down to 40FPS. It keeps dropping in this fashion: 30FPS @ LOD 9 and 20FPS @ LOD 12.

    Now the strange one: Compile-into-single-index-buffer. Like the previous one, it's 60FPS at LOD 5, and drops to 40FPS at around LOD 7. Then, it does something strange: at LOD 9 it's gone back up to 60FPS. What's even stranger: it hovers at 60FPS until you get to a massive LOD of 25! O_O

    Very confusing, but not entirely unpleasant: at least it means compiling into a single array was a good choise. And I'm still using CopyTo()... if I use the CopyMemory function, I'm told it will be several times as fast. ^_^

    Forth: I noticed a strange feature in the version I uploaded, but only just worked out what it is. When you set the view mode to "Point", move to the centre of the map and look back towards where you started (0,0,0), you can notice a significant frame rate drop. I've worked out that this is because of all the 0,0,0 primitives being rendered. I can only assume that they don't affect it in solid mode because of being cut out by the Z-Buffer... or it's possible that in solid mode they're being cut out by the GPU, and are not rendered at all. Given the nature of it though, it no longer applies: dynamic index arrays solved a whole bunch of problems at once! Hooray!

    Also, on the subject of Vertex Buffers, I've been holding a very similar conversation with Riemer on his forums: http://www.riemers.net/Forum/index.php?var=1196&var2=0. Some of the stuff he's mentioned has been very helpful, so I thought you might like to take a look. :)

    Cheers!
    Quasar.

  • 5/29/2008 5:11 AM In reply to

    Re: Terrain LOD Again

    So, I would recommend putting timers around all your major functions within the program. By 'major' I mean the ones doing the brunt of the work. If you get get details on how long the bounding box checks for the quad-tree nodes are taking, how long re-creating the index buffers is taking, how long calculating dynamic LOD stuff is taking, etc...., then you could find what your major bottleneck is. Up until now the results seems to be fluctuating based on various variables, it would be nice to narrow the problem down slightly.

    If I remember right Shawn's blog said something about not simply being able to time a Draw call because the GPU is asynchronous from the CPU. But if you can time everything else, you can figure out the time you're waiting for GPU. For example, if the bulk of your processing on the CPU is taking 20ms, than even with no rendering you'd only be getting 50fps maximum. So if you're taking up 20ms on the CPU side, and getting 25fps, then you know your draw and waiting for GPU is taking around 20ms as well. You don't need to get exact results overall, but I recommend the timers just to narrow down what might be causing your bottleneck.

    I recommend reading Shawns blog on determining your bottleneck. If you are indeed GPU bound, you might not know if it is vertex or pixel limited, or a number of other factors. For example, does your framerate change at all when your window size if much smaller? What about the shader, if the pixel shader very simple? Just throwing out some ideas.

    Oh, and I posted some stuff on your thread at Riemer's site if you want to read it, I'm too lazy to cut and paste it here. :)

    XNA QuickStart Engine (3D Game Engine for XNA) | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 5/29/2008 9:35 PM In reply to

    Re: Terrain LOD Again

    I'm sort of jumping backwards and forwards between the thread on Riemers forum and this one: both threads are providing me with invaluble information. I'm actually typing both posts at the same time. :lol:

    Timers are a good idea... I've just been too lazy to implement them before this. I'll check out Shawns blog, see what he has to say on the subject, and then set them up. Today's Friday, so I'll have a good amount of time to work on it after today.

    Ctrl-V

    It's funny, I seem to have got hung up on something that should be very simple: Frustrum checks.

    I've set them up, creating bounding boxes and a bounding frustrum, and then telling the array compiler to not add them to the master array if they're outside the view frustrum.

    And I keep seeing quads not being rendered out of the corner of the screen.

    *
    I've just had a thought that this might be caused by my recursive algorithm: maybe the parent quads aren't being rendered because the child ones don't tick off against the frustrum. It's an easy thought to check... I'll let you know how it goes. Don't let that stop you from posting If you've seen this problem before :).
    *

    Also: The weird thing I mentioned with framerate and LOD previously. I further defined it: The framrate drops steadily as you add primitives, down to about 30FPS. Then, when you hit 88000 primitives (no matter the LOD), it suddenly jumps all the way back to 160 FPS.
    With luck, timers will help me identify what's causing this...

  • 6/2/2008 1:59 AM In reply to

    Re: Terrain LOD Again

    Another forum Terrain LOD blog update. ;)

    I didn't get to work much on this over the weekend - had a life to attend to. Nonetheless, I managed to find a little amount of time for the things that are truly important...

    Frustrum Checks: No longer a big deal. It turns out I was defining the Quadnode bounding boxes as min(0,1,0)max(1,0,1) as opposed to min(0,0,0)max(1,1,1). Stupid me.

    I used Stopwatch objects as timers to work out my performance: here's the approximate results (quoting from memory here for reasons given at the bottom of this post, so bear with me... )

    Re-Initialise Array: ~10-12
    LOD Distance Checks: 3-4. (recursive)
    Frustrum Culling: 30-40. (currently not recursive, but only act on Nodes selected by the distance checks)
    Stitching: 3-4 (only acts on nodes selected by distance checks)
    Compile to Single Array 50-150.

    The Draw Call: 500-3000 depending on number of polygons.

    You know that strange thing I mentioned before: >88000 primitives = massive framerate jump. Well, it turns out that that jump is entirely contained within the Draw call: it goes from 3000 to 500 at 88000 primitives, changing FPS from 30 to 160. None of the other timer values change. Does anyone know why?

    Finally, the reason I'm forced to quote from memory: halfway finished multiple vertex buffers. Like everything else, I'm making these dynamic: the user can set the Vertex Buffer Size when they make the terrain. I've finished the vertex creation stuff: vertices are added to the correct array depending on their position (buffer edge vertices are added to more than one array). Now I need to incorporate this into the indices... which means adding a usedBuffer value to each Quadnode and somehow getting the creation, stitching and selecting of indices to use this value.

    Should be fun.

  • 6/18/2008 1:27 AM In reply to

    Re: Terrain LOD Again

    Hmmm... well, it's been a while (I've been posting elsewhere), but I have results to report!

    Multiple Vertex Buffers: After some fun with Windows Vista, I finally got these working. Something about my indices caused the problems, but once I found the bug and aligned them correctly it runs fine. I even ran a 2049x2049 terrain with a 20,000 far clip plane! (albeit at 10FPS, but there you are...)

    Somehow, the above sentence doesn't seem to capture the annoyance, the migranes, the permanent mental scars and the sheer frustration of not being able to debug my program because every time I did I got fun. Oh well...

    Anyway, that's no longer relevant because it works now, and I'm sharing the source code.

    It's not anywhere near finished: I still need to finish the comments, add a number of 'ease of use' methods, optimise a whole heap of stuff and basically make it better in every concievable way... but I thought I'd see what people thought of the prototype.

    Cheers!
    Qu.

    BTW: If you have any suggestions for improvements, additions or modifications, or have found errors or just things that could be done better (performance wise), let me know!

  • 6/23/2008 3:13 PM In reply to

    Re: Terrain LOD Again

    Hi

    I can humbly offer you the LOD implementation of BetaCell; it's not using quadtrees, I may consider adding that in the future. It has a tutorial on how to use it too.

    www.betacell3d.com


  • 6/23/2008 10:17 PM In reply to

    Re: Terrain LOD Again

    That's a very cool project! It actually reminds me a bit of Blitz3D, except done for XNA. Good work!

    I'm downloading it, and I'll take a look when I get home. I'm particulary interested in this statement on your home page:

    peacefulshade:
     BetaCell can divide the map into parts to do effective frustum culling and also sorts the parts in a front to back order before drawing to save fill rate.

    I don't do sorting at the moment, so I'll take a look at your code and see if I can't steal... err... "learn from" some of your ideas. :D

     

    In other news: I've started on the terrain shader. I understand that some people will want to use their own terrain shaders, so I'm still making the class versatile enough to quickly change shaders, but I'm adding some features to my shader that make it look better.

    One feature, which I thank jwatte for, is the idea of using a global normal map to set the normals, rather than a per-vertex system. This means that the distance LOD only affects the shape of the terrain, and not the lighting. I implemented this last night, which I think is quite impressive given that I had never used HLSL before 2 days ago. Thanks Riemer!

    Anyway, here's the result.
    The image on the left is 'before': using vertex normals. The image on the right is 'now': using textured normals and shader trickery. Note that the actual geometry in both images is identical. (Well, almost identical. The viewpoint is a bit off, so the frustrum is culling an extra quadNode on the second image (hense the different 'rendered indices' counts). The visible geometry in both images is identical, anyway. :)

  • 6/24/2008 2:00 PM In reply to

    Re: Terrain LOD Again

    By basing the texturing and/or normal mapping on a texture sampler at the per-pixel level rather than the per-vertex level, you can maintain full texture quality at any LOD. This is currently how it is being done in the QS Engine terrain. I've seen games like World of Warcraft do it as well. The only downside is that it requires extra texture lookups, which some older cards will hate, but not storing texture coords in each vertex saves on memory as well.
    XNA QuickStart Engine (3D Game Engine for XNA) | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 6/24/2008 5:12 PM In reply to

    Re: Terrain LOD Again

    Hey Qu,

    Your making some serious headway.  I've been following this thread for awhile and you finally got me interested enough to take a peek at your code. 

    But the past few times I've tried, your free file host's site is down. 

    I'm really curious how you have handled the LOD side of things, because I'm about to finally try my own hand at it. 

  • 6/24/2008 9:59 PM In reply to

    Re: Terrain LOD Again

    Lord Ikon:
    By basing the texturing and/or normal mapping on a texture sampler at the per-pixel level rather than the per-vertex level, you can maintain full texture quality at any LOD. This is currently how it is being done in the QS Engine terrain. I've seen games like World of Warcraft do it as well. The only downside is that it requires extra texture lookups, which some older cards will hate, but not storing texture coords in each vertex saves on memory as well.

    I'm sort of confused about your last sentence, Lord Ikon. Did you mean "not storing normals in each vertex saves on memory as well."?

    Oh, that reminds me: Texture Coordinates. I've decided not to bother storing these in vertices either. I can just calculate them from the x,z position of the vertices in the vertex shader. :)

    gorky:
    Hey Qu,

    Your making some serious headway.  I've been following this thread for awhile and you finally got me interested enough to take a peek at your code. 

    But the past few times I've tried, your free file host's site is down. 

    Oh noes! I hate file hosting sites... Got any idea's as to where I can upload the zip file?

    gorky:
    I'm really curious how you have handled the LOD side of things, because I'm about to finally try my own hand at it.

    I suppose that's the brilliant thing about a quadtree: every quadnode, no matter the depth, can be represented by a square grid of vertices. The deepest quadnodes have one vertex per pixel, the next ones up have one vertex for every 2 pixels, the next ones have one vertex per 4 pixels, etc... Image.

    So it becomes the more simple matter of choosing which quadnodes to render, as opposed to choosing individual vertices.

  • 6/24/2008 10:40 PM In reply to

    Re: Terrain LOD Again

    I just realised I hadn't been keeping this thread up-to-date with some of my progress in between the 17th and the 23rd, so here's a brief summary:

    • Flat area's. Some area's don't need lots of tiny polygons. When I originally decided to take this into account, I had meant to make these area's be represented by rectangles which spanned more than one line. I decided that this had three disadvantages: it would be a huge amount of extra work, would increase the terrain load time and most importantly didn't decrease the polygon count in many cases. So instead, I went for the flatstrip method (see image), and spent ages ensuring that gap artifacts that wont be generated.
    • Performance increase. I changed from DrawUserIndexedPrimitives to using static VertexBuffer's and DynamicIndexBuffer's. Read the linked thread to see the result. The extra work was well and truly worth it.
    • New source code. This is the *geo only* version: no fancy shader trickery here, although it does generate a global normal map for you. If you can't download it, let me know where else I can upload it!
  • 6/25/2008 3:08 AM In reply to

    Re: Terrain LOD Again

    I meant not storing texture coordinates. There might be a way to not store normals per vertex, but you'd have to calculate normals in the shader based on a texture sample or something.

    If you want accurate normal mapping you have to calculate tangents and bitangents and pass them into the shader somehow, presumably in the vertices. Using a hard-coded normal for terrain, like the world UP vector, will "work" well enough in cases where a vertex's normal is close to the world UP anyway, however on any steep areas of terrain that won't work properly.

    EDIT: I should mention that part of a hard-coded normal would also mean a hard-coded tangent/bitangent. Technically you don't have to hard-code the normal, but a hard-coded tangent and bitangent wouldn't work well without a hard-coded normal for normal mapping. Also, a "hard-coded normal" would only apply for normal mapping, the calculated normal stored in the vertex would of course still be needed for lighting.

    On another note, good work on the terrain stuff so far. Can't wait until you get some working downloads to take a look at this. :)

    XNA QuickStart Engine (3D Game Engine for XNA) | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 6/26/2008 1:58 AM In reply to

    Re: Terrain LOD Again

    Lord Ikon:
    I meant not storing texture coordinates. There might be a way to not store normals per vertex, but you'd have to calculate normals in the shader based on a texture sample or something.

    Uh... that's exactly what I'm doing with the shader.

    I'm very confused all of a sudden...  :)

    As of today, my shader looks like this image. I'm only storing position in the VertexBuffer: Texture Coordinates are derived from the x/z values of the position and normals are given to a Global Normal Texture, which is rendered in the pixel shader across the entire terrain.

    The Detail Normal Texture is added on top of this in the pixel shader with vector addition.

    I've started on multi-texturing (with 4 diffuse colours & 1 blend texture), and have been considering geo-morphing: but all the ways I can thing of to do Geomorphing will require a DynamicVertexBuffer, which either contains a geomorph "Translation value" or simply suffers direct modification of the position value...

    I'll need to see how much of a performance hit changing to a DynamicVB will cost me... hmmm...

  • 6/26/2008 4:36 PM In reply to

    Re: Terrain LOD Again

    I see what you're saying. I guess if you use a texture for your normals that is fine. I could never do that with mine, after I import the image I then smooth out the terrain, which changes the normals of all the verts. If I used an texture for normals then I'd have to create it after the terrain smoothing occured. And to be honest the normals aren't taking up too much data in the vertex buffer for me so it is no big deal. However once normal mapping occurs I will need to store tangents and bitangents in the vertex buffer, which changes things up a bit, effectively doubling the size of the vertex buffer.

    None of your image links are working for me still, just a heads up on that.

    I would imagine that using a texture sampler for calculating normals has some overhead to it. So it starts to become a question of memory usage vs. GPU time, and which you need more. To many texture lookups can become costly, especially on older machines, it may be a good idea to test on an older computer to make sure your stuff runs.

    XNA QuickStart Engine (3D Game Engine for XNA) | My site
    "I'll be whatever I want to do!", Philip J. Fry
  • 6/26/2008 6:32 PM In reply to

    Re: Terrain LOD Again

    the normals aren't taking up too much data in the vertex buffer for me so it is no big deal

    12 MB for a 1024x1024 isn't a lot of memory? A DXT5 compressed normal map would only use 1 MB for the same coverage.

    Anyway, you don't need tangents and bitangents, or even vertex normals. I generate a world-space normal map in the content processor for height maps, and apply it directly. If you still need tangents and bitangents, if it's a normal heightmap with regular U/V coordinates, you can easily derive the tangent basis by crossing the normal with global "right" to get the bitangent, and cross bitangent with normal to get the properly slanted tangent.

    That can then let you apply a detail normal map, if you're really ambitious :-) Because the larger normal is already baked into the tangent frame of the detail normal map, you don't need to blend the normals, just use the final normal that comes out.

    Jon Watte, Direct3D MVP
    Tweets, occasionally
    kW X-port 3ds Max .X exporter
    kW Animation source code
  • 6/30/2008 12:32 AM In reply to

    Re: Terrain LOD Again

    Lord Ikon:
    None of your image links are working for me still, just a heads up on that

    Weird. You're correct: I get a 404 google error when I click them. The URL itself works fine though: I can right-click on them, triple click the URL to select it, and copy-paste it into the Address bar, and it works perfectly fine.

    I wish I had a better option than storing them on my blog, but until now it's been more reliable than any image hosting site I've tried.

    jwatte:
    Anyway, you don't need tangents and bitangents, or even vertex normals. I generate a world-space normal map in the content processor for height maps, and apply it directly. If you still need tangents and bitangents, if it's a normal heightmap with regular U/V coordinates, you can easily derive the tangent basis by crossing the normal with global "right" to get the bitangent, and cross bitangent with normal to get the properly slanted tangent.

    That can then let you apply a detail normal map, if you're really ambitious :-) Because the larger normal is already baked into the tangent frame of the detail normal map, you don't need to blend the normals, just use the final normal that comes out.

    Cool. I think I finally understand what you're saying. My current version (see below) is a little too simple... the detail normal 'pulls' the global normal upwards rather than offsetting it.

            //Get global normal Texture  
            float3 Normal = tex2D(NormalSampler, input.TextureUV);  
            //Format global normal Texture  
        Normal[0] -= .5;  
        Normal[1] -= .5;  
        Normal[2] -= .5;  
        Normal = normalize(Normal);  
          
        //Get Detail Normal Texture  
        float3 detailNormalMap = (tex2D(DetailSampler, input.TextureUV*100/detailScale));  
            //Format Detail Normal Texture  
        detailNormalMap[0] -= .5;  
        detailNormalMap[1] -= .5;  
        detailNormalMap[2] -= .5;  
        detailNormalMap = normalize(detailNormalMap);  
          
            //Combine the two normal textures  
        Normal = normalize((Normal*2)+(detailNormalMap*detailMapStrength)); 

    I think I'll incorporate both versions into the shader (seperate them with an if statement), and let the user pick which one to use by setting a boolean.

    In other news (I hope this link works) I worked out multi-texturing.

  • 6/30/2008 12:48 AM In reply to

    Re: Terrain LOD Again

    Qu:

    Lord Ikon:
    None of your image links are working for me still, just a heads up on that

    Weird. You're correct: I get a 404 google error when I click them. The URL itself works fine though: I can right-click on them, triple click the URL to select it, and copy-paste it into the Address bar, and it works perfectly fine.

    I wish I had a better option than storing them on my blog, but until now it's been more reliable than any image hosting site I've tried.

    blogger.com dont want people using their bandwidth so my guess is that they are checking the referrer and 404ing any other site. You should make a blog entry with all the links in it and then just post the link to that blog entry. That will work.

    Play Kissy Poo - a game for 4 year olds on Xbox and windows
    The ZBuffer
    News and information for XNA
      Follow The Zman on twitter, Email me
        Please read the forum FAQs - Bug/Feature reporting
          Don't forget to mark good answers and good playtest feedback when you see it!!!
  • 7/2/2008 1:00 AM In reply to

    Re: Terrain LOD Again

    skytigercube:
    have you thought about:

    project a screen space grid onto terrain plane

    giving XYZ in world space and XY in terrain coordinates

    vertex shader sets XY position and looks up Z using XY coordinates from heightfield texture

    that gives you LOD for free with no holes to patch up

    and the only data loaded into the GPU is a small grid and a heightfield

    I thought of doing something like this awhile back.  I thought it was a outstanding idea when I came up with it.  Then I realised how I would have to convert to vertex shader version 3 to make it happen. :(

    I really like the possibility of having no holes to patch up, with LOD.  I'm assuming this is because you are looking up the y (height) on the texture map, therefore no matter what differing (simple/complex) grid you send to the card, there will be no gaps.  Correct?

    It seems like you would still have holes: if you had one 256x256 screen space grid, next to a 128x128 screen space grid, I still think that holes would appear.

    But if you had 1- 256x256 and 9 -128x128 versions (Stiched edges) then it would work.  It would also seem to cut down on the amount of data being sent to the graphics card to boot! (Not too mention resident in memory)

  • 7/2/2008 4:45 AM In reply to

    Re: Terrain LOD Again

    Hmm... I thought I understood SkyTigerCube's suggestion for a second there... but I've fallen back into confusion.

    How is it meant to provide LOD?

  • 7/2/2008 6:21 PM In reply to

    Re: Terrain LOD Again

    I cannot speak for skytigercube, but this is how I envisioned my own idea would work (Untested, Uncoded, Unproven):

    You have your standard partitioning mechanism in place (e.g. QuadTree)  But instead of storing the vertex buffer(s) and index buffers per node, you just store offset values.  So the first leaf node would have values of 0-0.  The next node might have 255-0 if your working with 256 sized patches.  These are values sent to the card as shader variables vs. data in channels in the vertex definition.

    The vertex buffer is a simple 256x256 with just positional data.  Ideally, if it can just be x,z without the y values, would be best.

    The index buffer has values of 1-256x256, 9-128x128, 9-64x64, etc...  These values represent the differing lods.  They are all packed into the single index buffer.  The draw function sets the lod index offset, based upon the nodes current lod.

    In the shader, each vertex position is set with the real terrain values.  The x & z come from the current offset value, combined with the vertex data from the channel.   E.g. in the 255-0 case for vertex 13-4 would become 268-4.  The y value would come from the texture lookup on the heighmap.

    All other data would come from texture lookups.  Normal map, light map, texture splat, detail texture splat are some examples.

     

    The draw backs to all this are:

    • You have to use shader model 3.
    • You cannot remove flat terrain like your implementation (of which I admit I don't understand)
    • More texture lookups (I'm also not too sure how fast vertex texture lookups are)
    • Slightly more complex vertex shader.  This will possibly be a preformance hit .

    But the benefits are:

    • It might be possible to combine this technique with instancing, to utilize just one draw call for all patches of same lod
    • Just one small vertex buffer and a medium sized index buffer (No switching needed.)
    • Smaller memory footprint of said data (better for XBox)
    • Because the height values come from a texture, deformable terrain might be easier via render to texture.
    • While the vertex shader was more complex, the CPU code will be less complex. (CPU speedup)

     

     

Page 2 of 5 (105 items) < Previous 1 2 3 4 5 Next > Previous Next
var gDomain='m.webtrends.com'; var gDcsId='dcschd84w10000w4lw9hcqmsz_8n3x'; var gTrackEvents=1; var gFpc='WT_FPC'; /*<\/scr"+"ipt>");} /*]]>*/
DCSIMG