GSoC 2022: Many Lights Sampling in Cycles X (Feedback Thread)

Yes, it is Cycles. I’ll explain how it was achieved a bit later. That is actually a workaround the ‘bug’ in Cycles when you have a scene with HDRI / Sun and many lights.

PS. The bug I mentioned above:

HE_noise_progress_area

6 Likes

Hey @Alaska, sorry for getting back to you so late - I’ve just pushed a change that seems to resolve things locally for me. I believe some of the issues you were encountering were related to the importance heuristics I was using earlier (which were just fixed along the way), but the main issue was that I wasn’t tagging the light manager to update when many lights sampling was enabled. As a result, the distribution wasn’t being constructed properly, which is why it was crashing earlier.

If you have the time to checkout the branch again, could you let me know if these changes work for you too?

1 Like

I gave your branch a try yesterday and just now with your updates and I’m seeing a crash inside LightTreePrimitive::calculate_bcone. The bug there can also lead to some faulty renders when it doesn’t crash so it would be good to fix up.

Uploading .blends on this site isn’t great but we can exchange it over at chat (same username as here) whenever your want. Just drop me a line over there if you’re interested.

2 Likes

@Jebbly, I’m sorry I have been unable to test the latest revision of your branch.
When compiling your branch of Blender I get many build warnings about “conversion from float to double” and “conversion of double to float” realted to the light tree. This results in the my compiler to stop building Blender. I tried disabling these “warnings as errors” but I must of not done it properly as the build continues to fail but for different reasons.

That’s a strange error to encounter, I don’t believe I used doubles anywhere in my code. If possible, could you send me your compiler output?

Here’s a relevenat build errors:

In file included from /intern/cycles/kernel/integrator/intersect_closest.h:11,
                 from /intern/cycles/kernel/device/cpu/kernel_arch_impl.h:25,
                 from /intern/cycles/kernel/device/cpu/kernel.cpp:48:
/intern/cycles/kernel/light/light.h: In function ‘float ccl::triangle_light_pdf(KernelGlobals, const ShaderData*, float)’:
/intern/cycles/kernel/light/light.h:670:70: error: implicit conversion from ‘float’ to ‘double’ to match other result of conditional [-Werror=double-promotion]
  670 |       const float area_pre = (kernel_data.integrator.use_light_tree) ? 1.0 : triangle_area(V[0], V[1], V[2]);
      |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/intern/cycles/kernel/light/light.h:670:70: error: conversion from ‘double’ to ‘float’ may change value [-Werror=float-conversion]
/intern/cycles/kernel/light/light.h: In function ‘void ccl::triangle_light_sample(KernelGlobals, int, int, float, float, float, ccl::LightSample*, ccl::float3)’:
/intern/cycles/kernel/light/light.h:831:70: error: implicit conversion from ‘float’ to ‘double’ to match other result of conditional [-Werror=double-promotion]
  831 |       const float area_pre = (kernel_data.integrator.use_light_tree) ?
      |                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
  832 |                                  1.0 :
      |                                  ~~~~~                                
  833 |                                  triangle_area(V[0], V[1], V[2]);
      |                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      
/intern/cycles/kernel/light/light.h: In instantiation of ‘void ccl::triangle_light_sample(KernelGlobals, int, int, float, float, float, ccl::LightSample*, ccl::float3) [with bool in_volume_segment = false; ccl::KernelGlobals = const ccl::KernelGlobalsCPU* __restrict__; ccl::LightSample = ccl::LightSample]’:
/intern/cycles/kernel/light/light.h:960:33:   required from here
/intern/cycles/kernel/light/light.h:831:70: error: implicit conversion from ‘float’ to ‘double’ to match other result of conditional [-Werror=double-promotion]
/intern/cycles/kernel/light/light.h:831:70: error: conversion from ‘double’ to ‘float’ may change value [-Werror=float-conversion]
/intern/cycles/kernel/light/light.h: In instantiation of ‘void ccl::triangle_light_sample(KernelGlobals, int, int, float, float, float, ccl::LightSample*, ccl::float3) [with bool in_volume_segment = true; ccl::KernelGlobals = const ccl::KernelGlobalsCPU* __restrict__; ccl::LightSample = ccl::LightSample]’:
/intern/cycles/kernel/light/light.h:913:45:   required from ‘bool ccl::light_distribution_sample(KernelGlobals, float, float, float, ccl::float3, int, uint32_t, ccl::LightSample*) [with bool in_volume_segment = true; ccl::KernelGlobals = const ccl::KernelGlobalsCPU* __restrict__; uint32_t = unsigned int; ccl::LightSample = ccl::LightSample]’
/intern/cycles/kernel/light/light.h:936:41:   required from here
/intern/cycles/kernel/light/light.h:831:70: error: implicit conversion from ‘float’ to ‘double’ to match other result of conditional [-Werror=double-promotion]
/intern/cycles/kernel/light/light.h:831:70: error: conversion from ‘double’ to ‘float’ may change value [-Werror=float-conversion]
In file included from /intern/cycles/kernel/integrator/subsurface.h:10,
                 from /intern/cycles/kernel/integrator/intersect_subsurface.h:6,
                 from /intern/cycles/kernel/device/cpu/kernel_arch_impl.h:27,
                 from /intern/cycles/kernel/device/cpu/kernel.cpp:48:

Oh okay, I think I understand the issue. Thanks for sharing!

Update: @Alaska I pushed a change that I believe should resolve your build errors. If you have the time, could you try building again? Sorry in advance if it doesn’t work, but please do share the build log again in that case. Could I also ask how much storage your Blender clone + build occupies on Linux? I have an Ubuntu machine that I could try building Blender on, but I’m unsure of whether or not it has enough storage.

2 Likes

On my ubuntu machine the build dir, including libs, tests and one debug build takes ~25GB.
The build dirs are by far the largest 17GB for build_linux_debug/ So a bit more space is handy if you want to keep builds around.

1 Like

Thanks, that fixed the build errors for me.


This was the issue you wanted me to investigate to see if it’s fixed?

From intial testing, both of these issues have been fixed.

The other issues I reported about weird lighting also appears to be fixed in my test scene. Thank you for fixing these issues for us.


Roughly 13GB for me. (Blender code + build + precompiled linux libraries)

1 Like

During testing I found a bug (or a feature that’s not currently implemented). With many lights sampling enabled, translucent materials do not render properly.

Moving the light around can result in the transulcent shader partially rendering with Many Lights Sampling on, but it’s still not right.

I also assume that you know that volumetrics currently don’t render properly with Many Lights Sampling enabled. If you don’t, you will discover it as you work on implementing Many Lights Sampling for volumes in the coming weeks.


May I also ask a question. What is the expected performance impacts of Many Lights Sampling? This is what I can think of, am I missing something?

  1. Constructing the light tree will increase the initiallization time of a given scene.

  2. Traversing the light tree/figuring out which light to sample will increase the cost of each sample.

  3. Ray splitting (which currently isn’t implemented?) will increase the cost per sample depending on the scene.

I’m sorry if this has already been documented somewhere, is 2 (Traversing the light tree) an expensive operation? I have a scene where lighting comes almost entirely from multiple mesh lights. And I’ve noticed that with Many Lights Sampling on, the “time per sample” increases drastically. And I don’t know if something like this is expected or not, hence why I am asking the question.

Time per sample - Many Lights Sampling Off: 0.643138 seconds
Time per sample - Many Lights Sampling On: 6.392621 seconds

Scene light statistics:

light.cpp:1237] Total 2 lights.
light.cpp:248] Background MIS has been disabled.
light.cpp:1216] Number of lights sent to the device: 1
light.cpp:1218] Number of lights without contribution: 1
light.cpp:390] Total 1153 of light distribution primitives.

Here is the .blend file if you wanted to take a look at it:

1 Like

I also assume that you know that volumetrics currently don’t render properly with Many Lights Sampling enabled. If you don’t, you will discover it as you work on implementing Many Lights Sampling for volumes in the coming weeks.

Thanks again for the thorough testing. You’re right that volumetrics are not yet supported, but I’ll hopefully be getting to it by next week.

  1. Constructing the light tree will increase the initiallization time of a given scene.
  2. Traversing the light tree/figuring out which light to sample will increase the cost of each sample.
  3. Ray splitting (which currently isn’t implemented?) will increase the cost per sample depending on the scene.

In terms of expected performance impacts, you’re correct about 1 and 2. As for 3, Brecht and I are still determining if this should be used or not. The main point is that Cycles is structured to take one direct light sample at a time (while ray splitting would do multiple).

I’m sorry if this has already been documented somewhere, is 2 (Traversing the light tree) an expensive operation? I have a scene where lighting comes almost entirely from multiple mesh lights. And I’ve noticed that with Many Lights Sampling on, the “time per sample” increases drastically. And I don’t know if something like this is expected or not, hence why I am asking the question.

Traversing the light tree is definitely going to be a much more expensive operation than the original distribution calculation. This is because we now need to perform position-dependent calculations at each level of the tree, whereas the original method only needs to binary search through a list of lights. The intended tradeoff is that each sample will take more time to calculate, but fewer samples will be needed for a good result. That said, there are definitely a lot of optimizations that can (and should) be made to improve the traversal performance, so that hopefully the difference is not as drastic in the future.

2 Likes

Out of curiosity, are there plans to further improve the importance heuristic during the coming weeks?

If so, should we the end user/testers continue to upload scenes show casing where Many Lights Sampling produces less than ideal results?

1 Like

Yes, I’ll be spending some more time on the heuristics this week. However, it’s difficult to balance working on new features along with creating test scenes to debug, so test scenes are always welcome!

Just as a note, everything outside of volumetrics should be implemented (although, I will be adjusting the distant light importance in the next few days). If any scenes only contain such features and are producing a weird result, please let me know!

what type of scene you need? I can make something that helps

1 Like

I have a scene containing three lights. When one of the lights is moved far enough away in a certain direction, Many Lights Sampling ends up producing an incorrect result where the two main lights in the scene overlap.

Here is the same scene rendering with Many Lights Sampling On (Top) and Many Lights Sampling Off (Bottom)


Here is the scene:

There is a light called “Green”. This is the light I’ve moved far away from the monkey head. If you bring it closer to the monkey head, or move it around to a different spot within a certain range, the issue resolves itself.

1 Like

Anything helps! If you just want to test anything that you already have (with and without the light tree), please let me know how it goes; if it fails, please share!

For posterity: the issue was related to the light tree construction, where the splitting bound was set incorrectly, so the red light was being grouped with the green light. As a result, the centroid was still relatively far, so the node containing that light had a very low probability of being sampled. I haven’t pushed these changes yet because I would like to first resolve the strange issues I’m encountering when merging with master, but it should be pushed within a few days.

EDIT: I’ve chosen to push my changes for now, but keep in mind that my branch is not updated to the current Cycles structure.

1 Like

I made a scene that might be worth testing with Many Lights Sampling patch.

The scene has 2 meshes with diffuse material and 682 area lights. The lights are in 5 groups of different size and emission.

Here are 1000px renders capped at 4096 spp. Full GI preset, noise threshold 0.007.

Renders are from two different cameras in the same scene.

Scene (change txt to blend):
MLS_TEST_DIFF.txt (932.6 KB)

4 Likes

Also same scene but with volumes instead of a box:

MLS_TEST_VOLUME.txt (930.1 KB)

5 Likes

I just thought I would share some testing I did in various scenes with many lights. Sorry for the long message. I tried making it shorter by reducing the preview size of images, but it didn’t help much.

I should note some stuff. In the scenes I tested. I rendered with Adaptive Sampling off and a time limit of 2 minutes. So in this case, we are comparing equal render times.

I have also uploaded all my scenes and the relevant test images to this Google Drive folder (All images uploaded to this site get converted to jpeg with compression, hence why I’ve uploaded the images to my Google drive):

https://drive.google.com/drive/folders/1lw3MgNodq822V0oSdqDeBxnVqcY6C2Ng?usp=sharing

I am also using this version of the Many Lights Sampling Branch:
3.3.0 Alpha, branch: soc-2022-many-lights-sampling, hash: rB37e651e62c80


Bistro:

This is the Amazon Lumberyard Bistro scene. I downloaded it from here (Amazon Lumberyard Bistro | NVIDIA Developer), imported it into Blender, and made some minor adjustments.

Many Lights Sampling Off:


Many Lights Sampling On:

My thoughts and observations:
In this scene, Many Lights Sampling does a great job at reducing noise in the same time frame. I have no complaints about it.


Nvidia Attic

This is the Attic demo scene provided by Nvidia. I downloaded it from here (Pixar Universal Scene Description (USD) | NVIDIA Developer), imported it into Blender, and made some minor adjustments.

It may seem like this scene isn’t really going to benefit from Many Lights Sampling, but it does because there is a bunch of Christmas lights in the scene which can detract from the sampling of other lights.

Many Lights Sampling Off:


Many Lights Sampling On:

My thoughts and observations:
In this scene, Many Light Sampling helps out and reduces noise in equal time renders. But I noticed something odd, the Christmas lights in the background on the upper left of the image. They’re noisier with Many Lights Sampling on. So I decided to investigate this issue by setting up a new camera near those lights to see what happens. These are the results:

Many Lights Sampling Off:


Many Lights Sampling On:

My thoughts and observations:
In this scene with a focus on the Christmas lights, I’m not sure what to say. With Many Lights Sampling on, the image looks noiser (with the exception of some areas).


Luxcore DLSC test scene

This is a demo scene for Luxcore. I downloaded it from here (Example Scenes – LuxCoreRender), recreated all the materials in Cycles and then rendered it.

Many Lights Sampling Off:


Many Lights Sampling On:

My thoughts and observations:
This one is a bit odd. In some places, the image is noiser with Many Lights Sampling On (for example, the wooden floor and the walls), but some of the lights close to the ladder have less noise. The lights also appear brighter with Many Lights Sampling On, but I’m not sure if that’s a bug or due to the undersampling of the lights with it off. Also, with Many Lights Sampling on, the light inside the switch for the power plug doesn’t show up.

I also ran a test with a short render time (30 seconds in this case).

Many Lights Sampling Off:


Many Lights Sampling On:

My thoughts and observations:
With the 30 second long render, the scene is overall noiser with Many Lights Sampling On, with the exception of areas close to the lights. This file might need further investigation.


Overnight, I’m going to run a “ground truth test” where I render the scene with Many Lights Sampling on and off to really high sampling counts to see if they match. I will upload the results at a later date.

17 Likes