This project is read-only.

Questions: Terrain/Shadow

Jan 18, 2012 at 6:03 PM

Hi, great stuff, just a few questions! For reference, I am using your latest build.

First, I've seen in another thread that you are waiting on finishing some material work before addressing cascaded shadow maps - my current fix for this is to use a moving orthographic light source that is clamped to the close half of my camera frustum - this allows me to get slightly higher shadow resolutions at the expense of not shadowing those items that are further away. This is obviously not great, but gets by - are you still considering cascaded maps?

Also, in order to do that, I loop through each model/mesh/part and set the effect parameter "ShadowMap9_LightViewProjection" to my new matrix every update. Is there a way to set it each frame through some "foreach IEffectShadowMap in model.GetEffects();" similar to changing textures?

Next, because it is (far) easier to convert Nine to Y-up than it is to convert Bepu's character controllers to Z-up, with each build, I run through and swap some of Nine's X/Y to make it work - 5 minutes time, no hassle. However, I am just getting to incorporating terrain and see that Nine's copy is very specific to Z-up. 1) Is there a way to rotate DrawableSurface along a particular axis? Transform does not seem to rotate them. If not, I would create a Y-up copy of your heightmap class - if that were converted to Y-up, would any other classes using it need to be adjusted, or does Heightmap.cs set the vertex positions in space? When loading a DrawableSurface such as terrain, can the bumpiness be set in any other location other than the processor?

Last questions :) Can you clarify these items concerning drawable surfaces. step: larger the value, greater distance between vertices? SegmentCountX/Y - appears to do the same as step, but along specific axises. PatcheSegmentCount: ? And finally, in your terrain samlple, "terrain = new DrawableSurface(GraphicsDevice, 1, 16, 16, 8)" loads a specific heightmap, but it is never specified - where is it getting the heightmap content?

Sorry for all the questions! I've spent the last month working with and tweaking my local copy of the code, and these components are new to me, so lots of questions :)



Jan 18, 2012 at 9:11 PM

Also, while waiting for a response, I started converting the terrain to YUp just to test and came across this comment:

// Step 2: Calculate all edge vectors (for normals and tangents)
// This involves quite complicated optimizations and mathematics,
// hard to explain with just a comment. Read my book :D

Which book is that? Thanks!

Jan 19, 2012 at 4:42 AM
Edited Jan 19, 2012 at 4:45 AM
-- are you still considering cascaded maps?
Yes, but it is not my top priority at the moment. I'm working on a top down game, so this shadows technique suffice.

-- Is there a way to set shadow effect parameter?
You don't need to set the effect parameter directly. Use Material.Find<IEffectShadowMap>() instead. The detailed code can be found in the ApplyShadows and ApplyShadowMap method in Scene.cs, it loops though all the drawable objects in the view frustum and assign the correct parameters for the materials used by each object.

For the axis problem, the short answer is no you cannot rotate the terrain. Several problems,
1. ISurface interface requires the axis to be Y up in order to work, but you can ignore that if you don't use that interface for movement.
2. The rendering system requires the bounding box of each terrain patch to be calculated correctly. Make sure you have set up the correct bounding box while converting the axis.
3. Be aware of the ray casting methods in DrawableSurface, it also rely on the axis.

There are lots of comments about this axis choice, hopefully I may have the time to convert to the standard Y up representation in the coming weeks.

-- When loading a DrawableSurface such as terrain, can the bumpiness be set in any other location other than the processor?
The Heightmap contains raw heights, you can adjust them manually using LoadHeightmap method.

-- DrawableSurface terms:
A terrain is build from heightmap, each pixel in the heightmap corresponds to a vertex in the terrain. Each adjacent 4 vertices creates two triangles that forms a square segment (or cell, block).
Step is the size (width & height) of this square cell in world space, so the larger the step is, the bigger the terrain is, but it does not affect the bumpiness.
SegmentCountX/Y is the count of the segments along x or y axis, it is equal to the width/height of the heightmap texture minus 1, since the border vertex doesn't count.
A large terrain may contain more than 1000x1000 cells, render all of them every frame is not ideal for performance, so the terrain is divided into square patches. The number of segments that a single patch covers along the x axis is called PatchSegmentCount and that value has to be an even number. The whole terrain is rendered patch by patch, so if a patch is outside the view frustum, it will be culled.

"terrain = new DrawableSurface(GraphicsDevice, 1, 16, 16, 8)" is a shortcut for creating a pure flat terrain.
"terrain = new DrawableSurface(GraphicsDevice, Content.Load<Heightmap>("MountainHeightmap"), 32);" loads the specified terrain from heightmap.

Finally, that book thing... is I grabbed the normal calculation method from "The racing game" sample on the xna creator's club without deleting that comment.
Jan 20, 2012 at 3:44 PM
Edited Jan 20, 2012 at 3:55 PM

Thank you very much for the detailed explanation! I did end up converting the heightmap to Y-up axis and everything worked fine - picking, movement, etc - all told, it took about an hour and worked well with my Y-up cameras/movement in Bepu. The only problem I encountered and could NOT fix was the normals were reversed - in other words, the BOTTOM of the DrawableSurface was textured. Reversing normal calculation in the CalculatePositionsAndNormals did not fix the problem and I was stumped for a while. Eventually, I found that setting rasterizer state to Fill and changing the blend mode gave the exact same results as drawing the DrawableSurface.

However, I'm not looking forward to changing that with each change set and it felt too much like a hack, so for now I'm not going to do that and will do without terrain :) At least I understand the code thoroughly!



Jan 21, 2012 at 4:23 AM
Can you upload a patch for the up axis conversion? I will help with the normal caculation and made Y the standard up axis in the future. Thanks :)