# Environment Mapping!

January 15, 2014 - 9:33 pm by Joss Whittle C/C++ Graphics PhDReally pleased with the first functioning results from my Environment Sphere class. For variance reduction I’ve implemented a stippling method, drawing samples directly from the Inverse CDF of the image.

Or rather, I first generate a CDF of the Y axis where each value is the average brightness for the row. From this I invert to build an Inverse CDF for the axis. For each row in turn I generate the CDF and Inverse CDF and store them in a 2D matrix. To sample the image, you simple generate a uniform random number in the range `v ~ Unif(0, Max avg row brightness in Y)`

and then lookup the corresponding value in the Inverse CDF of Y, `y = icdfY[v]`

. This gives a randomly selected row in the image based on the probability the pixel with be bright, and thus contribute highly to the image. To complete the sampling we now find a random pixel at column `x`

along row `y`

by sampling the Inverse CDF of row `y`

. We do this by drawing a second uniform random number `u ~ Unif(0, Max Brightness of row Y)`

and use it to look up the corresponding pixel location in x, `x = icdfX[y][u]`

. We now have a random pixel in the image drawn stochastically. Below is a visualization of how many samples were taken from each pixel area over the course of 1 million test samples. As you can see far more time is spent sampling pixels with high (bright) image contribution.

This can then easily be turned into a unit vector of the direction to the pixel when mapped onto a unit sphere. This is simply the XY coordinate mapped uniformly onto the range `x,y = ((x / w, y / h) * 0.5) - 0.5`

and then orthogonally projected onto the sphere along the Z axis; forming the vector `V(x,y, abs(x) * (rand() < 0.5 ? -1 : 1) )`

That is to say, we choose with a random probability whether the pixel is mapped to the near or far side of the sphere.

Potentially this could be optimized by then calculating the dot product between surface normal and the generated samples. If the face is culled we could immediately flip the vectors Z axis and potentially save the sample from being a waste of computation.