Thursday, June 24, 2010

A Practical (But Simple) Model for Daylight

For the past couple months I've been working off and on, trying to figure out a daylight model for the sky dome. To be more specific, I was attempting to incorporate the model discussed in a paper titled 'A Practical Analytic Model for Daylight'. It's a very interesting read and the theory is useful, even if you don't actually use their approach.

Unfortunately, I wasn't able to get the color conversion to work. Something with the Luminosity value just wasn't coming out correct no matter what I did. So instead, I just took the color gradients I knew I was looking for and hard coded some values to interpolate and presto- a day/night system. It's not bad, considering how simple the color calculations are. The most noticeable problem with this new feature is color banding. At sunrise and sunset, there is not enough of a change in color in the sky gradient, so the colors form very noticeable bands on the sky dome. Even worse, the bands move around as the colors change, which draws attention to the issue. The solution is probably dithering or some other form of noise to break up the pattern.

Eventually I'd like to get a more realistic model working, but for now it's time to leave 'good enough' alone and move on. Below is a series of screenshots taken during sunset.





Sunday, June 20, 2010

I spent some time playing around with normal maps and stumbled upon a much better looking ripple effect. By scaling up the the x and z coordinates of the normal map, the waves are much more pronounced. Here's a screenshot of the water at dusk.



Saturday, June 19, 2010

More water improvements

I've logged some solid hours programming this weekend, continuing to work on water effects. The water shader has been almost completely rewritten to add such features as specular lighting, normal mapping, waves, and caustic effects.

The first thing that I added was a simple wave function implemented in the vertex shader. The formula is pretty much just y += sin(x)*sin(y). If you were to zoom way out, the resulting wave form would follow a very obvious pattern, but when you're at eye level looking at the shore line it looks pretty realistic. This shader isn't meant to look like waves, but rather to give the water level a little bit of an ebb and flow.

Next, I got specular lighting working. I actually haven't used specular lighting in DirectX 10, and never had to code the lighting calculation myself. Once I got it working, I realized that the water needs texture to make the specular light look right. A flat sheet of water just shows a single dot of specular light, which looks pretty lame. Fortunately, normal mapping is pretty easy do in DirectX 10. It only took about 5 minutes to incorporate this into my shader. I used a normal map of a ripple pattern and overlaid two octaves (two versions of the same texture scaled to different sizes) moving at different rates across the surface. The resulting ripples in the water look infinitely more complex than a single normal map on its own. I'm very satisfied with how realistic the ripple effect came out.

Another simple feature I added was Fresnel alpha blending. If you're on a boat in the middle of a lake and look out toward the horizon, you'll see a reflection on the surface of the water. If you look straight down at the water, you'll see fish/rocks/etc underneath the surface. This is because the amount of light that's transmitted vs. reflected off the surface is dependent on the angle of incidence. The fraction of light that is reflected is the Fresnel term. There are lots of different ways to calculate this term, but the simplest way is to take the dot product of the viewing vector (camera to surface) and the normal vector of the surface. This calculation has already been done to compute specular lighting, which saves time. The Fresnel term is then used to interpolate between the color of the reflected pixel vs. the color of what's underneath.

The last thing I added was a caustic effect superimposed on the terrain underwater. Many examples I've found simply render the pattern to the water surface and call it good. In reality, the pattern is projected onto whatever geometry is at the bottom of the body of water. This requires a bit more work, but I think the added realism pays off. The approach here is similar to how I did the water ripples. Two octaves of the caustic pattern are overlaid and move randomly. It took a little bit of tweaking the scaling and rate of motion of the two textures to get this to look right. You have to look pretty hard to figure out how the pattern is animated.

Viewing the Water from Eye Level


Close Up of Caustic Effect

Friday, June 18, 2010

Multi-textured Terrain

One more update for today... multi-textured terrain. In my opinion, this is probably the most important aspect of rendering a realistic outdoor scene. I got the basic shader working, which allows me to splat up to four different textures onto my terrain at a resolution of 10 feet. In the picture below, the terrain only uses a basic gradient between sand and grass, which already looks a million times better then the grassy screenshots featured in my previous post.

The tricky part will be adding the functionality to my terrain editor to spit out alpha maps for texturing. This will need to take into account elevation, slope, and a few other parameters in order to create an organic and realistic texture map.

Water Fog

I've added a new feature to my terrain shader that accounts for depth when rendering portions of the terrain that are underwater. Because the water "plane" has a constant alpha value, the deepest part of a body of water is just as visible as the ground that's only covered by a few inches of water. In reality, bodies of water such as lakes and oceans have dirt and other particles that obscure light from reaching the bottom.

My approach to this problem is basically just per-vertex fog. Instead of interpolating colors based on distance from the camera, the shader uses the 'y' coordinate of the vertex in world space, and calculates its distance below the surface. This simple effect definitely gives the water a more realistic sense of depth.

Without Water Fog

With water fog

Sunday, June 13, 2010

The new graphics engine is coming along slowly but surely. I spent a lot of time working out some very mysterious bugs that were causing things to either render in the wrong spot or just not at all. I was starting to worry for a while there that I would have to start over because things were getting so complicated. Got it worked out though and now it's working beautifully.

One big thing I've started to implement is a day/night system. I want this feature to be very detailed and realistic. The ambient/diffuse light color, along with the sky colors and angle of light are all dependent on the time of day. The sky color is sampled from a 2D texture. The U coordinate is determined by time of day, and V coordinate is determined by the vertical angle of the sky. So basically, at any given time, the sky gradient is sampled from one column of texels in the sky Texture. Below is the very rudimentary texture I'm working with right now. Eventually I'll get the correct color gradient for dawn/dusk/etc.


Another thing I've added is water. Very. very. basic water. It's a semi-transparent heightmap with a caustic pattern texture. Waves, reflections, etc to be added later. Even this basic effect I've got now has made the terrain look much more like a realistic outdoor scene.


Next steps:
  • Waves, reflections, and specular highlights for water effect.
  • Multi-textured terrain to add regions of sand/rock/etc.
  • True-to-life sky dome gradient colors

Wednesday, May 12, 2010

New Graphics Engine


The GUI is coming along nicely, but I'm taking a break and moving back into some graphics stuff. It will be easier to test additions to the GUI later on when I have more uses for it.

Lately, I've been working on a new graphics engine. The central idea of the new engine is that everything is customizable and modular. It manages all of the resources, buffers, shaders, etc. Various entities in the game that need to be rendered check in with the graphics engine upon initialization and give it the details on how/when they need to be rendered.

So far I've got the terrain loading from a height map, per-vertex fog, and a fairly convincing skydome. The sky colors are actually sampled from a 2D texture. The sampled U value is proportional to the angle from the horizon (phi), and the V value is determined by the time of day. This 2D texture is calculated using the Preetham paper, A Practical Analytic Model for Daylight. Each column of pixels in the texture is a gradient of colors at a particular time of day. Tasks that remain for the skydome include clouds, stars, sun/moon sprites, and lens flare.

Friday, May 7, 2010

New GUI


I've been spending the past few weeks working on a custom GUI in DirectX. I modeled the GUI after MFC, making heavy use of inheritance. Gotta love c++. I went with this approach because it gives me (and potentially other developers) the freedom to derive modified versions of existing controls, along with creating new ones down the road.

The first week was pretty much spent getting the basic framework put together and getting a basic window drawn to the screen. Then I moved on to adding buttons, checkbox, edit box, and slider controls. The text box is capable of being assigned a value, but I haven't gotten around to allowing the user to enter values into it.

The next big tasks are to complete the edit box control and move on to list boxes.

Wednesday, March 17, 2010

Mini-projects

So I've been working toward learning DirectX 10 for the past couple weeks and it's proved more difficult and time consuming than I anticipated.

While I'm learning the new API, I've decided to take a break from working on the Earth project and do a series of small projects instead. I realized that most of the programming projects I've built were complex games and simulations that never got done. I usually spend lots of time working on specific aspects of the game, and before I know it the project is a year or two old and there is very functionality to show for it. It is probably a better idea to come up with a relatively simple idea and get all of the key features up and running. Then the extra effort can go into refining the details/mechanics.

One such project I've been contemplating is a "business" simulator. It would be a game where you own a business and try to earn money. The graphics would be very minimal and the focus would be on programming a solid and realistic simulation. Once the game is functional, the graphical representation could be improved (make it 3D, show people doing stuff, etc). I think the basic program could be done in a weekend.

Sunday, February 21, 2010

New Map Generator


I've spent the past few days working on a procedural map generator. Previously, my Earth3 game had randomly generated terrains using some fluid dynamics formulae. The result was a wavy map that somewhat resembled rolling hills. As you can see in the screenshot, the terrain is random, but lacks variety.

The new terrain generator uses coherent noise, which generates much more interesting and realistic terrains. The program starts by generating a Perlin noise map to determine the shape and elevation of land masses. Regions of the map where the elevation is above a certain threshold are designated as mountain ranges. These regions of the height map are blended with a Voronoi noise map in order to gove them a "ridged" look. You can see where the terrain transitions from Perlin to Voronoi, because the mointain ranges are the only regions that have that ridged pattern.

One very useful aspect of coherent noise is that the input parameters allow the user to control the look and feel of the map. For example, increasing the frequency of the Perlin noise causes the map to have several small continents instead of a couple of big ones. Other aspects that can be controled are the smoothness/roughness of the shore lines, and quantity of mountains.

Here's a screenshot of the above map, rendered in Earth3. The map clearly has more personality than the old map. The terrain has distinct geological formations ocurring in different areas, as you would expect to see in nature. The next big feature that this map needs is multi-texturing based on elevation and slope.

Monday, February 15, 2010

First post

I've decided to start a programming blog. I'm always playing around with new ideas and could use a place to collect them and maybe get some feedback. I've been programming in C++ in Visual Studio 6.0 for the past nine years and now it's time for a new chapter of my programming career. I'm upgrading to a new laptop with Windows 7, and will be purchasing Visual Studio 2008 soon.

This programming renaissance came about a few weeks ago when I purchased a copy of "Introduction to 3D Game Programing with DirectX 10". I scanned through the book and quickly became a fan of both the power of DirectX 10 and the author's method of explaining it. To my dismay, I discovered that DirectX 10 does not work in Windows XP. I've become increasingly aware of how out-of-date my system and software have become, and I'm ready to get caught up.