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