dipityPix app

Monday, July 6, 2015

Slightly simplified Cornell Box data

I just put my new renderer through the Cornell Box test using this data from the Cornell lab.   I didn't want to type in all those numbers for the boxes, nor deal with the slightly wonky walls that aren't necessarily planar (the real walls aren't).   So here is my geometry for it (in millimeters like the Cornell measurements):

Box itself: (0,0,0) to (555,555,555)

Small block: (0,0,0) to (165,165,165), rotate around Y -0.314 radians, move (130,0,65)
Big block: (0,0,0) to (165,330,165), rotate around Y  +0.3925 radians, move (265,0,295)

For fun I made the materials of the block glass and copper.   I used the metal Fresnel equations from this very nice post by S Legarde.

This is still brute force so the rays just have to be lucky enough to hit the light (100k initial rays per pixel)


Friday, July 3, 2015

Debugging refraction in a ray tracer

That picture I suspected had a refraction bug did.   It's always hard to tell-- that is one reason refraction hack can work so well.  I found a good debugging case so I will share.

Suppose you have a plate (closed box shape in my code) of glass of refractive index n.   What ray will go into it with easy to understand outcome?   Here is one:
Pink is the cross section of the solid glass pane which continues to the right.
Recall Snell's law that n sin(theta) = n' sin(theta').   That implies that for an incident ray from vacuum (my renderer will kill inhabitants immediately) at 45 degrees into a medium with refractive index sqrt(2), the refracted ray will have sin(theta') = 1/2.   There can't be any reflection on the next bounce because you would need sin(theta) = sqrt(6)/2, so you will get total internal reflection all the way until the other end of the glass plate.   I add some green exponential attenuation and voila (hopefully right):
Refraction looks plausible.  Maybe that quasi reflection of the sphere in the floor is a caustic?

Thursday, July 2, 2015

Shadow rays and I are getting a divorce

Like most batch rendering people I have a love-hate relationship with shadow rays.   They are wonderfully simple and can easily get you effects like accurate shadows of an eclipse.   And yet without getting fancy you start having car interiors turn black because the shadow rays hit the windows.    And brute force methods give better pictures given huge amounts of rays.   But I think I am finally believing my own BS and thinking computers are fast enough.  In my new rendering project I am abandoning shadow rays so the floor under the glass is automatically illuminated.   Note the quasi-TV is the only light source in the room.   No importance sampling here yet-- just getting the functionality in.   (I think there is still a bug in the glass but getting close).


Tuesday, June 30, 2015

A new iOS photo app: Subjective

We have a new iOS photo app out that combines some features of our previous apps.   The basic idea we have been pursuing for a while is based on the subjective refraction test from optometry where a person uses their own judgment for which of a set of things is better.  A/B testing is a more randomized version of this basic idea.

We first have you pick a category of editing (e.g., is it an outdoor landscape or is it food or do you want to make a stencil version like the Obama HOPE poser?).   It shows the image being edited as a background:

Pick one of the filter families-- like Stencil

Now three screens of choose best of 4:
Now pick best of four 3 times
And voila!

And here's the product.

You can of course go more conventionally and adjust contract and color temperature and saturation (one screen for each).  I like this for food.  Here's before:


and after.   Is it better?  I think so, but it's SUBJECTIVE!




Monday, June 29, 2015

Ray tracing: refraction

As my new ray tracer is spectral I am rewriting some of the basics from scratch including dielectric code.   I figured I could cut and paste some stuff out of ancient "ray tracing news" but ran into some problems with normal vectors.   So I am re-deriving this for my own benefit.
Sketch created with limnu iphone app from limnu.com
All renderers have some convention about which way surface normals point and whether that depends on incoming rays.   I am a fan of surfaces being boundaries between materials, and a dielectric has a surface normal N pointing to the side with refractive index n.   One thing that means is that in the diagram N might be pointing "down" along the dotted line.

First what about reflection?   It is usually the classic formula:

S = D - 2*N*dot(D, N)

Does that formula still work if N points along the dotted line?   Happily, yes-- try substituting -N in there and you get a "-" on the N and the dot product and they cancel.   Also, D need not be a unit vector.  I rarely require that in my ray tracers so I can use instancing if I want.   N however does need to be a unit vector.

Now what about refraction?   It obeys Snell's law:

n sin(theta) = n' sin(theta')

We can use the same trick as in reflection where we use N and D as a 2D basis.   First let's make life easy on ourselves and assume D is a unit vector and N points "up" like in the picture, and make an orthogonal basis (let's change the sin() and cos() with c, c', s, s')

D = -cN + sQ

Here Q is to the right and perpendicular to N.   We don't know what is is yet, but it we know what it is by rearranging the terms above to be get

Q = (D +  cN) / s


We also know that

T = -c'N + s'*Q

We know c = -dot(D,N), and s = sqrt(1 - c^2)

Further we know that s' = (n/n') s

Right there is a place we can get into trouble-- n can be high (over 2 for diamond) so if the more dense medium is where D is (the top medium), we could have s > 1.   In that case we get all reflection and no refraction (total internal reflection).   Here's a nice image of that:
The water acts as a perfect mirror due to total internal reflection (from wikipedia)
OK plug and chug the algebra:

T = -c'N + s'Q

T =  -c'N + s'(D +  cN) / s

We know s'/s = n'/n.

We also know c' = sqrt(1-s'^2) = sqrt(1 - (n/n')^2 (1-c^2) ).


T = (n'/n) D +(c(n'/n) - sqrt(1 - (n/n')^2 (1-c^2) ))

putting back in c = -dot(D, N) we get

T = (n'/n) D +(-dot(D, N)(n'/n) - sqrt(1 - (n/n')^2 (1-dot(D, N)^2) )) N

Ok!  That agrees with the ray tracing news formula.   Now what happens when N points down?  Only the last term is different:

T = (n'/n) D +(-dot(D, N)(n'/n) + sqrt(1 - (n/n')^2 (1-dot(D, N)^2) )) N

Well isn't that annoying?   That sign difference is just sgn(dot(D, N)).   I never know how to best code that sort of thing, but when in doubt, be very readable!

if (dot(D,N) > 0) temp_normal = -N    // now proceed with original formula


Friday, June 26, 2015

First real test of new spectral renderer

I just ran my first serious end to end test of my (still primitive) spectral renderer.   I turned to the trusy Macbeth color checker (data from BabelColor which Brian Cabral turned me onto).   I used Chris Wyman's approximations to the XYZ tristimulous curves and they were so much more pleasant than typing that junk it.  This is the chart with just a uniform background(lambda) = constant and no lights.  Looks like it all works fine.  This was a great test case (which is why everybody uses it for spectral work) and it shook out several bugs.


Wednesday, June 24, 2015

HDR and stb_image.h

I just got my renderer where I wanted so I will start outputting hdr.   The simple library I talked about in an earlier post has a minimal but sweet interface for dealing with Radiance .rgbe/.hdr files.   This appears to work fine (reading in a pgm into floats and then cranking them up X10).   Question: on OSX what do people use to view Radiance image files?    I downloaded ximage for OSX but it needs x windows and I am trying to avoid installing X for no good reason (maybe just one of these moments I experience with perfectly good things like X).  Edit: I knuckled under and put X on my mac.   Running ximage from xterm works great.  ximage stands up well for its age!  The stb_image* support for HDR seems to work perfectly!