this option was already unselectable in the UI, and is treated as GGX
with zero roughness. Upon building the shader graph, we only convert a
closure to `SHARP` when option Filter Glossy is not used and the
roughness is below certain threshold. The benefit is that we can avoid
calling `bsdf_eval()` or return earlier in some cases, but the thresholds
vary across files.
This patch removes `SHARP` closures altogether, and checks if the
roughness value is below a global threshold `BSDF_ROUGHNESS_THRESH`
after blurring, in which case the flag `SD_BSDF_HAS_EVAL` is not set.
The global threshold is set to be `5e-7f` because threshold smaller than
that seems to have caused problem in the past (c6aa0217ac). Also removes
a bunch of functions, variables and arguments that were only there
because we converted closures under certain conditions.
Pull Request: https://projects.blender.org/blender/blender/pulls/109902
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
When baking only indirect lighting, light sampling is skipped at the
first bounce. However, light evaluation is still done, so depending
on how the MIS weights end up more or less of the direct lighting
still ends up in the bake.
This is most noticeable with background lighting, but can also be
reproduced with e.g. point lights with a large radius.
Pull Request: https://projects.blender.org/blender/blender/pulls/108955
The problem here was that when direct light contibutions to baking were
disabled, the kernel just skipped all direct lighting evaluation.
However, at secondary bounces, "direct light" would actually end up
being indirect (since there's an extra bounce along the way), but
we're still skipping it.
Therefore, only apply direct lighting skipping at the first bounce.
So far, each closure in Cycles was either diffuse OR glossy OR
transmissive, and its color and contributions were assigned
to the corresponding direct/indirect/color passes.
However, since Glass is a single closure now, that is no longer enough,
since glass has both a glossy and a transmissive component.
Therefore, this commit adds support for splitting contributions from
the Glass closure between the two types.
For 4.0, we might want to also use this for Principled Hair since it
also technically has both types, but that would be a change from
the existing result so it's not part of 3.6 yet.
A couple of mistakes since the light linking commit:
- The +1 got missed in some of the refactors in the branch
- The order of arguments to the shadow path split was wrong
Pull Request: https://projects.blender.org/blender/blender/pulls/108420
The original names were `...update_position()`, but no update in
position is performed in these functions, rather, the entries in
`LightSample` are updated. Also make clear that the functions are used
by MNEE.
After the removal of the Shadow pass this no longer worked. Now it works by
marking the object as a shadow catcher and returning the Shadow Catcher pass.
The result is different than before, since it also takes into account indirect
light now and uses a different method to weight the contribution of lights that
is adaptive to the light strength.
This is a workaround fix for Open PGL 0.4.1 when the first volume
samples are collected in a later training iteration.
The problem is fixed in Open PGL > 0.5.0 and the workaround
can be removed after upgrading Open PGL.
This commit replaces the current Glass approach, where Glass is a virtual closure
that gets replaced with a Glossy and a Refractive closure, with a combined
closure that handles Fresnel after sampling the microfacet. That way, the Fresnel
term is more accurate since it accounts for the microfacet normal, not the
shading normal.
Also updates the BSDF sampling to use a 3D sampler now, since we need two
dimensions to pick the microfacet normal and then a third dimension to pick
reflection/refraction. This can also be used to get rid of the LCG in the
Principled Hair BSDF, which means we can remove it altogether once MultiGGX is
gone.
Also, "sharp" is now supported as a microfacet distribution in OSL, and 2
is supported as the "refract" argument to microfacet() in order to get glass.
To improve mesh upload speeds and reduce the size of the scene data which allows larger scenes to be rendered.
The meshes in Cycles are currently stored as flattened meshes, where each triangle is stored as a set of 3 vertices. Unflattening writes out the vertices in a list according to the index buffer. This uses a lot of memory and for current hardware does not provide a noticeable benefit. This change unflattens the mesh by directly using the meshes vertex and index buffers directly and skips the unflattening. This change allows for larger scenes and also a reduction in the sizes of the meshes. Further it results in a decrease the amount of time it takes to upload the data to a GPU. This is especially important for when multiple GPUs are used in a single machine.
Pull Request #105173
This reverts commit 19222627c6.
Something went wrong here, seems like this commit merged the main branch
into the release branch, which should never be done.
This patch adds two new kernels: SORT_BUCKET_PASS and SORT_WRITE_PASS. These replace PREFIX_SUM and SORTED_PATHS_ARRAY on supported devices (currently implemented on Metal, but will be trivial to enable on the other backends). The new kernels exploit sort partitioning (see D15331) by sorting each partition separately using local atomics. This can give an overall render speedup of 2-3% depending on architecture. As before, we fall back to the original non-partitioned sorting when the shader count is "too high".
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D16909
This is both a cleanup and a preparation for the Principled v2 changes.
Notable changes:
- Clearcoat weight is now folded into the closure weight, there's no reason
to track this separately.
- There's a general-purpose helper for computing a Closure's albedo, which is
currently used by the denoising albedo and diffuse/gloss/transmission color
passes.
- The d/g/t color passes didn't account for closure albedo before, this means
that e.g. metallic shaders with Principled v2 now have their color texture
included in the glossy color pass. Also fixes T104041 (sheen albedo).
- Instead of precomputing and storing the albedo during shader setup, compute
it when needed. This is technically redundant since we still need to compute
it on shader setup to adjust the sample weight, but the operation is cheap
enough that freeing up the storage seems worth it.
- Future changes (Principled v2) are easier to integrate since the Fresnel
handling isn't all over the place anymore.
- Fresnel handling in the Multiscattering GGX code is still ugly, but since
removing that entirely is the next step, putting effort into cleaning it up
doesn't seem worth it.
- Apart from the d/g/t color passes, no changes to render results are expected.
Differential Revision: https://developer.blender.org/D17101
The background evaluation samples the sky discretely, so if the sun is
too small, it can be missed in the evaluation. To solve this, the sun is
ignored during the background evaluation and its contribution is
computed separately.
wi is the viewing direction, and wo is the illumination direction. Under this notation, BSDF sampling always samples from wi and outputs wo, which is consistent with most of the papers and mitsuba. This order is reversed compared with PBRT, although PBRT also traces from the camera.
When rendering in the viewport (or probably on instanced objects, but I didn't
test that), emissive objects whose scale is negative give the wrong value on the
"backfacing" input when multiple sampling is enabled.
The underlying problem was a corner case in how normal transformation is handled,
which is generally a bit messy.
From what I can tell, the pattern appears to be:
- If you first transform vertices to world space and then compute the normal from
them (as triangle light samping, MNEE and light tree do), you need to flip
whenever the transform has negative scale regardless of whether the transform
has been applied
- If you compute the normal in object space and then transform it to world space
(as the regular shader_setup_from_ray path does), you only need to flip if the
transform was already applied and was negative
- If you get the normal from a local intersection result (as bevel and SSS do),
you only need to flip if the transform was already applied and was negative
- If you get the normal from vertex normals, you don't need to do anything since
the host-side code does the flip for you (arguably it'd be more consistent to
do this in the kernel as well, but meh, not worth the potential slowdown)
So, this patch fixes the logic in the triangle emission code.
Also, turns out that the MNEE code had the same problem and was also having
problems in the viewport on negative-scale objects, this is also fixed now.
Differential Revision: https://developer.blender.org/D16952