Thursday, November 24, 2011

Raytracing OBJ Models

I recently found this website and wrapped up the obj reader I found there for use in my raytracer.  In order for this to work, I had to re-implement (or at least refactor) my bounding volume hierarchy code and get it working in my new raytracer.  Once I did that, I verified that it still provided the speedup I had seen before by testing it on a sphereflake.  It still worked.  So then I implemented another subclass of my GeometricObject type and used my BVH class inside of it to efficiently hit the many triangles that make up the model.

The image below depicts a model with roughly 16,000 triangles and facet normals.



Here it is up close, again with 16,000 triangles, facet normals, and 1 ray per pixel.  The image below took about 2 or 3 seconds to render.




Ok, now I'm rendering the "smooth mesh" model with more like 64,000 triangles, still using facet normals, and 1 ray per pixel.  This image took more like 5 seconds to render.




Finally, below you can see the model with 64,000 triangles, facet normals, and 25 rays per pixel.  This took about 2.5 minutes to render, and almost 15 million rays were generated.




Below is my glass version of the model, with 64,000 triangles, facet normals, and 25 rays per pixel.  It took my raytracer over 9 minutes to render the image.  I'm kind of disappointed with the results, I'm not sure where all the black lines and patches are coming from.




The soccer ball model looked a little better as glass, but not much.




I think if I use the vertex normals provided by Nate Robins' excellent sample code, then maybe even interpolate those across each triangle using barycentric coordinates, some of the mess might get cleaned up.

Still, it's kind of cool to be able to raytrace obj files now, and it's pretty neat to see them as glass, or at least a little like glass.

Monday, November 21, 2011

Dielectric Spheres

After rewriting my raytracer (most of it anyway, some pieces still haven't made the transition), I've got much of the functionality back and, for the most part, working better than before.

Now that it's easier to swap out "tracers", it was a snap to, for example, drop one in that visualizes normals instead of doing normal raytracing, the results of which you see below.




Additionally, after the rewrite I didn't even need to worry about where those weird speckles were coming from in my previous refraction blog entry.  I think adding a ShadeRecord to the hit functions of all my objects took care of that problem.  So I started working on splitting the energy between reflected and refracted rays by just dividing it in half everywhere.




Then I tried fiddling with the constant value a bit.  This resulted in interesting images, but they're definitely not correct.




The red sphere which appears on the surface of the left-most sphere in this scene is actually behind it and it's image is visible due to refraction.  I don't seem to have to the reflections here.




Now in the image below you can see that the reflection of the red sphere, which should have become more visible in it's transparent neighbor due to the incidental view angle on the transparent sphere, is completely missing.  So my Fresnel term isn't working yet.




Oh, is this more like it?  I can see below that when my view angle at a transparent sphere hit point gets closer to 90 degrees from the normal, the reflections on the surface of the sphere are more visible, but where my view angle is close to the normal angle, I see more of the refraction.




I don't know.  These sphere's look weird, below.  They don't seem to have any blending between where you see refracted and reflected images.  The whole set of seven spheres have indices of refraction ranging from 1.1 to 1.7, and to me, the lower ior spheres look better.  Maybe that's because a perfect sphere with an ior of 1.7 just doesn't exist in nature, so my eye isn't used to what it should look like?




It's very pronounced below.  Around the edges, you see all reflection, and in the middle you see all refraction.




I'm definitely missing something, because when I set a sphere's index of refraction to 1.0, it still completely disappears.




In image below, I tried setting the index of refraction of this sphere to something less than that of air.  I believe it was 0.9.




Below you can see all seven spheres in one shot, the one with the lowest index of refraction is on the right, the sphere with the highest is on the left.





This one is still a mystery to me.  I put my camera inside this sphere, and I get a mess!  If this is what is seen from inside the sphere, why doesn't it show up in refracted rays that leave the sphere and reflect off other objects?




I'm not sure it's correct, but I like this image below, looking down the line of spheres, with the dark side of the scene in the background.




Here I decided to take a little break and get some color filtering, or attenuation due to Beer's Law, working while I keep working on the Fresnel term.




I'm currently working on getting OBJ file reading working.  I'm actually just wrapping up some code I found from Nate Robins to read the OBJ files, and then I'm going to create a compound object in my geometric object hierarchy which will allow me to contain all the triangles of an OBJ file in a BVH within the compound object itself.  Hopefully soon I'll have a Frank model rendered as colored glass!

I'm also still working on getting other types of compound objects working which can be composed of parts of implicitly defined objects.

Ok, well I got a good tip to visualize the fresnel terms on my transparent spheres and see if they, indeed, looked like a step function as all the above images seem to indicate.  The following sequence of images illustrate the situation.


Above is an image created by a "Tracer" which keeps only refracted rays from transparent surfaces, and doesn't even compute reflections at all.  Now look at the image below, created by my buggy tracer which computes the Fresnel term and allows for wavelength-dependent absorption in the medium of each sphere.


Instead of a gradual change from refraction to reflectance as rays approach hitting the sphere at a glancing angle, there appears to be an arbitrary cutoff.  So in the next image, I'm visualizing this Fresnel term which determines the reflect/refract ratio, and it's clearly a step function.  The white outer rim indicates a Fresnel term of 1.0, corresponding to pure reflection and no refraction, the black inner circle indicates a Fresnel term of 0.0, corresponding to pure refraction.


So I went to work and found the problem, now that I was sure where it was.  When I had fixed the problem, the first thing I saw were much more reasonable looking Fresnel terms, seen below.


So then I went back to doing the normal refraction/reflection rendering, and the images immediately looked a lot better.  Notice in the following images that the reflections on the spheres are visible pretty much all over, but they're very faint when you look straight into the center of the sphere, and they get more visible as you look closer to the edge of the sphere.





Saturday, November 12, 2011

Texturing Spheres with Crayon Art

My kids and I love to color with crayons, so we spend a lot of time doing it, and as a result we have a lot of our art hanging around.  I thought it would be fun to capture some digital images of a few of our masterpieces and use them to texture some raytraced spheres.

This was my first one.

Too reflective for something supposedly colored with crayons

I kind of like that, but I was hoping for a softer look from the spheres, they just seem too mirror-like for having been colored with crayon.  To get rid of those reflections and create a more diffuse effect, I turned off reflections altogether.

I created a small scene of textured spheres, each with a different one of the pictures my kids and I worked on in the last few weeks.  I fiddled with the scene for awhile too, moving the spheres and camera around, and monkeying with the number and colors of the lights.  I spent too long on this.

Below you can see some of the images my dallying produced.  First is the Halloween sphere.

Welcome to the Halloween Ball!

This image is aliased, and the light near the ground in front is too pink. 

I replaced that pink light with a dim white one, and I sent out 25 rays per pixel for this image. 

Due to the perspective viewing, the ones near the edge resemble colored Easter eggs.

Well, that was fun.  Perhaps it was a waste of time, but it was fun nonetheless.  And tomorrow morning my kids will be happy to see their artwork plastered onto my computer screen.

When I mentioned this little experiment to a graphics friend of mine, he wondered whether we could achieve the effect of coloring things with crayon computationally rather than photographically.  I thought that was a great question.