For my final project I was interested in playing around with different types of noise, so an image of a sunrise over the ocean seemed like a good image to render. My goal was to create a realistic looking image using as little geometry as possible by relying on the noise bump mapping and texturing to fill in the details.
The geometry scene is kept very simple. The scene is rendered using only 4 objects:
All of the detail in the scene is achieved using bump mapping and texturing based on noise functions.
Ocean was the main focus of the project. I was interested in cellular noise as texturing and bump mapping source and after seeing a couple of images of the ocean generated with the use of Worley fractal F1 I decided to concentrate on generating something similar. The ocean is made of 2 large triangles laying in xz plane. I played around with the parameters quite a bit and realized that the best combination to generate the small waves on the surface was fractal F1 with 5 octaves and persistency of 0.5 - a common combination. Below is an image of an early development version of the ocean (back when I thought the ocean will be at night).
The gradient vector for the bump map is calculated as the vector pointing from the closest reference point to the point in question (by definition of cellular noise). The slopes are smoothed by using the actual distance from the point to scale the gradient vector, so that close to the point the original normal of the surface is almost unmodified and farther out the gradient potentially overpowers the original normal creating sharper equidistant edges. For fractal noise the gradient was calculated similar to the noise itself: by calculating the sum of gradients for each frequency weighted by the persistence for that frequency.
I wanted to have a lot of detail in the ocean surface bump map, so I needed a cellular noise system that would be robust enough to handle a large number of random points. The bump map uses 62500 random points on the surface of the ocean. The points are arranged in a 250 x 250 grid and the noise (and gradient) value is calculated by finding the grid cell the point belongs to and considering the 9 points in the surrounding cells. The grid is made small enough to condense the detail, so the wrapping is implemented for the points outside of the grid. Because the comparison time is independent of the number of points in the list (because in any case only 9 points will be considered) the number of points (as well as the size of the grid) becomes virtually unlimited - it will be limited only by the capability of reproducing the level of detail on the monitor.
Most of the images I saw used heavier clouds or even cloud covers. I wanted to create an image of something peaceful and quiet and I decided that the best way to do that would be to make the clouds some very light. I wanted to create a feeling of a sunrise of a sunny day, when the clouds that are there do not really matter. To achieve the goal I used the output of the Perlin noise function as an alpha value to blend white color with the color of the background. In order to achieve what I was going for I needed to go a little bit past standard and calculate the color of the pixel in the intersection test instead of the shader.
The idea was to surround the scene with a sphere that would provide input into a Perlin noise function. On the intersection test with this sphere the value of the noise is calculated based on the angles the vector connecting the center of the sphere makes with the x and y axis. The exact formula for calculating inputs into the Perlin noise function is as follows:
Vector3 radius = S * (result.P - m_vCenter + Vector3(PX, PY, PZ)) / m_fRadius;
In this formula S regulates the relative size of of the clouds and PX, PY, PZ move the cloud texture around. For the picture above the parameters are:
The noise value is then clamped to 1 if it is greater than 1 and then 0.2 is subtracted. If after these operations the value of the result is checked for negativity, and if result < 0 the intersection is rejected effectively making the sphere see-through in places where noise value is less than 0.2. Otherwise the value is used as an alpha value for blending pure white with some background color that is supposed to represent the color of the sky. For testing of Perlin function the clouds were initially implemented by texturing a vertical plane instead of the sphere. The result of the test can be seen below
The final result was rendered with fractal Perlin noise with 25 octaves and persistency of 0.6.
While working on the project I changed my mind a couple of times regarding what time of day the final image would represent. The initial idea was to create an image of the ocean at night with the stars and the moon and some clouds. It turned out that this way the image turned out too dark to be able to see the details of both the ocean and the clouds. The second Idea was to implement the bright daylight. However, after implementing spherical clouds the sky still looked too flat and unrealistic because of the very even coloring of the background (I used plain light blue background color to implement the sky). The production images of that period follows.
Finally I decided to go with the flow and make a sunrise picture. After trying a number of methods I chose a simple and to my point of view fairly effective method of generating the color of the sky. The sky is represented by yet another surrounding sphere which is significantly larger than the cloud sphere to with the center significantly farther back (for The Quiet i used camera position (0, 1, 3), clouds center (0, 0, 14 ) with radius 30, sky position (0, 0, 80) with radius of 100). The sphere is colored a very light blue color to approximate the color of the sky and has a moderate specular exponent (to create a moderate sized white or yellowish specular highlight). The very powerful reddish light is then put behind it and illuminates it creating a nice spread of color with a reddish/yellowish spot in the place of the specular highlight. This can be used to approximate the area around the sun right before sunrise or after sunset. The clouds are not affected by lighting (as stated above the color is calculated during intersection calculation) but they are affected by the color of the surrounding sky because the blending is done now with the color of the sky as seen behind the clouds instead of flat background color.