EMAIL: wamplerk@cs.arizona.edu NAME: Kevin Wampler TOPIC: Out of Place COPYRIGHT: I SUBMIT TO THE STANDARD RAYTRACING COMPETITION COPYRIGHT. TITLE: A Real Heron COUNTRY: United States RENDERER USED: Self-written raytracer, extended from skeleton code for cse557 at the University of Washington http://www.cs.washington.edu/education/courses/557/05wi/projects/ray/handout.html TOOLS USED: Modeling scripts in Icon (tree and grass) GIMP (for the heron) C++ for raytracer gcc preprocessor RENDER TIME: 6-7 hours (estimated, with crazy AA settings) HARDWARE USED: Pentium 3GHz with enough RAM IMAGE DESCRIPTION: A creature from the real world finding itself in a synthetic scene. The idea for this arose form the disparity between how scenes for a raytracer are often constructed through a careful and subtle combination of mathematical functions, and the use of image maps to insert objects/textures from the real world directly into such a scene. The use of a bird from the real world landing inside of a scene built up from mathematical functions pretty much came directly from there. I wanted the theme of this image to be rather subtle, rather than to hit the viewer over the head with the fact that the heron did not belong there, so my intention was that the heron whould *almost* fit perfectly into the scene, but not quite. Thus I put a bit of time into making mathematical foundation of the rest of the scene non-obvious (though it is still apparent). In retrospect I debate weather this was a good idea -- I like the image but the out-of-placeness of the heron is indeed somewhat subtle, though I suppose there no a priori reason why it need be blindingly obvious. In order to somewhat enhance how the heron stands out I created the scene so that it is the only object in it which has a color that is more blue than red or green. DESCRIPTION OF HOW THIS IMAGE WAS CREATED: The raytracer used for this image was created from the skeleton code for my computer graphics class. As we had to create an image demoing the raytracer, I decided that I'd also do one that I could submit to this IRTC competition. We only had a little over two weeks to write the raytracing code and create the image, so a lot of the process was pretty rushed. But first some thanks: First off, my project partner Jon Froehlich deserves a good deal of credit. Although most of his code (of which there was a good deal) does not appear in this image (I found it easier to write all the things which I'd be using for it), his splendid antialiasing routine was used in its creation. The entire process was also made a good deal smoother than it otherwise would have been by his good organizational skills and attention to detail in the code in general. Secondly, the picture of the heron was taken (with permission) from an excellent photograph by Thomas Michael Corcoran. his webpage can be found at http://www.thomasmichaelcorcoran.com/ and the photograph which I used can be found on the page http://www.thomasmichaelcorcoran.com/2004_05_16_archive.html Now back to the raytracer. The skeleton code already handled affine transformations and ray intersections with simple objects (sphere, cone, cylinder, box). Of these, I expected to make good use of cone, but knew that I'd need to have isosurfaces to handle the landscape. Accordingly I first write some code to do ray isosurface intersections. I used pretty much the simplest algorithm that came to my mind -- but I looked it up later and it turns out that it's called `sphere tracing'. Once the isosurface code seemed to be working, I needed to implement materials. The skeleton code rendered every object in a single flat unshaded color, so I implemented Whitted's illumination model so handle diffuse shading, ambient shading, and specular highlights as well as reflection and refraction. This model gave pretty poor results for objects which were both transparent and reflective, so I added in povray-style conservation of energy to fix this. In order to aid in the creation of more realistic water, I also added an option to calculate the reflected and refracted values using (perpendicular) Fresnel reflection. I also built off of the code for defining functions that was used in isosurfaces and extended to to allow the specification of three dimensional textures. The way it's set up you can (or have to, depending on you view) specify a texture or a solid color for the diffuse, ambient, specular, reflective and transmissive material components independently. I also specified a function which loads these values from a bitmap, so you can do image-mapped textures. The framework would also allow things like AOI or slope dependent textures, but i didn't use any of these possibilities in the image. After materials were working, I added in shadows and fog. In addition to a global fog I allowed a fog to be specified within an object, in which case it behaves much like attenuation in povray, though I never got around to making it work correctly with shadows. The water in the scene actually has very dark green fog inside of it, and if you look at the corner where the rock dips into the water you'll notice it. A requirement of the project, and also a necessity for this image, was to implement speedups to handle large numbers of objects. For this I implemented a hierarchical bounding box scheme. It starts by creating a single bounding box for all of the boundable objects in the scene. It then divides this box perpendicular to its longest axis and creates three children: one for objects which lie entirely less than this division, one for objects which lie entirely greater than this division, and one for the rest. These bounding volumes are then recursively optimized. In order to support instancing I built the bounding method to allow unions which would be optimized, but the components of would be left inside the union. This allows me to refer to complicated unions with a single pointer and transformation node -- much the way that as I understand it povray currently handles meshes. This describes the basics of the raytracer, so I'll move on to the creation of the scene. The tree was the first thing in this image that was created. To do so, I wrote a little program in the Icon programming language to help me out. This program would generate a tree, and then would allow me to see a rough line drawing of it for a quick preview. There's not too much of interest in this program, as the tree algorithm was pretty much just made in an ad hoc manner. The bends in the branches come primarily from gravity and a 1D perlin noise function, and the code is pretty much tailored to produce exactly what I wanted for a tree in this image, but doesn't do too much else. I also wrote a little script in this program to generate the tufts of grass (which are actually rather closely approximated by arcs of parabolas). In order to preview these, I wrote a plugin for the program which generated povray code. This allowed me to work on the tree while the raytracer was not yet in a state to render it. Later I of course also wrote an output plugin for the raytracer's input file format. In the image, there are actually only 10 tufts of grass, but differently transformed references to them are automatically placed on the landscape according to a distribution function defined so that they're placed relatively well in the context of the rocks and water. The objects for the grass and tree themselves consist of just a whole bunch of textured cones. The function for the landscape is generated by several functions each adding detail at a different scale. The holes where the water can be seen come from a 3D smooth noise function, the output of which is modified to give a more sharply defined hole. The ridges in the rock are arise from a heavily turbulated sheared sine wave. The finer details in the rock are mostly generated from various modifications of 3D smooth noise. I found that i could get quite a bit more realism bu having the degree to which these finer scaled features where exhibited depend on the value of the ridges and holes, essentially simulating that softer rocks would weather more. The texture of the rocks is a layering of an algae texture, and underwater texture, and a pinkish rock texture. All of these textures are created from differently turbulated bands (like povray marble). In general there's pretty heavy turbulence applied so that the underlying band structure isn't apparent and the textures look a bit more swirly. I also gave the rock very slightly different hues at different places within the ridges. In order to increase the rough sand-papery texture of the rocks, the texture also has a bit of random noise thrown in -- the idea was to simulate something sort of like povray's crand graininess. The water is another isosurface which is essentially the combination of a plane and a single scale of smooth noise. The texture is just Fresnel reflecting with a dark green interior fog. it's pretty simple, but it worked rather well I guess. The heron was taken from a photograph, and then manipulated in GIMP to add transparency and cut out the heron. A simple color bmp and a transparency mask bmp were then generated as used as textures for the emissive and transmissive components of a texture respectively. The texture was then placed on a square in the scene. In order to make the managing of the scene files and the rendering of teh scene at various quality setting and objects included, the source files are forst run through the gcc preprocessor before being rendered. This let me use super-handy functions like #ifdef and #include and generally made the scene creation pretty managable.