Blender V4.3
bsdf_oren_nayar.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
8
17
18static_assert(sizeof(ShaderClosure) >= sizeof(OrenNayarBsdf), "OrenNayarBsdf is too large!");
19
20/* NOTE: This implements the improved Oren-Nayar model by Yasuhiro Fujii
21 * (https://mimosa-pudica.net/improved-oren-nayar.html), plus an
22 * energy-preserving multi-scattering term based on the OpenPBR specification
23 * (https://academysoftwarefoundation.github.io/OpenPBR). */
24
25ccl_device_inline float bsdf_oren_nayar_G(const float cosTheta)
26{
27 if (cosTheta < 1e-6f) {
28 /* The tan(theta) term starts to act up at low cosTheta, so fall back to Taylor expansion. */
29 return (M_PI_2_F - 2.0f / 3.0f) - cosTheta;
30 }
31 const float sinTheta = sin_from_cos(cosTheta);
32 const float theta = safe_acosf(cosTheta);
33 return sinTheta * (theta - 2.0f / 3.0f - sinTheta * cosTheta) +
34 2.0f / 3.0f * (sinTheta / cosTheta) * (1.0f - sqr(sinTheta) * sinTheta);
35}
36
38 float3 n,
39 float3 v,
40 float3 l)
41{
42 ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
43 float nl = max(dot(n, l), 0.0f);
44 float nv = max(dot(n, v), 0.0f);
45 float t = dot(l, v) - nl * nv;
46
47 if (t > 0.0f)
48 t /= max(nl, nv) + FLT_MIN;
49
50 const float single_scatter = bsdf->a + bsdf->b * t;
51
52 const float El = bsdf->a * M_PI_F + bsdf->b * bsdf_oren_nayar_G(nl);
53 const Spectrum multi_scatter = bsdf->multiscatter_term * (1.0f - El);
54
55 return nl * (make_spectrum(single_scatter) + multi_scatter);
56}
57
60 const Spectrum color)
61{
62 bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID;
63
64 const float sigma = saturatef(bsdf->roughness);
65 bsdf->a = 1.0f / (M_PI_F + sigma * (M_PI_2_F - 2.0f / 3.0f));
66 bsdf->b = sigma * bsdf->a;
67
68 /* Compute energy compensation term (except for (1.0f - El) factor since it depends on wo). */
69 const Spectrum albedo = saturate(color);
70 const float Eavg = bsdf->a * M_PI_F + ((M_2PI_F - 5.6f) / 3.0f) * bsdf->b;
71 const Spectrum Ems = M_1_PI_F * sqr(albedo) * (Eavg / (1.0f - Eavg)) /
72 (one_spectrum() - albedo * (1.0f - Eavg));
73 const float nv = max(dot(bsdf->N, sd->wi), 0.0f);
74 const float Ev = bsdf->a * M_PI_F + bsdf->b * bsdf_oren_nayar_G(nv);
75 bsdf->multiscatter_term = Ems * (1.0f - Ev);
76
78}
79
81 const float3 wi,
82 const float3 wo,
83 ccl_private float *pdf)
84{
85 ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
86 const float cosNO = dot(bsdf->N, wo);
87 if (cosNO > 0.0f) {
88 *pdf = cosNO * M_1_PI_F;
89 return bsdf_oren_nayar_get_intensity(sc, bsdf->N, wi, wo);
90 }
91 else {
92 *pdf = 0.0f;
93 return zero_spectrum();
94 }
95}
96
98 float3 Ng,
99 float3 wi,
100 float2 rand,
101 ccl_private Spectrum *eval,
103 ccl_private float *pdf)
104{
105 ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
106
107 sample_cos_hemisphere(bsdf->N, rand, wo, pdf);
108
109 if (dot(Ng, *wo) > 0.0f) {
110 *eval = bsdf_oren_nayar_get_intensity(sc, bsdf->N, wi, *wo);
111 }
112 else {
113 *pdf = 0.0f;
114 *eval = zero_spectrum();
115 }
116
118}
119
MINLINE float safe_acosf(float a)
#define saturate(a)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_device Spectrum bsdf_oren_nayar_get_intensity(ccl_private const ShaderClosure *sc, float3 n, float3 v, float3 l)
ccl_device int bsdf_oren_nayar_setup(ccl_private const ShaderData *sd, ccl_private OrenNayarBsdf *bsdf, const Spectrum color)
ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 wi, float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
ccl_device Spectrum bsdf_oren_nayar_eval(ccl_private const ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
ccl_device_inline float bsdf_oren_nayar_G(const float cosTheta)
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define CCL_NAMESPACE_END
#define saturatef(x)
@ CLOSURE_BSDF_OREN_NAYAR_ID
@ SD_BSDF_HAS_EVAL
@ SD_BSDF
ShaderData
@ LABEL_DIFFUSE
@ LABEL_REFLECT
ShaderClosure
#define M_PI_F
Definition mikk_util.hh:15
ccl_device_inline void sample_cos_hemisphere(const float3 N, float2 rand_in, ccl_private float3 *wo, ccl_private float *pdf)
#define M_PI_2_F
Definition sky_float3.h:20
#define M_2PI_F
Definition sky_float3.h:23
Spectrum multiscatter_term
float max
#define one_spectrum
#define zero_spectrum
#define make_spectrum(f)
SPECTRUM_DATA_TYPE Spectrum
ccl_device_inline float sqr(float a)
Definition util/math.h:782
ccl_device_inline float sin_from_cos(const float c)
Definition util/math.h:787