NOTE: this post has three basic problems. It assumes property 1 and 2 are true, and there is a missing piece at the end that keeps us from showing anything :)
This post results from a bunch of conversations with Dave Hart and the twitter hive brain. There are several ways to generate a random Lambertian direction from a point with surface normal
N. One way is inspired by a
cool paper by Sbert and Sandez where he simultaniously generated many form factors by repeatedly selecting a uniformly random 3D line in the scene. This can be used to generate a direction with a cosine density, an
idea first described, as far as I know, by Edd Biddulph.
I am going to describe it here using three properties, each of which I don't have a concise proof for. Any help appreciated! (I have algebraic proofs-- they just aren't enlightening--- hoping for a clever geometric observation).
Property 1:
Nusselt Analog: uniform random points on an equatorial disk projected onto the sphere have a cosine density. So in the figure, the red points, if all of them projected, have a cosine density.
Property 2: (THIS PROPERTY IS NOT TRUE-- SEE COMMENTS) The red points in the diagram above when projected onto the normal, will have a uniform density along it:
Property 3: For random points on a 3D sphere, as shown (badly) below, they when projected onto the central axis will be uniform on the central axis.
Now if we accept Property 3, we can first generate a random point on a sphere by first choosing a random phi uniformly theta = 2*PI*urandom(), and then choose a random height from negative 1 to 1, height = -1 + 2*urandom()
In XYZ coordinates we can convert this to:
z = -1 + 2*urandom()
phi = 2*PI*urandom()
x = cos(phi)*sqrt(1-z*z)
y = sin(phi)*sqrt(1-z^2)
Similarly from
property 2 we can given a random point (x,y) on a unit disk in the XY plane, we can generate a direction with cosine density when
N = the z axis:
(x,y) = random on disk
z = sqrt(1-x*x-y*y)
To generate a cosine direction relative to a surface normal
N, people usually construct a local basis, ANY local basis, with tangent and bitangent vectors
B and
T and change coordinate frames:
get_tangents(B,T,N)
(x,y) = random on disk
z = sqrt(1-x*x-y*y)
direction = x*B + y*T + z*N
There is f
inally a compact and robust way to write get_tangents. So use that, and your code is fast and good.
But can we do this show that using a uniform random sphere lets us do this without tangents?
So we do this:
P = (x,y,z) = random_on_unit_sphere
D = unit_vector(N + P)
So
D is the green dot while (
N+P) is the red dot:
So is there a clever observation that the green dot is either 1) uniform along N, or 2, uniform on the disk when projected?