mmp / pbrt-v4

Source code to pbrt, the ray tracer described in the forthcoming 4th edition of the "Physically Based Rendering: From Theory to Implementation" book.
https://pbrt.org
Apache License 2.0
2.88k stars 448 forks source link

Incorrect Motion Blur with SPPM #440

Open paulgrassler opened 2 months ago

paulgrassler commented 2 months ago

Hey there, I am a bit confused, hopefully someone can help me. I am trying to write my own SPPM implementation and currently I am working on Motion Blur. To have some kind of reference, I took a look at how PBRT implements this. From what I understand, you sample a time value for each camera ray and photon ray independently and that is what I initially tried as well. What I found, however, is that the Motion Blur with SPPM seems incorrect when doing this. At least it does not match the same scene rendered with the path integrator and I am pretty sure they should not look this different, should they? Is this known or am I misunderstanding something? I will include my scene description and the 2 renders (one with sppm [bottom one] and one with path [top one]).

cornell-box-pathtracer cornell-box-sppm

As you can see, the sphere is generally darker and the blur certainly looks somewhat weird for SPPM. I would appreciate any clarification on this! Also, if this is indeed a known issue, how would you go about implementing it correctly?

Thank you for your help!

Scene:

Integrator "path"
#Integrator "sppm"
#    "float radius" [ 0.005 ]
Transform [ 1 -0 -0 -0 -0 1 -0 -0 -0 -0 -1 -0 -0 -1 6.8 1  ]
Sampler "paddedsobol"
    "integer pixelsamples" [ 64 ]
Film "rgb"
    "string filename" [ "cornell-box.png" ]
    "integer yresolution" [ 1024 ]
    "integer xresolution" [ 1024 ]
Camera "perspective"
    "float fov" [ 19.5 ]
TransformTimes 0 1

WorldBegin

MakeNamedMaterial "LeftWall"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0.75 0.25 0.25 ]
MakeNamedMaterial "RightWall"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0.25 0.25 0.75 ]
MakeNamedMaterial "Floor"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0.725 0.71 0.68 ]
MakeNamedMaterial "Ceiling"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0.725 0.71 0.68 ]
MakeNamedMaterial "BackWall"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0.725 0.71 0.68 ]
MakeNamedMaterial "ShortBox"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0.25 0.75 0.25 ]
MakeNamedMaterial "TallBox"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0.25 0.75 0.25 ]
MakeNamedMaterial "Light"
    "string type" [ "diffuse" ]
    "rgb reflectance" [ 0 0 0 ]
NamedMaterial "Floor"
Shape "trianglemesh"
    "point2 uv" [ 0 0 1 0 1 1 0 1 
        ]
    "normal N" [ 4.37114e-8 1 1.91069e-15 4.37114e-8 1 1.91069e-15 4.37114e-8 1 1.91069e-15 
                 4.37114e-8 1 1.91069e-15 ]
    "point3 P" [ -1 1.74846e-7 -1 -1 1.74846e-7 1 1 -1.74846e-7 1 1 -1.74846e-7 -1 ]
    "integer indices" [ 0 1 2 0 2 3 ]
NamedMaterial "Ceiling"
Shape "trianglemesh"
    "point2 uv" [ 0 0 1 0 1 1 0 1 
        ]
    "normal N" [ -8.74228e-8 -1 -4.37114e-8 -8.74228e-8 -1 -4.37114e-8 -8.74228e-8 
                 -1 -4.37114e-8 -8.74228e-8 -1 -4.37114e-8 ]
    "point3 P" [ 1 2 1 -1 2 1 -1 2 -1 1 2 -1 ]
    "integer indices" [ 0 1 2 0 2 3 ]
NamedMaterial "BackWall"
Shape "trianglemesh"
    "point2 uv" [ 0 0 1 0 1 1 0 1 
        ]
    "normal N" [ 8.74228e-8 -4.37114e-8 -1 8.74228e-8 -4.37114e-8 -1 8.74228e-8 -4.37114e-8 
                 -1 8.74228e-8 -4.37114e-8 -1 ]
    "point3 P" [ -1 0 -1 -1 2 -1 1 2 -1 1 0 -1 ]
    "integer indices" [ 0 1 2 0 2 3 ]
NamedMaterial "RightWall"
Shape "trianglemesh"
    "point2 uv" [ 0 0 1 0 1 1 0 1 
        ]
    "normal N" [ 1 -4.37114e-8 1.31134e-7 1 -4.37114e-8 1.31134e-7 1 -4.37114e-8 
                 1.31134e-7 1 -4.37114e-8 1.31134e-7 ]
    "point3 P" [ 1 0 -1 1 2 -1 1 2 1 1 0 1 ]
    "integer indices" [ 0 1 2 0 2 3 ]
NamedMaterial "LeftWall"
#NamedMaterial "ShortBox" 
#Shape "trianglemesh" "integer indices" [ 0 2 1 0 3 2 4 6 5 4 7 6 8 10 9 8 11 10 12 14 13 12 15 14 16 18 17 16 19 18 20 22 21 20 23 22 ] "point P" [ -0.0460751 0.6 0.573007 -0.0460751 -2.98023e-008 0.573007 0.124253 0 0.00310463 0.124253 0.6 0.00310463 0.533009 0 0.746079 0.533009 0.6 0.746079 0.703337 0.6 0.176177 0.703337 2.98023e-008 0.176177 0.533009 0.6 0.746079 -0.0460751 0.6 0.573007 0.124253 0.6 0.00310463 0.703337 0.6 0.176177 0.703337 2.98023e-008 0.176177 0.124253 0 0.00310463 -0.0460751 -2.98023e-008 0.573007 0.533009 0 0.746079 0.533009 0 0.746079 -0.0460751 -2.98023e-008 0.573007 -0.0460751 0.6 0.573007 0.533009 0.6 0.746079 0.703337 0.6 0.176177 0.124253 0.6 0.00310463 0.124253 0 0.00310463 0.703337 2.98023e-008 0.176177 ] "normal N" [ -0.958123 -4.18809e-008 -0.286357 -0.958123 -4.18809e-008 -0.286357 -0.958123 -4.18809e-008 -0.286357 -0.958123 -4.18809e-008 -0.286357 0.958123 4.18809e-008 0.286357 0.958123 4.18809e-008 0.286357 0.958123 4.18809e-008 0.286357 0.958123 4.18809e-008 0.286357 -4.37114e-008 1 -1.91069e-015 -4.37114e-008 1 -1.91069e-015 -4.37114e-008 1 -1.91069e-015 -4.37114e-008 1 -1.91069e-015 4.37114e-008 -1 1.91069e-015 4.37114e-008 -1 1.91069e-015 4.37114e-008 -1 1.91069e-015 4.37114e-008 -1 1.91069e-015 -0.286357 -1.25171e-008 0.958123 -0.286357 -1.25171e-008 0.958123 -0.286357 -1.25171e-008 0.958123 -0.286357 -1.25171e-008 0.958123 0.286357 1.25171e-008 -0.958123 0.286357 1.25171e-008 -0.958123 0.286357 1.25171e-008 -0.958123 0.286357 1.25171e-008 -0.958123 ] "float uv" [ 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 ] 
#NamedMaterial "TallBox" 
#Shape "trianglemesh" "integer indices" [ 0 2 1 0 3 2 4 6 5 4 7 6 8 10 9 8 11 10 12 14 13 12 15 14 16 18 17 16 19 18 20 22 21 20 23 22 ] "point P" [ -0.720444 1.2 -0.473882 -0.720444 0 -0.473882 -0.146892 0 -0.673479 -0.146892 1.2 -0.673479 -0.523986 0 0.0906493 -0.523986 1.2 0.0906492 0.0495656 1.2 -0.108948 0.0495656 0 -0.108948 -0.523986 1.2 0.0906492 -0.720444 1.2 -0.473882 -0.146892 1.2 -0.673479 0.0495656 1.2 -0.108948 0.0495656 0 -0.108948 -0.146892 0 -0.673479 -0.720444 0 -0.473882 -0.523986 0 0.0906493 -0.523986 0 0.0906493 -0.720444 0 -0.473882 -0.720444 1.2 -0.473882 -0.523986 1.2 0.0906492 0.0495656 1.2 -0.108948 -0.146892 1.2 -0.673479 -0.146892 0 -0.673479 0.0495656 0 -0.108948 ] "normal N" [ -0.328669 -4.1283e-008 -0.944445 -0.328669 -4.1283e-008 -0.944445 -0.328669 -4.1283e-008 -0.944445 -0.328669 -4.1283e-008 -0.944445 0.328669 4.1283e-008 0.944445 0.328669 4.1283e-008 0.944445 0.328669 4.1283e-008 0.944445 0.328669 4.1283e-008 0.944445 3.82137e-015 1 -4.37114e-008 3.82137e-015 1 -4.37114e-008 3.82137e-015 1 -4.37114e-008 3.82137e-015 1 -4.37114e-008 -3.82137e-015 -1 4.37114e-008 -3.82137e-015 -1 4.37114e-008 -3.82137e-015 -1 4.37114e-008 -3.82137e-015 -1 4.37114e-008 -0.944445 1.43666e-008 0.328669 -0.944445 1.43666e-008 0.328669 -0.944445 1.43666e-008 0.328669 -0.944445 1.43666e-008 0.328669 0.944445 -1.43666e-008 -0.328669 0.944445 -1.43666e-008 -0.328669 0.944445 -1.43666e-008 -0.328669 0.944445 -1.43666e-008 -0.328669 ] "float uv" [ 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 ] 
AttributeBegin
    Translate 0 1.9 0
    AreaLightSource "diffuse" "rgb L" [ 40 40 40 ] 
    NamedMaterial "Light" 
    Shape "sphere" "float radius" [ 0.1 ] 
AttributeEnd
Shape "trianglemesh"
    "point2 uv" [ 0 0 1 0 1 1 0 1 
        ]
    "normal N" [ -1 -4.37114e-8 -4.37114e-8 -1 -4.37114e-8 -4.37114e-8 -1 -4.37114e-8 
                 -4.37114e-8 -1 -4.37114e-8 -4.37114e-8 ]
    "point3 P" [ -1 0 1 -1 2 1 -1 2 -1 -1 0 -1 ]
    "integer indices" [ 0 1 2 0 2 3 ]

AttributeBegin
    NamedMaterial "ShortBox"
    Translate 0 0.2 0
    ActiveTransform EndTime
    Translate 0 0.2 0
    Shape "sphere"
        "float radius" [ 0.2 ]
AttributeEnd
paulgrassler commented 1 month ago

Hey, I implemented a straightforward fix for this and created a pull request #441. Please take a look! Instead of sampling separate timestamps for each ray and photon, one time sample is taken at the beginning of the SPPM iteration and used for all rays and photons. Each iteration therefore estimates the radiance in the scene at that timestamp and because of the increasing number of iterations/samples, it converges to the correct results and avoids sampling artifacts. I am fairly certain that this is also how they did it in the original paper.

In the pull request, I included images of the scene above with and without the fix compared to the path tracer ground truth. I also included the contact information of my supervisor (Reinhold Preiner) and myself (Paul Graßler). I found this issue while working on a seminar paper about Photon Mapping at the Institute of Computer Graphics and Knowledge Visualisation, Graz University of Technology.

pbrt4bounty commented 1 month ago

I checked here and, indeed, the result seems very accurate.