Dropping the inlining hint for `light_tree_pdf` and reverting to the
default inlining thresholds for DPC++ compiler gives a ~4% speedup on
classroom and other scenes on Arc B580.
Pull Request: https://projects.blender.org/blender/blender/pulls/135042
This is an intermediate steps towards making lights actual geometry.
Light is now a subclass of Geometry, which simplifies some code.
The geometry is not added to the BVH yet, which would be the next
step and improve light intersection performance with many lights.
This makes object attributes work on lights.
Co-authored-by: Lukas Stockner <lukas@lukasstockner.de>
Pull Request: https://projects.blender.org/blender/blender/pulls/134846
In a previous commit (1), adjustments to light tree traversal were made
to try and skip distant lights when deciding which light to sample
while within a world volume.
The skip wasn't implemented properly, and as a result distant lights
were still included in the light tree traversal in that sitaution.
And due to the way the skip was implemented, there were some
unintialized variables used in the processing of the distant lights
importance which caused artifacts on some platforms.
This commit fixes this issue by reverting the skip of distant lights
in that situation.
(1) blender/blender@6fbc958e89
Pull Request: https://projects.blender.org/blender/blender/pulls/132344
Check was misc-const-correctness, combined with readability-isolate-declaration
as suggested by the docs.
Temporarily clang-format "QualifierAlignment: Left" was used to get consistency
with the prevailing order of keywords.
Pull Request: https://projects.blender.org/blender/blender/pulls/132361
* Use .empty() and .data()
* Use nullptr instead of 0
* No else after return
* Simple class member initialization
* Add override for virtual methods
* Include C++ instead of C headers
* Remove some unused includes
* Use default constructors
* Always use braces
* Consistent names in definition and declaration
* Change typedef to using
Pull Request: https://projects.blender.org/blender/blender/pulls/132361
When a scene contains distant lights and local lights, the first step
of the light tree traversal is to compute the importance of
distant lights vs local lights and pick one based on a random number.
In the specific case of when there is only one distant light,
the line of code that had been changed in this commit
effectively reduced to:
`min_importance = fast_cosf(x) < cosf(x) ? 0.0 : compute_min_importance`
And depending on the hardware, compiler, and the specific value being
tested, different configurations could take different code paths.
This commit fixes this issue by turning the comparison into
`fast_cosf(x) < fast_cosf(x)`.
---
Why does `cos_theta_plus_theta_u < cosf(bcone.theta_e - bcone.theta_o)`
reduce to `fast_cos(x) < cos(x)` in this specific case?
- `cos_theta_plus_theta_u` is computed as
`cos_theta * cos_theta_u - sin_theta * sin_theta_u`
- `cos_theta` is always 1.0 in the case of a single distant light.
- `cos_theta_u` is computed earlier as `fast_cosf(theta_e)` in
`distant_light_tree_parameters()`
- `sin_theta` is zero, and so that side of the equation doesn't matter.
This reduces `cos_theta_plus_theta_u` to `fast_cosf(theta_e)`.
`cosf(bcone.theta_e - bcone.theta_o)` reduces to `cosf(bcone.theta_e)`
because for the case of a single distant light `theta_o` is always 0.
Pull Request: https://projects.blender.org/blender/blender/pulls/131932
In volume segment, the minimal angle formed by the emitter bounding cone
axis and the vector pointing from the cluster centroid to any point on
the ray is computed via `dot(bcone.axis, point_to_centroid)`, see Fig.8.
in paper.
For distant light this angle is 0, but due to numerical issues this is
not always true. Therefore explicitly assign `-bcone.axis` to
`point_to_centroid` in this case.
Pull Request: https://projects.blender.org/blender/blender/pulls/129489
Gitea would complain the apostrophe in one of the code comments in
tree.h was an ambiguous Unicode character. So fix it by swapping it
for a more common apostrophe type.
Use a bounding sphere instead of the corners of a bounding box to
compute the subtended angle of a light tree node.
Using the corners of the bounding box was an underestimate in some
scenes, causing some light tree nodes being incorrectly skipped.
Using the subtended angle of a bounding sphere is an overestimate, but
it covers the entire node and would not skip any valid contribution,
and no other reliable algorithm to compute the minimal enclosing angle
is known to us.
We expect some increase in noise due to overestimation, but this has
not been observed yet, in our benchmark scenes only a difference in
noise is visible.
Thanks to Weizhen for the suggestion to use the bounding sphere.
Pull Request: https://projects.blender.org/blender/blender/pulls/126625
The original paper only considers the minimal distance of the cluster to
the ray, not the interval length, resulting in low weight for distant
lights that have large influence over a long distance.
This commit modifies the measure by considering `theta_b - theta_a` for
local lights and the ray length `t` for distant lights.
Pull Request: https://projects.blender.org/blender/blender/pulls/123537
In the original paper, the falloff inside `bcone.theta_e` is assumed to
be `pi/2`, which is too large for spot light and resulted in an
overestimation near the cone boundary.
To address this issue, attenuate the energy of a spot light using the
minimal possible angle formed by the light axis and the shading point
when traversing the light tree.
Ref: #122362
Pull Request: https://projects.blender.org/blender/blender/pulls/122667
it is not clear from which point the `cos_theta_u` should be computed in
volume segment, so the original implementation was mixing the closest point
and the point where the minimal angle is formed.
Use the closest point on segment as a conservative measure.
Pull Request: https://projects.blender.org/blender/blender/pulls/119965
in the test scene `all_light_types_in_volume.blend`, `theta - theta_o -
theta_u` is slightly above the threshold. Even if we do a strict check
with `acos` on the failing cases, it will go to the other branch and
deliver a result which is also 1.0f. Better to relax the threshold.
The same random number was used when sampling from the volume segment
and from the direct scattering position, causing correlation issues with
light tree.
To solve this problem, we ensure the same light is picked for
volume segment/direct scattering, equiangular/distance sampling by
sampling the light tree only once in volume segment. From the direct
scattering position in volume, we sample a position on the picked light
as usual. If sampling from the light tree fails, we continue with
indirect scattering.
For unbiased MIS weight for forward sampling, we retrieve the `P`, `D`
and `t` used in volume segment for traversing the light tree.
The main changes are:
1. `light_tree_sample()` and `light_distribution_sample()` now only pick
lights. Sampling a position on light is done separately via
`light_sample()`.
2. `light_tree_sample()` is now only called only once from volume
segment. For direct lighting we call `light_sample()`.
3. `light_tree_pdf()` now has a template `<in_volume_segment>`.
4. A new field `emitter_id` is added to struct `LightSample`, which just
stores the picked emitter index.
5. Additional field `previous_dt = ray->tmax - ray->tmin` is added to
`state->ray`, because we need this quantity for computing the pdf.
6. Distant/Background lights are also picked by light tree in volume
segment now, because we have no way to pick them afterwards. The direct
sample event for these lights will be handled by
`VOLUME_SAMPLE_DISTANCE`.
7. Original paper suggests to use the maximal importance, this results
in very poor sampling probability for distant and point lights therefore
excessive noise. We have a minimal importance for surface to balance, we
could do the same for volume but I do not want to spend much time on
this now. Just doing `min_importance = 0.0f` seems to do the job
okayish. This way we still won't sample the light with zero
`max_importance`.
The current solution might perform worse with distance sampling, because
the light tree measure is biased towards equiangular sampling. However,
it is difficult to perform MIS between equiangular and distance sampling
if different lights are picked for each method. This is something we can
look into in the future if proved to be a serious regression.
Pull Request: https://projects.blender.org/blender/blender/pulls/119389
When using light linking with the light tree, the root index of a
mesh light subtree can be 0. The current code assumed this wasn't
possible, and as such it caused rendering issues, specifically the
incorrect computation of the PDF of certain mesh lights during
forward path tracing.
So we adjust the code to allow mesh light subtree root node
indices of 0.
This was worked on by Alaska, Sergey, and Weizhen
Pull Request: https://projects.blender.org/blender/blender/pulls/119770
This reverts commit 206ab6437b.
Seems that the illegal address error should be covered elsewhere, but it's not directly
clear where. Revert the commit for further investigation.
Discovered during an investigation into #111277
in rare situations (E.G. When normals are NaN), an emitter
won't be selected as part of `light_tree_cluster_select_emitter()`
and as a result of that, an `emitter_index` of `-1` is passed to
`kernel_data_fetch(light_tree_emitters, emitter_index)` resulting in
an "illegal address" error on some devices.
Pull Request: https://projects.blender.org/blender/blender/pulls/111292
This pull request covers up a subtle difference between the CPU and GPU
when rendering with a light tree. Specifically a case where the user
has a sun light with a small angle.
The difference was caused by the dot() function being different between
CPU and GPU backends, with the GPU showing more meaningful
floating-point precision losses when working with small suns.
Pull Request: https://projects.blender.org/blender/blender/pulls/110307
for energy preservation and better compatibility with other renderes. Ref: #108505
Point light now behaves the same as a spherical mesh light with the same overall energy (scaling from emission strength to power is \(4\pi^2R^2\)).
# Cycles
## Comparison
| Mesh Light | This patch | Previous behavior |
| -------- | -------- | -------- |
|  |  |  |
The behavior stays the same when `radius = 0`.
| This patch | Previous behavior |
| -------- | -------- |
|  |  |
No obvious performance change observed.
## Sampling
When shading point lies outside the sphere, sample the spanned solid angle uniformly.
When shading point lies inside the sphere, sample spherical direction uniformly when inside volume or the surface is transmissive, otherwise sample cosine-weighted upper hemisphere.
## Light Tree
When shading point lies outside the sphere, treat as a disk light spanning the same solid angle.
When shading point lies inside the sphere, it behaves like a background light, with estimated outgoing radiance
\[L_o=\int f_aL_i\cos\theta_i\mathrm{d}\omega_i=\int f_a\frac{E}{\pi r^2}\cos\theta_i\mathrm{d}\omega_i\approx f_a \frac{E}{r^2}\],
with \(f_a\) being the BSDF and \(E\) `measure.energy` in `light_tree.cpp`.
The importance calculation for `LIGHT_POINT` is
\[L_o=f_a E\cos\theta_i\frac{\cos\theta}{d^2}\].
Consider `min_importance = 0` because maximal incidence angle is \(\pi\), we could substitute \(d^2\) with \(\frac{r^2}{2}\) so the averaged outgoing radiance is \(f_a \frac{E}{r^2}\).
This only holds for non-transmissive surface, but should be fine to use in volume.
# EEVEE
When shading point lies outside the sphere, the sphere light is equivalent to a disk light spanning the same solid angle. The sine of the new half-angle is the tangent of the previous half-angle.
When shading point lies inside the sphere, integrating over the cosine-weighted hemisphere gives 1.0.
## Comparison with Cycles
The plane is diffuse, the blue sphere has specular component.
| Before | |After ||
|---|--|--|--|
|Cycles|EEVEE|Cycles|EEVEE|
|||||
Pull Request: https://projects.blender.org/blender/blender/pulls/108506
This fixes an issue where the light tree sampling algorithm would
discard light samples from groups of distance lights with an angle
greater than 0 when it shouldn't.
Pull Request: https://projects.blender.org/blender/blender/pulls/108832
This will make further changes for light linking easier, where we want to
build multiple trees specialized for each light linking set.
It's also easier to understand than the stack used previously.
Pull Request: https://projects.blender.org/blender/blender/pulls/107560
The first two dimensions of scrambled, shuffled Sobol and shuffled PMJ02 are
equivalent, so this makes no real difference for the first two dimensions.
But Sobol allows us to naturally extend to more dimensions.
Pretabulated Sobol is now always used, and the sampling pattern settings is now
only available as a debug option.
This in turn allows the following two things (also implemented):
* Use proper 3D samples for combined lens + motion blur sampling. This
notably reduces the noise on objects that are simultaneously out-of-focus
and motion blurred.
* Use proper 3D samples for combined light selection + light sampling.
Cycles was already doing something clever here with 2D samples, but using
3D samples is more straightforward and avoids overloading one of the
dimensions.
In the future this will also allow for proper sampling of e.g. volumetric
light sources and other things that may need three or four dimensions.
Differential Revision: https://developer.blender.org/D16443
There has been an attempt to reorganize this part, however, it seems that didn't compile on HIP, and is reverted in
rBc2dc65dfa4ae60fa5d2c3b0cfe86f99dcb5bf16f. This is another attempt of refactoring. as I have no idea why some things don't work on HIP, it's
best to check whether this compiles on other platforms.
The main changes are creating a new struct named `MeshLight` that is shared between `KernelLightDistribution` and `KernelLightTreeEmitter`,
and a bit of renaming, so that light sampling with or without light tree could call the same function.
Also, I noticed a patch D16714 referring to HIP compilation error. Not sure if it's related, but browsing
https://builder.blender.org/admin/#/builders/30/builds/7826/steps/7/logs/stdio, it didn't work on gfx1102, not gfx9*.
Differential Revision: https://developer.blender.org/D16722
Uses a light tree to more effectively sample scenes with many lights. This can
significantly reduce noise, at the cost of a somewhat longer render time per
sample.
Light tree sampling is enabled by default. It can be disabled in the Sampling >
Lights panel. Scenes using light clamping or ray visibility tricks may render
different as these are biased techniques that depend on the sampling strategy.
The implementation is currently disabled on AMD HIP. This is planned to be fixed
before the release.
Implementation by Jeffrey Liu, Weizhen Huang, Alaska and Brecht Van Lommel.
Ref T77889