[Soc-2018-dev] Weekly Report #08 - Many Light Sampling

Erik Englesson erikenglesson at gmail.com
Mon Jul 9 08:44:59 CEST 2018


Hi,

Thanks for finding the paper! This is great news! Having looked through it
quickly, it looks like they have a completely different splitting heuristic
now:
"The decision to split traversal into both branches is based on the
estimated variance of the lighting within it. We consider two sources of
variance: the energy differences between the emitters in the tree and the
geometric term 1/d^2"

They also explain some other things that were unclear before, e.g. how they
aggregate bounding cones, their regularization factor that penalizes thin
bounding boxes in the tree construction, how they traverse the tree
"bottom-up" for a specific light when MIS is used, etc. This is great! I am
really happy about this.

Is it OK if I continue my work based on this paper instead of the
abstract/slides from 2017?

Thanks,
Erik

On 8 July 2018 at 23:31, Brecht Van Lommel <brechtvanlommel at gmail.com>
wrote:

> Hi,
>
> Thanks for the detailed analysis! I didn't have time yet to think though
> it all yet.
>
> The HPG paper appears to be here, hopefully it has some answers:
> http://www.aconty.com/pdf/many-lights-hpg2018.pdf
>
> Regards,
> Brecht.
>
>
>
>
> On Sat, Jul 7, 2018 at 8:25 AM Erik Englesson <erikenglesson at gmail.com>
> wrote:
>
>> Hi all,
>>
>> (Reposting this with a link to the figure instead.)
>>
>> Here is my weekly report:
>>
>> *This week* I have started the implementation of the split traversal
>> method. When traversing the tree, instead of always choosing between going
>> down the left or the right child, it is now also possible to go down both.
>> If a certain split heuristic is smaller than a user parameter then the
>> traversal goes down both children otherwise it chooses one of them. This
>> results in several lights being sampled at the same time instead of one.
>>
>> Here is a summary of what I have done:
>> * Added a GUI for setting the splitting threshold
>> * Recursive split traversal
>>       - A split heuristic based on the solid angle and the BSDF peak
>>       - At leaves, the path radiance is accumulated
>>       - Have created a simplified GGX evaluation that is not
>>         currently being used.
>> * Refactored common code
>>
>> This work can be found in this commit
>> <https://developer.blender.org/rB36cfc9e9fdc1>.
>>
>> *Next week* I plan to continue working on the split traversal. There are
>> still a lot of things that are unclear to me in the split heuristic. A more
>> detailed description of the split heuristic, what I have done and what I
>> find unclear can be found at the end of this email.
>>
>> Have a great weekend!
>>
>> Thanks,
>> Erik
>>
>> ------------------------------------------------------------
>> ------------------------------------------------------------
>>
>>
>> *Split Heuristic*
>>
>> This is how the authors describe the split heuristic on slide 20
>> <https://docs.google.com/viewer?a=v&pid=sites&srcid=ZGVmYXVsdGRvbWFpbnxja3VsbGF8Z3g6NWM0NmU2YWVlNjE3ODk1Yw>
>> :
>>
>> "To make the split decision on a cluster we take into account its subtended
>> solid angle from the shading point. Also the BSDF peak in case it is highly
>> specular pointing to the cluster. All together it gives us a number, easy
>> to normalize from zero to one."
>>
>> where they describe the BSDF peak as:
>>
>> "• BSDF peak is computed as follows:
>> 1. Sample a random direction from the BSDF
>> 2. Compute a conservative maximum cosine with the vector to the
>> cluster’s center
>> 3. Evaluate a simple GGX model with the BSDF roughness"
>>
>> My interpretation of the above, in pseudocode, looks like this:
>>
>> *bool split()*
>>
>> *{*
>>
>> *   Compute solid angle*
>>
>>
>> *   If BSDF is highly specular*
>> *      Sample BSDF to get the direction of the BSDF peak*
>> *      if BSDF peak points towards the cluster*
>>
>> *         Compute conservative cosine*
>>
>> *         Evaluate simplified GGX*
>> *         Calculate the BSDF peak by combining the GGX evaluation and the
>> conservative cosine*
>> *         Calculate the split heuristic by combining the BSDF peak and
>> solid angle*
>> *         Normalize the split heuristic*
>> *         Return true if the normalized split heuristic is less than
>> split threshold else false*
>>
>>
>> *    // No contribution from BSDF*
>> *   Normalize the solid angle*
>>
>> *   Return true if the normalized solid angle is less than split
>> threshold*
>> *}*
>>
>> This could be way off and if you think it should be some other way then
>> please let me know. This applies to anything written below too. Assuming my
>> interpretation is correct, there are still a lot of things that are
>> unclear. Let us go over what I have done this week and be more precise
>> about what I find unclear.
>>
>> *Solid Angle*
>> The solid angle is probably the least unclear part. The notation in the
>> figure below will be used in the rest of the email.
>>
>> https://wiki.blender.org/w/images/2/24/Splitting.png
>>
>> C is the center of the cluster, P is the shading point, N is the normal
>> at the shading point, d is the distance between C and P, r is the radius of
>> the bounding sphere, θmax is the maximum angle from the vector C-P that is
>> still inside the bounding sphere, and "BSDF direction" is the importance
>> sampled BSDF direction.
>>
>> I currently approximate the solid angle of the bounding box of the
>> cluster/node by the bounding sphere of the cluster/node:
>>
>> cos(θmax) = sqrt( 1 - sin^2(θmax) ) // sin^2 + cos^2 = 1
>> solid_angle = 2π(1 - cos(θmax))
>>
>> I might look into doing a more accurate solid angle calculation in a
>> later iteration.
>>
>> *BSDF Peak*
>> *If BSDF is highly specular*:
>> This is a bit simplified. What if the shading point has several BSDFs?
>> Maybe the best thing to do would be to loop over them and see if any of
>> them are highly specular. If so, choose one of these. How do you know if a
>> shader is highly specular?
>>
>> Currently, I use shader_bsdf_pick() to just randomly choose one of the
>> BSDFs. However, I think it could pick a diffuse BSDF even if there are
>> highly specular ones. Once a BSDF has been picked, I decide if it is highly
>> specular or not by looking at its roughness using
>> bsdf_get_roughness_squared().
>>
>> *if BSDF peak points towards the cluster*:
>> I sample a random direction from the BSDF with bsdf_sample() and
>> calculate θ and check if it is smaller or equal to θmax. See the figure
>> above. I might look into doing a more accurate intersection test in a later
>> iteration.
>>
>> *Compute conservative cosine*:
>> The conservative cosine is described like this:
>> "Compute a conservative maximum cosine with the vector to the cluster’s
>> center"
>>
>> Option 1
>> My current best guess is that they refer to a conservative cosine for the
>> angle between the cluster's center and the normal N. Something like this:
>>
>> NI = arccos( dot( normalize( C-P), N) )
>> conservative_cosNI = cos( clamp( NI - θmax, 0.0, π/2 - θmax) )
>>
>> See the figure above for what C, P, N, and θmax are referring to. This
>> is similar to what they did for the "conservative cosine factor to the
>> orientation bounds". The conservative angle essentially becomes the
>> smallest possible angle between any light in the node and the normal.
>>
>> Sidenote: A small issue with this is that the conservative angle will be
>> between 0 and π/2 - θmax, which means the conservative cosine will never be
>> less than cos(π/2 - θmax). This is something I will look at in the next
>> iteration. It would be nicer to have the conservative cosine be 1 for all
>> angles less than θmax and a cosine falloff from 1 to 0 between θmax and π/2
>> and 0 otherwise. Maybe something like this:
>>
>> if(NI < θmax)
>>   NI = 0
>> else if(θ > π/2)
>>   NI = π/2
>> else // NI ∈ [ θmax, π/2 ]
>>   NI = π/2  *  (NI - θmax) / (π/2 - θmax) // have to be careful if
>> θmax=π/2
>>
>> The else case essentially scales [ θmax, π/2 ] to [ 0, π/2 ].
>>
>> Option 2
>> Another interpretation of the "Also the BSDF peak in case it is highly
>> specular pointing to the cluster." could be that it is up to the
>> conservative cosine to scale directions not pointing to the cluster. That
>> is, to not do the if-check described in "if BSDF peak points towards the
>> cluster" and instead have the conservative cosine be for the angle between
>> the cluster's center and the sampled direction. Multiplication with the
>> conservative cosine then acts like a more forgiving if-check. Something
>> like this:
>>
>> conservative_cos = cos( clamp(θ - θmax, 0.0, π/2 - θmax) )
>> (see the figure)
>> If the BSDF direction is inside the bounding sphere then the cosine term
>> will be 1 otherwise there will be a cosine falloff with the same issue as
>> mentioned in the sidenote above. It is a bit strange for a highly specular
>> BSDF to have a non-zero contribution for all directions, or even for all
>> directions in the hemisphere if something like the sidenote is done. This
>> makes me think this option is less likely, but I am not sure.
>>
>>
>> *Evaluate simplified GGX: *
>> Which direction should be used as the light direction in the GGX
>> evaluation?
>>
>> Option 1: Direction to the center of the cluster
>> The BSDF is highly specular so there is a high risk of this direction to
>> evaluate to zero? Even if there are other directions within the cluster
>> that are non-zero. Makes me think this option is unlikely.
>>
>> Option 2: Direction from importance sampling of BSDF
>> We know this direction is pointing towards the cluster, so it is not
>> unreasonable to me to consider it as a light direction. This is the
>> direction I currently use. However, since I use bsdf_sample() to get the
>> direction I get the evaluation of it at the same time. This means that I do
>> not do any GGX evaluations currently. However, I think it is more efficient
>> to only sample a random direction without evaluation first and only if this
>> direction points towards the cluster then a simplified GGX is evaluated.
>>
>> *Calculate the BSDF peak by combining the GGX evaluation and the
>> conservative cosine:*
>> The computation of the BSDF peak was described as three different steps,
>> but it is unclear to me how these should be combined. Currently, I just
>> multiply the conservative cosine with the BSDF evaluation.
>>
>>
>> *Solid Angle "times" BSDF Peak*
>> On slide 20 again the authors write that the split heuristic should(?):
>> "Approximate solid angle times BSDF peak"
>>
>> *Calculate the split heuristic by combining the BSDF peak and solid angle*
>> The BSDF peak is a float3 with the current way of generating it(BSDF
>> evaluation returns a float3) and the solid angle is just a float value,
>> while the split heuristic is supposed to be a number. We need some way of
>> combining the BSDF peak and the solid angle into a number.
>>
>> I do not know how to do this and the way I do it now is just by
>> multiplying the BSDF peak and the solid angle and take the maximum
>> component. Is there a standard way of doing this?
>>
>> *Normalize the split heuristic:*
>> The splitting heuristic should be normalized between zero and one. To be
>> able to do this, we need to know the bounds of the BSDF, the conservative
>> cosine, and the solid angle.
>>
>> The bounds of a general BSDF does not necessarily have to be within
>> [0,1]^3, right? It is probably hard to have an upper bound for a general
>> BSDF, but maybe that is one of the reasons they evaluate a simplified GGX
>> which they know how to bound?
>>
>> I think the range of the conservative cosine is [cos(π/2 - θmax), 1] with
>> the current implementation.
>>
>> The absolute maximum for the solid angle is 4π (area of the entire unit
>> sphere). However, since P cannot be inside the bounding box(then always
>> split) I think the upper bound for the solid angle actually is 2π, i.e.
>> entire hemisphere?
>>
>> In the abstract/paper the authors write:
>> "We drive this scoring process by both the bounding box of the cluster
>> (clusters that contain the shading point are always split) but also by an
>> approximation of the BRDF’s cone of influence to *give higher weight* to
>> distant clusters that are likely to fall within the specular highlight."
>>
>> So, the combination of the BSDF peak and the solid angle should make it
>> more likely for it to split than if it is only based on the solid angle.
>>
>> The first thing I thought of was to normalize the solid angle and the
>> BSDF peak separately and then combine them by multiplying them. However, if
>> both these are numbers between zero and one then their combination will be
>> smaller or equal to the normalized solid angle. This is not what we want,
>> but it is what I currently do.
>>
>> ------------------------------------------------------------
>> ------------------------------------------------------------
>>
>> As we have seen above. There are a lot of things that need to be
>> clarified and fixed next week. Please let me know if there is anything that
>> you think is strange/unclear/wrong above, then it most probably is.
>>
>> Fun fact: I saw that the same authors will have a presentation
>> <http://www.highperformancegraphics.org/2018/program/> with the same
>> name(Importance Sampling of Many Lights With Adaptive Tree Splitting) at
>> the High-Performance Graphics conference on August 10th. Maybe they plan to
>> clarify their method or have improved it or both?
>>
>> Random idea: Would it make sense to have the throughput of the path
>> affect the splitting heuristic too? Say times BSDF peak.
>>
>> Thanks for your time.
>>
>> --
>> Soc-2018-dev mailing list
>> Soc-2018-dev at blender.org
>> https://lists.blender.org/mailman/listinfo/soc-2018-dev
>>
>
> --
> Soc-2018-dev mailing list
> Soc-2018-dev at blender.org
> https://lists.blender.org/mailman/listinfo/soc-2018-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.blender.org/pipermail/soc-2018-dev/attachments/20180709/2d6bb0a8/attachment-0001.html>


More information about the Soc-2018-dev mailing list