Thursday, May 10, 2012

Bidirectional PT, Part 4

During the past few days I implemented specular support in the uniformly weighted BDPT. The key (or obvious) insight is that you're weighting a particular path against the alternatives of doing that particular path, and not against paths of equivalent length. Essentially, one must keep track of what the current combined path has (# of specular/not generatable edges) and weight based on that.


Renders

Note that the caustic looks weird because I disabled shading normals.
BDPT 6 bounces

MIS Ref 6 bounces
Maxwell Ref (mainly for comparing gradients)


Debugging

I found that using 'posterize' is a great way to compare images as it lets you easily visualize intensity differences, gradient differences, and image variance.

BDPT - For Debugging

Ref - For Debugging

Implementation

In my implementation, I have the following logic (please note that in my BDPT the eye vertex and the direction of the 1st eye path edge is fixed). The constants were derived on paper, through trial and error.

int epVariableNonSpecularEdges = 0;
//eye path vertices
for(int epvIdx = 0; epvIdx < numEPV; epvIdx++)
{
     if(epvIdx > 0 && !epVerts[epvIdx - 1].isDelta()) epVariableNonSpecularEdges++;

     //add contribution from the eye path randomly hitting the light
     output += 1.f / (epVariableNonSpecularEdges + 1) * random hit contribution

     //add contribution from direct lighting
     output += 1.f / (epVariableNonSpecularEdges + 2) * direct lighting contribution

     int lpVariableNonSpecularEdges = 0;

     //light path vertices - ignore vertex on the light
     for(int lpvIdx = 1; lpvIdx < numLPV; lpvIdx++) 
     {
           if(lv.isDelta()) continue;
           if(!lpVerts[lpvIdx-1].isDelta()) lpVariableNonSpecularEdges++;
           //add contribution from connecting eye-light path
           output += 1.f/(lpVariableNonSpecularEdges + epVariableNonSpecularEdges + 2) * connection contribution
     }
}

No comments:

Post a Comment