* 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
Previously, Cycles only supported the Henyey-Greenstein phase function for volume scattering.
While HG is flexible and works for a wide range of effects, sometimes a more physically accurate
phase function may be needed for realism.
Therefore, this adds three new phase functions to the code:
Rayleigh: For particles with a size below the wavelength of light, mostly athmospheric scattering.
Fournier-Forand: For realistic underwater scattering.
Draine: Fairly specific on its own (mostly for interstellar dust), but useful for the next entry.
Mie: Approximates Mie scattering in water droplets using a mix of Draine and HG phase functions.
These phase functions can be combined using Mix nodes as usual.
Co-authored-by: Lukas Stockner <lukas@lukasstockner.de>
Pull Request: https://projects.blender.org/blender/blender/pulls/123532
Add Metallic BSDF Node to the shader editor.
This node can primarily be used to create more realistic looking
metallic materials than the existing Glossy BSDF node.
This commit does not add any new closures to Cycles, it simply exposes
existing closures that were previous hard to access on their own.
- Exposes the F82 fresnel type that is currently used by the
metallic component of the Principled BSDF. Results should match
between the Metallic BSDF and Principled BSDF when using the same
settings.
- Exposes the Physical Conductor fresnel type that was previously
limited to custom OSL scripts. The Conductor fresnel type accepts
IOR and Extinction coefficients to define the appearance of the
material based off real life measurements.
EEVEE only supports the F82 fresnel type with internal code to convert
the the physical conductor inputs in to a colour format for F82,
which can lead to noticeable rendering differences with
some configurations.
Pull Request: https://projects.blender.org/blender/blender/pulls/114958
Setting this option to a value above zero replaces the lambertian Diffuse term
with the modified energy-preserving Oren-Nayar BSDF, which matches the OpenPBR
behavior.
Pull Request: https://projects.blender.org/blender/blender/pulls/123616
This patch implements a new Gabor noise node based on [1] but with the
improvements from [2] and the phasor formulation from [3].
We compare with the most popular existing implementation, that of OSL,
from the user's point of view:
- This implementation produces C1 continuous noise as opposed to the
non continuous OSL implementation, so it can be used for bump
mapping and is generally smother. This is achieved by windowing the
Gabor kernel using a Hann window.
- The Bandwidth input of OSL was hard-coded to 1 and was replaced with
a frequency input, which OSL hard codes to 2, since frequency is
more natural to control. This is even more true now that that Gabor
kernel is windowed as opposed to truncated, which means increasing
the bandwidth will just turn the Gaussian component of the Gabor
into a Hann window. While decreasing the bandwidth will eliminate
the harmonic from the Gabor kernel, which is the point of Gabor
noise.
- OSL had three discrete modes of operation for orienting the kernel.
Anisotropic, Isotropic, and a hybrid mode. While this implementation
provides a continuous Anisotropy parameter which users are already
familiar with from the Glossy BSDF node.
- This implementation provides not just the Gabor noise value, but
also its phase and intensity components. The Gabor noise value is
basically sin(phase) * intensity, but the phase is arguably more
useful since it does not suffer from the low contrast issues that
Gabor suffers from. While the intensity is useful to hide the
singularities in the phase.
- This implementation converges faster that OSL's relative to the
impulse count, so we fix the impulses count to 8 for simplicitly.
- This implementation does not implement anisotropic filtering.
Future improvements to the node includes implementing surface noise and
filtering. As well as extending the spectral control of the noise,
either by providing specialized kernels as was done in #110802, or by
providing some more procedural control over the frequencies of the
Gabor.
References:
[1]: Lagae, Ares, et al. "Procedural noise using sparse Gabor
convolution." ACM Transactions on Graphics (TOG) 28.3 (2009): 1-10.
[2]: Tavernier, Vincent, et al. "Making gabor noise fast and
normalized." Eurographics 2019-40th Annual Conference of the European
Association for Computer Graphics. 2019.
[3]: Tricard, Thibault, et al. "Procedural phasor noise." ACM
Transactions on Graphics (TOG) 38.4 (2019): 1-13.
Pull Request: https://projects.blender.org/blender/blender/pulls/121820
This multiscattering term comes from the OpenPBR specification and nicely
preserves energy while correctly modeling increased saturation at high
roughness.
Preparation for adding a diffuse roughness option to the Principled BSDF.
To me, the difference in output and computation seems small enough to
not need an enum for the old behavior.
Note that this also switches sampling to cosine-weighted, in my tests this
gives lower noise. I also checked doing MIS between cosine and uniform,
using the A term as a weight for how often to use cosine (since that term
is Lambertian diffuse), but always using cosine was better.
A nice consequence of that is that you don't get a huge noise jump when
going from 0.0 to 0.01 roughness.
Pull Request: https://projects.blender.org/blender/blender/pulls/123345
This is an implementation of thin film iridescence in the Principled BSDF based on "A Practical Extension to Microfacet Theory for the Modeling of Varying Iridescence".
There are still several open topics that are left for future work:
- Currently, the thin film only affects dielectric Fresnel, not metallic. Properly specifying thin films on metals requires a proper conductive Fresnel term with complex IOR inputs, any attempt of trying to hack it into the F82 model we currently use for the Principled BSDF is fundamentally flawed. In the future, we'll add a node for proper conductive Fresnel, including thin films.
- The F0/F90 control is not very elegantly implemented right now. It fundamentally works, but enabling thin film while using a Specular Tint causes a jump in appearance since the models integrate it differently. Then again, thin film interference is a physical effect, so of course a non-physical tweak doesn't play nicely with it.
- The white point handling is currently quite crude. In short: The code computes XYZ values of the reflectance spectrum, but we'd need the XYZ values of the product of the reflectance spectrum and the neutral illuminant of the working color space. Currently, this is addressed by just dividing by the XYZ values of the illuminant, but it would be better to do a proper chromatic adaptation transform or to use the proper reference curves for the working space instead of the XYZ curves from the paper.
Pull Request: https://projects.blender.org/blender/blender/pulls/118477
Transport rays that enter to another location in the scene, with
specified ray position and normal. This may be used to render portals
for visual effects, and other production rendering tricks.
This acts much like a Transparent BSDF. Render passes are passed
through, and this is affected by light path max transparent bounces.
Pull Request: https://projects.blender.org/blender/blender/pulls/114386
This replaces the fixed Tangent input in BsdfNode::compile
with a custom input.
This is done because very few nodes actually use the tangent input
and it would be better to have this slot available for other inputs
on different nodes in the future.
Pull Request: https://projects.blender.org/blender/blender/pulls/119042
This path merges the Musgrave and Noise Texture nodes into a single
combined Noise Texture node. The reasoning is that both nodes
intrinsically do the same thing, which is the layering of Perlin noise
derivatives to produce fractal noise. So the patch de-duplicates code
and unifies the use of fractal noise for the end use.
Since the Noise node had a Distortion input and a Color output, while
the Musgrave node did not, those are now available to the Musgrave types
as new functionalities.
The Dimension input of the Musgrave node is analogous to the Roughness
input of the Noise node, so both inputs were unified to follow the same
behavior of the Roughness input, which is arguable more intuitive to
control. Similarly, the Detail input was slightly different across both
nodes, since the Noise node evaluated one extra layer of noise. This was
also unified to follow the behavior of the Noise node.
The patch, coincidentally fixes an unreported bug causing repeated
output for certain noise types and another floating precision bug
#112180.
The versioning code implemented with this patch ensures backward
compatibility for both the Musgrave and Noise Texture nodes. When
opening older Blender files in Blender 4.1 the output of both nodes are
guaranteed to always be exactly identical to that of Blender files
created before the nodes were merged in all cases.
Forward compatibility with Blender 4.0 is implemented by #114236.
Forward compatibility with Blender 3.6 LTS is implemented by #115015.
Pull Request: #111187
This was a regression after the sphere light changes, where the normal
now is the normal along the geometry of the light and no longer suitable
for the IES texture direction.
This not only fixes point lights with non-zero radius, but makes the IES
texture direction work consistently across light types and meshes,
always rotated by the object transform.
Update the Glass BSDF to internally use Generalized Schlick fresnel.
This allows for easier expansion of certain features in the future.
There should be no functional change from the users perspective.
Pull Request: https://projects.blender.org/blender/blender/pulls/112701
This was causing a warning when using OSL, since the OSL implementation
didn't implement the input.
Since the socket isn't really implemented on the Blender side anyways,
just get rid of it.
Also, the SVM code uses the shading normal while OSL used the geometric normal.
- Changes defaults from Emission Color 0.0, Emission Strength 1.0 to be the
other way around (Color 1.0, Strength 0.0), suggested by @brecht
- Makes emission component occluded by sheen and coat
(to simulate e.g. dust-covered light sources)
- Moves transparency into the Principled SVM/OSL node, to allow for future
support for e.g. transparent shadows in thin sheet mode.
Note that there are optimization opportunities here (mostly skipping the
non-transparent components for transparent shadow evaluation, and skipping
the parts that don't affect emission for light evaluation), but I have a
separate point for those in the Principled V2 planning since there's some
other optimization topics as well.
Co-authored-by: Weizhen Huang <weizhen@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/111155
Previously, the Principled BSDF used the Subsurface input to scale the radius.
When it was zero, it used a diffuse closure, otherwise a subsurface closure.
This sort of scaling input makes sense, but it should be specified in distance
units, rather than a 0..1 factor, so this commit changes the unit and renames
the input to Subsurface Scale.
Additionally, it adds support for mixing diffuse and subsurface components.
This is part of e.g. the OpenPBR spec, and the logic behind it is to support
modeling e.g. dirt or paint on top of skin. Before, materials would be either
fully diffuse (radius=0) or fully subsurface.
For typical materials, this mixing factor will be either zero or one
(just like metallic or transmission), but supporting fractional inputs makes
sense for e.g. smooth transitions at boundaries.
Another change is that there is no separate Subsurface Color anymore - before,
this was mixed with the Base Color using the Subsurface input as the factor,
but this was not really useful since that input was generally very small.
And finally, the handling of how the path enters the material for random walk
subsurface scattering is changed. Before, this always used lambertian (diffuse)
transmission, but this caused some problems, like overly white edges.
Instead, two different methods are now used, depending on the selected mode.
In Fixed Radius mode, the code assumes a simple medium boundary, and performs
refraction into the material using the main Roughness and IOR inputs.
Meanwhile, when not using Fixed Radius, the code assumes a more complex
boundary (as typically found on organic materials, e.g. skin), so the entry
bounce has a 50/50 chance of being either diffuse transmission or refraction
using the separate Subsurface IOR input and a fixed roughness of 1.
Credit for this method goes to Christophe Hery.
Pull Request: https://projects.blender.org/blender/blender/pulls/110989
- Adds tint control, which simulates volumetric absorption inside the coating.
This results in angle-dependent saturation and affects all underlying layers
(diffuse, subsurface, metallic, transmission). It provides a physically-based
alternative to ad-hoc effects such as tinted specular highlights.
- Renames the component from "Clearcoat" to "Coat", since it's no longer
necessarily clear now. This matches naming in e.g. other renderers or OpenPBR.
- Adds an explicit Coat IOR input, in preparation for future smarter IOR logic
around the interaction between Coat and main IOR. This used to be hardcoded
to 1.5.
- Removes hardcoded 0.25 weight multiplier, and adds versioning code to update
existing files accordingly. OBJ import/export still applies the factor.
- Replaces the GTR1 microfacet component with regular GGX. This removes a corner
case in the Microfacet code, solves #53038, and makes us more consistent with
other standard surface shaders. The original Disney BSDF used GTR1, but it
doesn't appear that it caught on in the industry.
Co-authored-by: Weizhen Huang <weizhen@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/110993
Implements the paper [A Microfacet-based Hair Scattering
Model](https://onlinelibrary.wiley.com/doi/full/10.1111/cgf.14588) by
Weizhen Huang, Matthias B. Hullin and Johannes Hanika.
### Features:
- This is a far-field model, as opposed to the previous near-field
Principled Hair BSDF model. The hair is expected to be less noisy, but
lower roughness values takes longer to render due to numerical
integration along the hair width. The hair also appears to be flat when
viewed up-close.
- The longitudinal width of the scattering lobe differs along the
azimuth, providing a higher contrast compared to the evenly spread
scattering in the near-field Principled Hair BSDF model. For a more
detailed comparison, please refer to the original paper.
- Supports elliptical cross-sections, adding more realism as human hairs
are usually elliptical. The orientation of the cross-section is aligned
with the curve normal, which can be adjusted using geometry nodes.
Default is minimal twist. During sampling, light rays that hit outside
the hair width will continue propogating as if the material is
transparent.
- There is non-physical modulation factors for the first three
lobes (Reflection, Transmission, Secondary Reflection).
### Missing:
- A good default for cross-section orientation. There was an
attempt (9039f76928) to default the orientation to align with the curve
normal in the mathematical sense, but the stability (when animated) is
unclear and it would be a hassle to generalise to all curve types. After
the model is in main, we could experiment with the geometry nodes team
to see what works the best as a default.
Co-authored-by: Lukas Stockner <lukas.stockner@freenet.de>
Pull Request: https://projects.blender.org/blender/blender/pulls/105600
This PR adds the Lacunarity and Normalize inputs to the Noise node
similar to the Voronoi node.
The Lacunarity input controls the scale factor by which each
successive Perlin noise octave is scaled. Which was previously hard
coded to a factor of 2.
The Noise node normalizes its output to the [0, 1] range by default.
The Normalize option makes it possible for the user to disable that.
To keep the behavior consistent with past versions it is enabled by
default.
To make the aforementioned normalization control easer to implement,
the fractal noise code now accumulates signed noise and remaps the
final sum, as opposed to accumulating positive [0, 1] noise.
Pull Request: https://projects.blender.org/blender/blender/pulls/110839
Both the `Math` node and the `Vector Math` currently only explicitly
support modulo using truncated division which is oftentimes not the
type of modulo desired as it behaves differently for negative numbers
and positive numbers.
Floored Modulo can be created by either using the `Wrap` operation or
a combination of multiple `Math` nodes. However both methods obfuscate
the actual intend of the artist and the math operation that is actually
used.
This patch adds modulo using floored division to the scalar `Math` node,
explicitly stating the intended math operation and renames the already
existing `"Modulo"` operation to `"Truncated Modulo"` to avoid confusion.
Only the ui name is changed, so this should not break compatibility.
Pull Request: https://projects.blender.org/blender/blender/pulls/110728
This replaces the Sheen model used in the Principled BSDF with the
model from #108869 that is already used in the Sheen BSDF now.
The three notable differences are:
- At full intensity (Sheen = 1.0), the new model is significantly
stronger than the old one. For existing files, the intensity is
adjusted to keep the overall look similar.
- The Sheen Tint input is now a color input, instead of the
previous blend factor between white and the base color.
- There is now a Sheen roughness control, which can be used to
tweak the look between velvet-like and dust-like.
Pull Request: https://projects.blender.org/blender/blender/pulls/109949
This was already unsupported in combination with Multiscattering GGX,
prevented the Principled BSDF from using microfaced-based Fresnel for
Glass materials, and would have made future improvements even trickier.
Pull Request: https://projects.blender.org/blender/blender/pulls/109950
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
Fractal noise is the idea of evaluating the same noise function multiple times with
different input parameters on each layer and then mixing the results. The individual
layers are usually called octaves.
The number of layers is controlled with a "Detail" slider.
The "Lacunarity" input controls a factor by which each successive layer gets scaled.
The existing Noise node already supports fractal noise. Now the Voronoi Noise node
supports it as well. The node also has a new "Normalize" property that ensures that
the output values stay in a [0.0, 1.0] range. That is except for the F2 feature where
in rare cases the output may be outside that range even with "Normalize" turned on.
How the individual octaves are mixed depends on the feature and output socket:
- F1/Smooth F1/F2:
- Distance/Color output:
The individual Distance/Color octaves are first multiplied by a factor of
`Roughness ^ (#layers - 1.0)` then added together to create the final output.
- Position output:
Each Position octave gets linearly interpolated with the combined output of the
previous octaves. The Roughness input serves as an interpolation factor with
0.0 resutling in only using the combined output of the previous octaves and
1.0 resulting in only using the current highest octave.
- Distance to Edge:
- Distance output:
The Distance octaves are mixed exactly like the Position octaves for F1/Smooth F1/F2.
It should be noted that Voronoi Noise is a relatively slow noise function, especially
at higher dimensions. Increasing the "Detail" makes it even slower. Therefore, when
optimizing a scene one should consider trying to use simpler noise functions instead
of Voronoi if the final result is close enough.
Pull Request: https://projects.blender.org/blender/blender/pulls/106827
While the multiscattering GGX code is cool and solves the darkening problem at higher roughnesses, it's also currently buggy, hard to maintain and often impractical to use due to the higher noise and render time.
In practice, though, having the exact correct directional distribution is not that important as long as the overall albedo is correct and we a) don't get the darkening effect and b) do get the saturation effect at higher roughnesses.
This can simply be achieved by adding a second lobe (https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf) or scaling the single-scattering GGX lobe (https://blog.selfshadow.com/publications/turquin/ms_comp_final.pdf). Both approaches require the same precomputation and produce outputs of comparable quality, so I went for the simple albedo scaling since it's easier to implement and more efficient.
Overall, the results are pretty good: All scenarios that I tested (Glossy BSDF, Glass BSDF, Principled BSDF with metallic or transmissive = 1) pass the white furnace test (a material with pure-white color in front of a pure-white background should be indistinguishable from the background if it preserves energy), and the overall albedo for non-white materials matches that produced by the real multi-scattering code (with the expected saturation increase as the roughness increases).
In order to produce the precomputed tables, the PR also includes a utility that computes them. This is not built by default, since there's no reason for a user to run it (it only makes sense for documentation/reproducibility purposes and when making changes to the microfacet models).
Pull Request: https://projects.blender.org/blender/blender/pulls/107958
The additional SocktType::VECTOR argument was being interpreted as flags,
which caused the OSL compiler to skip the input (since the Vector type enum
happens to align with the INTERNAL flag), which caused the OSL shader to
always use the hardcoded default absorption regardless of what was entered.
Used to be https://archive.blender.org/developer/D17123.
Internally these are already using the same code path anyways, there's no point in maintaining two distinct nodes.
The obvious approach would be to add Anisotropy controls to the Glossy BSDF node and remove the Anisotropic BSDF node. However, that would break forward compability, since older Blender versions don't know how to handle the Anisotropy input on the Glossy BSDF node.
Therefore, this commit technically removes the Glossy BSDF node, uses versioning to replace them with an Anisotropic BSDF node, and renames that node to "Glossy BSDF".
That way, when you open a new file in an older version, all the nodes show up as Anisotropic BSDF nodes and render correctly.
This is a bit ugly internally since we need to preserve the old `idname` which now no longer matches the UI name, but that's not too bad.
Also removes the "Sharp" distribution option and replaces it with GGX, sets Roughness to zero and disconnects any input to the Roughness socket.
Pull Request: https://projects.blender.org/blender/blender/pulls/104445
Due to floating point differences between importance sampling and
texture evaluation, disagreeing on whether or not a ray lies within
the sun disc.
* Use the same input values for geographical_to_direction() in
sky_radiance_nishita() and kernel_data.background.sun.
* The mathematical operations in pdf_uniform_cone() were adjusted to
match sky_radiance_nishita().
Pull Request: https://projects.blender.org/blender/blender/pulls/106764