erichlof / THREE.js-PathTracing-Renderer

Real-time PathTracing with global illumination and progressive rendering, all on top of the Three.js WebGL framework. Click here for Live Demo: https://erichlof.github.io/THREE.js-PathTracing-Renderer/Geometry_Showcase.html
Creative Commons Zero v1.0 Universal
1.93k stars 177 forks source link

rendering artifacts #1

Closed jdaniellhebert closed 7 years ago

jdaniellhebert commented 8 years ago

This is a very compelling project. Thank you for sharing. I have been experimenting with changing the scenes and am finding that when I remove certain objects the rendering "whites out". I am unfortunately not experienced with rendering and I am uncertain how to debug this. Any insights you might share would be appreciated. Thanks for your consideration of this!

erichlof commented 8 years ago

@jdaniellhebert Hi, thank you for the kind words. Would you mind posting your entire SetupScene(void) function? That way I can look at some of the objects and their values that you have entered.
In the original SmallPT pathtracer (the code that I used to start my own project here), the rendering is constantly being accumulated to the final image. So that means it is very sensitive to bright lights (over exposure). When you say "whites out" that makes me think that maybe one of the lights in the scene is set too high. But if you can post your changes, I'll be glad to take a look and help you! :)

jdaniellhebert commented 8 years ago

Hi Erich, thanks for your reply here are two versions of SetupScene(). One does not have the whiteout accumulation and the other does. I have found that this happens in other cases when I try commenting out only one of the other spheres.

This works:

//-----------------------------------------------------------------------
void SetupScene(void)
//-----------------------------------------------------------------------
{
    vec3 z  = vec3(0);          
    vec3 L1 = vec3(1.0, 1.0, 1.0) * 2.0;// Whiteish light
    vec3 L2 = vec3(1.0, 0.8, 0.1) * 1.5;// Yellowish light
    vec3 L3 = vec3(0.1, 0.7, 1.0) * 1.5;// Blueish light

        spheres[0] = Sphere( 4000.0, vec3(0, -4000, 0), z, vec3(0.4,0.4,0.4), CHECK);//Checkered Floor

        spheres[1] = Sphere( 500.0, vec3(0.0, 700.0, 0.0),      L1, z, DIFF);//spherical white Light1 
    spheres[2] = Sphere( 100.0, vec3(200.0, 300.0, -200.0), L2, z, DIFF);//spherical yellowish Light2
    spheres[3] = Sphere( 100.0, vec3(800.0, 300.0, -200.0), L3, z, DIFF);//spherical blueish Light3

    spheres[4] = Sphere( 16.5, vec3(-25.0,16.5,5.0),  z, vec3(0.9,0.9,0.9), SPEC);//Mirror sphere
    spheres[5] = Sphere( 16.5, vec3(32.0,17.0,30.0),  z, vec3(0.9,0.9,0.9), REFR);//Glass sphere //0.6,0.9,0.7
        spheres[6] = Sphere( 10.0, vec3(-30.0,12.6,50.0), z, vec3(0.5,0.5,0.5), VOLUME);//Volume-filled sphere
        spheres[7] = Sphere( 15.4, debugSpherePos,        z, vec3(0.9,0.9,0.9), TRANSLUCENT);//debug translucent sphere
        spheres[8] = Sphere(  8.0, vec3(5.0,8.0,35.0),    z, vec3(0.9,0.9,0.9), SPECSUB);//shiny covering over sub-surface material

//  ellipsoids[0] = Ellipsoid(  vec3(30,40,16), vec3(90,5,-20),    z, vec3(0.9,0.7,0.1), SPEC);//metallic ellipsoid

//  cylinders[0] = Cylinder( 15.0, 30.0, vec3(-80,0,-50), z, vec3(0.5,0.0,0.0), REFR);//red glass Cylinder

//  cones[0] = Cone( 20.0, 20.0, vec3(0,0,0), z, vec3(0.0,0.0,0.9), COAT);//blue Cone

    planes[0]  = Plane( vec4( -1.0,-0.1,0.0,800.0), z, vec3(0.9,0.9,0.9), DIFF);//WhitePlane Right Wall
    planes[1]  = Plane( vec4(  1.0,-0.1,0.0,800.0), z, vec3(0.9,0.0,0.9), DIFF);//MagentaPlane Left Wall
    planes[2]  = Plane( vec4(  0.0,-0.1,1.0,800.0), z, vec3(0.9,0.9,0.9), DIFF);//WhitePlane Back Wall
    planes[3]  = Plane( vec4( 0.0,-0.1,-1.0,800.0), z, vec3(0.0,0.9,0.9), DIFF);//CyanPlane Front Wall

    disks[0]   = Disk( 16.5 * 16.5, vec3(-100.0,11.0,-10.0), vec3( 1.0,-1.0,0.0 ), z, vec3(0.9,0.0,0.0), DIFF);//RedDisk Left 
    disks[1]   = Disk( 16.5 * 16.5, vec3( 30.0,-10.0,-180.0), vec3( -1.0,0.0,0.3 ), L3, z, DIFF);//DiskLight 

//  triangles[0] = Triangle( vec3(0.0,0.0,1.0), vec3( 0.0,30.0,-50.0), vec3( 20.0,60.0,-50.0), vec3( -20.0,60.0,-50.0 ), z, vec3(0.0,0.9,0.0), DIFF);//Green Triangle

//  quads[0] = Quad( vec3(0.0,0.0,1.0), vec3( -150.0,40.0,-50.0), vec3( -100.0,40.0,-50.0), vec3( -100.0,90.0,-50.0 ), vec3( -150.0,90.0,-50.0 ), z, vec3(0.0,0.0,0.9), DIFF);//Blue Quad

//  boxes[0]  = Box( vec3(0.0,7.0,-90.0), vec3(50.0,14.0,-180.0), z, vec3(0.2,0.9,0.7), REFR);//Glass Box
//  boxes[1]  = Box( vec3(2.0,9.0,-92.0), vec3(48.0,12.0,-178.0), z, vec3(0.0,0.0,0.0), DIFF);//Diffuse Box
}

This does not work and whites out. Note I have commented out just one of the spheres in addition to the other items in the first example.

//-----------------------------------------------------------------------
void SetupScene(void)
//-----------------------------------------------------------------------
{
    vec3 z  = vec3(0);          
    vec3 L1 = vec3(1.0, 1.0, 1.0) * 2.0;// Whiteish light
    vec3 L2 = vec3(1.0, 0.8, 0.1) * 1.5;// Yellowish light
    vec3 L3 = vec3(0.1, 0.7, 1.0) * 1.5;// Blueish light

        spheres[0] = Sphere( 4000.0, vec3(0, -4000, 0), z, vec3(0.4,0.4,0.4), CHECK);//Checkered Floor

        spheres[1] = Sphere( 500.0, vec3(0.0, 700.0, 0.0),      L1, z, DIFF);//spherical white Light1 
    spheres[2] = Sphere( 100.0, vec3(200.0, 300.0, -200.0), L2, z, DIFF);//spherical yellowish Light2
    spheres[3] = Sphere( 100.0, vec3(800.0, 300.0, -200.0), L3, z, DIFF);//spherical blueish Light3

    spheres[4] = Sphere( 16.5, vec3(-25.0,16.5,5.0),  z, vec3(0.9,0.9,0.9), SPEC);//Mirror sphere
    spheres[5] = Sphere( 16.5, vec3(32.0,17.0,30.0),  z, vec3(0.9,0.9,0.9), REFR);//Glass sphere //0.6,0.9,0.7
        spheres[6] = Sphere( 10.0, vec3(-30.0,12.6,50.0), z, vec3(0.5,0.5,0.5), VOLUME);//Volume-filled sphere
        spheres[7] = Sphere( 15.4, debugSpherePos,        z, vec3(0.9,0.9,0.9), TRANSLUCENT);//debug translucent sphere
//       spheres[8] = Sphere(  8.0, vec3(5.0,8.0,35.0),    z, vec3(0.9,0.9,0.9), SPECSUB);//shiny covering over sub-surface material

//  ellipsoids[0] = Ellipsoid(  vec3(30,40,16), vec3(90,5,-20),    z, vec3(0.9,0.7,0.1), SPEC);//metallic ellipsoid

//  cylinders[0] = Cylinder( 15.0, 30.0, vec3(-80,0,-50), z, vec3(0.5,0.0,0.0), REFR);//red glass Cylinder

//  cones[0] = Cone( 20.0, 20.0, vec3(0,0,0), z, vec3(0.0,0.0,0.9), COAT);//blue Cone

    planes[0]  = Plane( vec4( -1.0,-0.1,0.0,800.0), z, vec3(0.9,0.9,0.9), DIFF);//WhitePlane Right Wall
    planes[1]  = Plane( vec4(  1.0,-0.1,0.0,800.0), z, vec3(0.9,0.0,0.9), DIFF);//MagentaPlane Left Wall
    planes[2]  = Plane( vec4(  0.0,-0.1,1.0,800.0), z, vec3(0.9,0.9,0.9), DIFF);//WhitePlane Back Wall
    planes[3]  = Plane( vec4( 0.0,-0.1,-1.0,800.0), z, vec3(0.0,0.9,0.9), DIFF);//CyanPlane Front Wall

    disks[0]   = Disk( 16.5 * 16.5, vec3(-100.0,11.0,-10.0), vec3( 1.0,-1.0,0.0 ), z, vec3(0.9,0.0,0.0), DIFF);//RedDisk Left 
    disks[1]   = Disk( 16.5 * 16.5, vec3( 30.0,-10.0,-180.0), vec3( -1.0,0.0,0.3 ), L3, z, DIFF);//DiskLight 

//  triangles[0] = Triangle( vec3(0.0,0.0,1.0), vec3( 0.0,30.0,-50.0), vec3( 20.0,60.0,-50.0), vec3( -20.0,60.0,-50.0 ), z, vec3(0.0,0.9,0.0), DIFF);//Green Triangle

//  quads[0] = Quad( vec3(0.0,0.0,1.0), vec3( -150.0,40.0,-50.0), vec3( -100.0,40.0,-50.0), vec3( -100.0,90.0,-50.0 ), vec3( -150.0,90.0,-50.0 ), z, vec3(0.0,0.0,0.9), DIFF);//Blue Quad

//  boxes[0]  = Box( vec3(0.0,7.0,-90.0), vec3(50.0,14.0,-180.0), z, vec3(0.2,0.9,0.7), REFR);//Glass Box
//  boxes[1]  = Box( vec3(2.0,9.0,-92.0), vec3(48.0,12.0,-178.0), z, vec3(0.0,0.0,0.0), DIFF);//Diffuse Box
}

Thanks for your help!

erichlof commented 8 years ago

Hi again, thanks for posting your code - that really helps me see what is happening. At first glance, I think I spot the reason that the second example is malfunctioning. Earlier in my source code, in the path tracing loop of bool SceneIntersect(...), it loops through all the objects according to how many you specify at the top of the script with the #define N_SPHERES (in this case). When the looping int 'i' gets to spheres[8], you have commented its construction out, so it has bad random values probably that have not been initiated.

The most simple fix I can think of is to simply set the #define N_SPHERES value to 8 instead of 9, so the intersect function doesn't try intersecting with undefined objects.

Let me know if this works. If not, I will try running both your scenes on my computer and keep looking for possible bugs.