Friday, June 20, 2008

Terrain and Atmospheric Scattering Source

I figured I would release my source for the terrain rendering demo. There aren't that many terrain and atmospheric scattering examples on the net, so I figured I might as well post mine for anyone that would like to see it.
It's still a work in progress (that I paused about a year ago), so it's kind of immature. But it is the same code that produced the images I posted awhile back. You'll probably need at least a 6 series Nvidia graphics card (or ATi equivalent). For the terrain, the demo uses a simple quad tree with frustum culling, so it's not the greatest performer for anything above 512x512 heigtmaps. Also, it is in Managed DirectX, but it shouldn't be too hard to port to XNA.

Anyway, enough of that. If you didn't know, the Creature Creator for Spore has been released, and it's an absolute blast to mess around with. The possibilities on what you can create are pretty much endless. Here's a couple that I made:


Charles Humphrey said...

LOL, as expected the demo does not play well with my crappy laptop...shame, would have been cool to see it running on my machine :(

Thanks for the source though, I am sure it will be an interesting read.

Kyle Hayward said...

D'oh! Where's it failing? Maybe I can get it running :)

--Making these compatible for older cards is kind of fun

Charles Humphrey said...


Well it is running, it's just that a few of the methods in the Draw call are very, very slow like 5+ seconds to complete, so the form never seems to get populated.

I will try and narrow this down and give you a list of where it is not playing well with my system.

Pitereeek said...

Hello. First I want to say Great Job!!! Effect is great. Better than water in many actual games. Right now I'm trying to move it to XNA 2.0

Effect is perfect but it has one issue. If you are at very low attitude just above water. You will see it:). Is it possible to fix that somehow because it is destroying perfect view of this project and it is making him useless and many situations.

Kyle Hayward said...

The way to fix the problem you're talking about is to make the spacing of the water grid very small. In SceneSetup, change the dx, dy parameters of the WaterInfo struct to .5f, and that will alleviate the problem.

But then you'll need a water grid with more vertices.

For my purposes, the 5.25 spacing worked well enough for me.

Pitereeek said...


Thank for your advice.

I still can't get your shader working properly in XNA.

I think that it can be caused by the different in coordinate system.

From what I now Direct3D's left-hand coordinate system and XNA's right-hand coordinate system.

So view and viewprojection matrix is different.

Did you tested maybe your shader in XNA or do you know how it is possible to fix that?



Kyle Hayward said...

I have not tested in XNA, but the difference between the LH coordinate system and the RH coordinate system are just how the matrices are built. The view and projection matrices basically just look the opposite direction in a RH coordinate system.

The shaders are pretty complex, so if you don't set something up right, the whole effect can be thrown off.

What problem exactly are you having? Maybe you could post a link to a build of your XNA version?

Pitereeek said...

Subdividing my plane to many triangles fixed displaying problems.

Probably I have to find different shader because this one need a lot of triangles. Most of shaders on the web need only plate build from 2 triangles.

Thank You

Endri said...

Hi there! Really GREAT work there, better than many commercial games' water! I'm trying to port this to Irrlicht 3D engine but with no results yes. I'd like to aska couple of questions if that's not a problem,

1st, For the water effect, only the water.fx shader file is needed ?

2nd, i'm passing to the shader through my app the following variables, the 2 matrices ( gWorld, gWVP, gEyePosw, gSunDir,gWaveNMapOffset0, gWaveNMapOffset1, and gSunColor. But no desirable result till now, Am i missing something in the process ? the 4 texture layers i'm using is, ( layer 0 and 1 ) and the refraction map and the reflection map ( layer 2 and 3 ).

Congratulations again!

Charles Humphrey said...

Kyle, sorry for the delay, been very busy (mostly with my clouds lol)

The delay is in the terrain render, takes an absolute age to draw the terrain and as it does it quite a few times per draw call it just kicks the crap out of my laptop.

Anychance you could do a trimmed down version?? I might just try and hackout the terrain and just see the water.


Kyle Hayward said...

Hi endri,

It looks like you're passing in all the required data. What problem are you having specifically?

Are you making sure that the reflection and refraction maps generate correct results? The reflection map should basically be the scene rendered upside down, and the refraction map should be the scene rendered as normal.

Also, the water shader does use data generated in the refraction pass. In the refraction pass I store the distance from the water plane to the height of the terrain in the alpha channel, and then in the water shader I use this value to smoothly interpolate the water edge to produce soft water edges:

finalColor.rgb = lerp(finalColor.rgb, refraction.rgb, 1 - refraction.a);

I'm not sure if this is part of the problem, but look in HoffmanUnderWaterTerrainPS in the Hoffman_Preethem.fx to see how I do this.

Kyle Hayward said...

Hey Charles,

The whole quadtree and frustum culling works great for 1024 and above heightmaps but is probably over kill on the 257 that I set as the default.

What I think I'll do for ya is rip all that out, generate a 129x129 heightmap and just brute force it. I might also take out the multi-texturing, this might also be killer on your video card.

Might be a couple of days before I can get it out.

Endri said...

Hi Kyle,
There was a small issue with the reflection map but that's not a problem it's a 5' work. The only issue is that i don't get the color changing of the water, from transparent to light green to deep blue as the water gets deeper. Maybe I should look at the scattering effect shaders ? ( Hoffman ). I would also like to say that the specular spot of the sun is not present, but i guess that will automatically be solved with the corrected reflection map. Thank you for your tips.

Charles Humphrey said...

No worries, thanks for taking the time to do it :)

Pitereeek said...

Hello. That is me again. I was fighting a little with your water shader. I have one question. Is it possible to change it for per pixel metod not per vertex? I was trying to do that. Without results :( ...

AND Endri!!!. Save refraction map. You will see that terrain is generated with layered fog. Probably this is the reason why you can't see this effect. Water shader is not doing "deep" effect. Terrain shader is responsible for that. Small trick:)

Sorry for my english!

Nice that you are helping people Kyle!! Thank yoy

Kyle Hayward said...

Hey pitereek. It's definitely possible to move the water shader to per pixel instead of per vertex.

Here are the steps:

--Do the projTexC calculation in the pixel shader. In the vertex shader, just set outVS.projTexC to posL. The main thing here is that the calculation of tpos has to be done in the pixel shader if you very little vertices. Without any math optimizations you'll also need to compile to ps_3_0.

--Also, the other thing that needs to be changed is the texture scale for the normal map look-ups. Change the WaterInfo.texScale to around 128.

--And remember that the vertRows and vertCols need to be in the form 2^x + 1. So changing the grid to be 5x5 should work just fine.

That's all there is to it. If you have any questions just let me know.

Kyle Hayward said...

Alright Charles I've put together 2 different versions. I just hope that the grid renders correctly (as it's the same code I used in the DP tutorials).

Small grid + quadtree, uses 16 bit indices

Brute force + 16 bit indices

Charles Humphrey said...


Thanks for this, downloading now, will let you know how I get on.

Charles Humphrey said...


Nope neither play at all. Behave as the first did, I get the form window, unfilled so you can see the IDE behind it, just the window border is drawn. I even tried to capture the effect, but I guess it must be tying up my machine so bad that Ctrl+PrntScreen wont capture the screen...

Oh well. Guess I might have to buy a new machine at some point eh..

Kyle Hayward said...

Well crap...

The terrain is being draw 3 times. Besides that I'm not sure what the problem could be. The render targets are all ARGB32, and the indices are 16 bit.

Charles Humphrey said...

LOL, yes it's a shame. If I get time i will delve into it as I would love this effect.

I loved your PP sample to, I have modded it a little so all I have to pass is 'this' to the classes. So once I have this working I might try and migrate that into it as well as the shadow map stuff (if I can).

Thanks for your time an effort it's really appreciated :)

Kyle Hayward said...

Hey no problem. Just glad I could offer something interesting.

Vincent Scheib said...

Nice sample here, thanks for contributing. ;)

Thang Nguyen said...

Hi Kyle,

I just download your code and somehow it doesn't work for me :(. I rebuild the project in XNA 3.0 and it gave me this error:

An unhandled exception of type "System.BadImageFormatException" occurred in Unknown Module.

Additional Info: is not a valid Win32 application.

I don't really know much about XNA so I can't pin point the problem. It would be great if you can help me out :D. I want to implement the scattering and atmospheric effect like you did :D.

Kyle Hayward said...

Well it's not an XNA application. It uses Managed DirectX, so you need to make sure you have the Managed DirectX 1.1 SDK/run-times installed.

I'm not sure if these are even included in the DirectX SDK anymore.

Thang Nguyen said...

Hi Kyle,

Thank you for verifying that. I have to say I am amazed by this project. I look at the paper and there are a lot of functions to implement.

Do you have any helps from other sources such as an example code or something?

Kyle Hayward said...

I believe I list some references in the main .cs file.

For the scattering, my main resources were:

and the chapter in Shader X3 on atmospheric scattering.

Sean O'neil also has source available for his implementation: