<< Go back to: Microsphere Projection

| Premise | Defining the Sphere | Projection | Accumulation of Final Values |
| Examples | Walkthrough |



Microsphere projection is based on the physical model of an infinitesimally small sphere located at the point of interpolation. This tiny sphere is then ‘illuminated’ by the surrounding sample points. Based on the degree of illumination on various parts of the sphere by various sample points, a series of weights for all the sample points are assigned. These weights, when applied, yield the interpolated value for the location.

Defining the Sphere

The surface of the Microsphere is divided into a large number of equally-spaced regions. Each region records for itself which sample point has illuminated it the most, and what illumination that sample point has provided. Each surface region is represented by a single unit vector pointing out from the center of the sphere to the center of that region. “S[i].Vector” will be used to represent the unit vector for surface region i. The more regions used, the greater the precision of the interpolation.

For each region, two values are recorded: one recording the index of which sample point has illuminated this section the greatest, and the second recording the degree of illumination from this point. These will be referred to as “S[i].Brightest_Sample” and “S[i]. Max_Illumination”, respectively.

Since determining an arbitrarily large number of equally-spaced regions on the surface of a sphere is no small task, we accept that a large number of randomly placed unit vectors will provide a fairly uniform distribution. The vectors are generated using the following algorithm:

    // x,y,z are uniformly-distributed random numbers in the range (-1,1)
    x := rand(-1,1)
    y := rand(-1,1)
    z := rand(-1,1)
    vectorSize := sqrt (x*x + y*y + z*z)

    // if the vector these points form is outside the unit sphere,
    // disregard and find a new vector.

while ( vectorSize > 1 )

// normalize the vector, so that it forms a unit vector for the surface of our sphere.
x := x / vectorSize
y := y / vectorSize
z := z / vectorSize


Net illumination is applied to the microsphere by iterating through each of the sample points, and applying illumination to the sphere one-by-one. It should be noted that illumination on various parts of the sphere decreases proportionally to the acuteness of the angle between the surface of the sphere and the direction of the sample point. Illumination also decreases as the distance between the microsphere and the sample point increase. Much like Shepard’s Method, this inverse relationship between distance and ‘brightness’ is governed by a power value ‘p’ specified by the user where p>0, p=1 and p=2 are typical values. p=1 yields an interpolation that is C0 (non-differentiable), p > 1 is C1 (first-derivative is continuous). Similar to Shepard’s Method, as p→∞, the closest points dominate the interpolation and the algorithm becomes the equivalent of Nearest Neighbor.

Intesnsity Projection Function:

for i := 0 to Number of Samples

     // vector connecting the current sample to the interpolation location
     vector1 := sample[i].XYZLocation - interpolation.XYZLocation

     // the distance-modified weight of this point
     // p > 0, typically p=1 or p=2.

     weight := pow(vector1.Size, -p)

     // the value of ‘Precision’ represents how many subdivisions
     // of the surface of the microsphere we are working with.

     for j := 0 to Precision

          // each sample only 'shines' on one hemisphere.
          // as the angle becomes more acute, the intensity
          // of that shine decreases as the cosine function

          cosValue := CosValueBetweenVectors(vector1, S[j].Vector)

          // if the brightness of the shine on this section of the sphere
          // is more than any other point thus far checked, update our
          // 'Brightest_Sample' and 'Illumination' data.

          if (cosValue * weight > S[j].Max_Illumination)
               S[j].Max_Illumination := cosValue * weight
               S[j].Brightest_Sample := i

Accumulation of the Final Values from the Sphere

Once all the calculations are complete regarding the maximum illuminations on the various sections of the sphere, we must make use of this data to produce a single interpolated value. To do this, we assign a weight to each sample point equal to the total illumination that point provided to the sections of the sphere. Note that each section of the sphere only records data regarding the point which provided the most illumination; sample points which did not out-shine any other points on any section of the sphere are assigned a weight of 0. If you are having problems understanding this, please visit the walkthrough.

Accumulation Pseudo-Code:

// accumulate the data from our sphere, and determine final interpolation
value := 0
totalWeight := 0
for i := 0 to Precision
     value := value + S[j].Max_Illumination * sample[S[j].Brightest_Sample].SampledValue
     totalWeight := totalWeight + S[j].Max_Illumination

// the final interpolated value generated by the algorithm
interpolation := value / totalWeight


Example 1, Top-Left: Illumination of a 2D Microsphere with a single sample point known.

Example 2, Top-Middle-Left: Illumination of a 2D Microsphere with a single sample point known. Sample point is closer than in Example 1, thus illumination is brighter.

Example 3, Top-Middle-Right:
Illumination of a 2D Microsphere with 3 sample points known. Note the exclusivity of each section of the sphere (ie, all top sections are either red or green. No greenish-red or redish-green).

Example 4, Top-Right:
Illumination of a 2D Microsphere with 3 sample points known. Similar to the previous example, note that the red points are not additive.

Example 5, Bottom:
Illumination of a 2D Microsphere with 4 sample points known. Note that since the distance of the green point is greater than red and blue points, it dominates fewer sections of the sphere.


Click HERE to go to the algorithm walkthrough.