Blender V4.5
bsdf_sheen.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: Copyright 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7/* Shading model by Tizian Zeltner, Brent Burley, Matt Jen-Yuan Chiang:
8 * "Practical Multiple-Scattering Sheen Using Linearly Transformed Cosines" (2022)
9 * https://tizianzeltner.com/projects/Zeltner2022Practical/
10 */
11
13
15
17
24
25static_assert(sizeof(ShaderClosure) >= sizeof(SheenBsdf), "SheenBsdf is too large!");
26
28 const ccl_private ShaderData *sd,
30{
31 bsdf->type = CLOSURE_BSDF_SHEEN_ID;
32
33 bsdf->roughness = clamp(bsdf->roughness, 1e-3f, 1.0f);
34 make_orthonormals_safe_tangent(bsdf->N, sd->wi, &bsdf->T, &bsdf->B);
35 const float cosNI = dot(bsdf->N, sd->wi);
36
37 const int offset = kernel_data.tables.sheen_ltc;
38 bsdf->transformA = lookup_table_read_2D(kg, cosNI, bsdf->roughness, offset, 32, 32);
39 bsdf->transformB = lookup_table_read_2D(kg, cosNI, bsdf->roughness, offset + 32 * 32, 32, 32);
40 const float albedo = lookup_table_read_2D(
41 kg, cosNI, bsdf->roughness, offset + 2 * 32 * 32, 32, 32);
42
43 /* If the given roughness and angle result in an invalid LTC, skip the closure. */
44 if (fabsf(bsdf->transformA) < 1e-5f || albedo < 1e-5f) {
45 bsdf->type = CLOSURE_NONE_ID;
46 bsdf->sample_weight = 0.0f;
47 return 0;
48 }
49
50 bsdf->weight *= albedo;
51 bsdf->sample_weight *= albedo;
52
54}
55
57 const float3 wi,
58 const float3 wo,
59 ccl_private float *pdf)
60{
61 const ccl_private SheenBsdf *bsdf = (const ccl_private SheenBsdf *)sc;
62 const float3 N = bsdf->N;
63 const float3 T = bsdf->T;
64 const float3 B = bsdf->B;
65 const float a = bsdf->transformA;
66 const float b = bsdf->transformB;
67
68 if (dot(N, wo) <= 0.0f) {
69 *pdf = 0.0f;
70 return zero_spectrum();
71 }
72
73 const float3 localO = to_local(wo, T, B, N);
74 if (localO.z <= 0.0f) {
75 *pdf = 0.0f;
76 return zero_spectrum();
77 }
78
79 const float lenSqr = sqr(a * localO.x + b * localO.z) + sqr(a * localO.y) + sqr(localO.z);
80 const float val = M_1_PI_F * localO.z * sqr(a / lenSqr);
81
82 *pdf = val;
83 return make_spectrum(val);
84}
85
86ccl_device int bsdf_sheen_sample(const ccl_private ShaderClosure *sc,
87 const float3 Ng,
88 const float3 wi,
89 const float2 rand,
92 ccl_private float *pdf)
93{
94 const ccl_private SheenBsdf *bsdf = (const ccl_private SheenBsdf *)sc;
95 const float3 N = bsdf->N;
96 const float3 T = bsdf->T;
97 const float3 B = bsdf->B;
98 const float a = bsdf->transformA;
99 const float b = bsdf->transformB;
100
101 const float2 disk = sample_uniform_disk(rand);
102 const float diskZ = safe_sqrtf(1.0f - dot(disk, disk));
103 const float3 localO = normalize(make_float3((disk.x - diskZ * b), disk.y, diskZ * a));
104
105 *wo = to_global(localO, T, B, N);
106
107 if (dot(Ng, *wo) <= 0) {
108 *eval = zero_spectrum();
109 *pdf = 0.0f;
111 }
112
113 const float lenSqr = sqr(a * localO.x + b * localO.z) + sqr(a * localO.y) + sqr(localO.z);
114 const float val = M_1_PI_F * localO.z * sqr(a / lenSqr);
115 *pdf = val;
116 *eval = make_spectrum(val);
117
119}
120
MINLINE float safe_sqrtf(float a)
ccl_device int bsdf_sheen_sample(const ccl_private ShaderClosure *sc, const float3 Ng, const float3 wi, const float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
Definition bsdf_sheen.h:86
ccl_device int bsdf_sheen_setup(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private SheenBsdf *bsdf)
Definition bsdf_sheen.h:27
ccl_device Spectrum bsdf_sheen_eval(const ccl_private ShaderClosure *sc, const float3 wi, const float3 wo, ccl_private float *pdf)
Definition bsdf_sheen.h:56
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
ccl_device_inline T to_global(const float2 p, const T X, const T Y)
ccl_device_inline float2 to_local(const T p, const T X, const T Y)
#define kernel_data
#define ccl_device
#define zero_spectrum
#define make_spectrum(f)
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define M_1_PI_F
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define fabsf(x)
VecBase< float, D > normalize(VecOp< float, D >) RET
constexpr T clamp(T, U, U) RET
@ CLOSURE_BSDF_SHEEN_ID
@ CLOSURE_NONE_ID
@ SD_BSDF_HAS_EVAL
@ SD_BSDF
@ LABEL_DIFFUSE
@ LABEL_REFLECT
ccl_device float lookup_table_read_2D(KernelGlobals kg, const float x, float y, const int offset, const int xsize, const int ysize)
ccl_device_inline float sqr(const float a)
Definition math_base.h:600
#define N
#define T
#define B
CCL_NAMESPACE_BEGIN ccl_device float2 sample_uniform_disk(const float2 rand)
ccl_device void make_orthonormals_safe_tangent(const float3 N, const float3 T, ccl_private float3 *a, ccl_private float3 *b)
float roughness
Definition bsdf_sheen.h:20
float transformA
Definition bsdf_sheen.h:21
float3 T
Definition bsdf_sheen.h:22
float3 B
Definition bsdf_sheen.h:22
float transformB
Definition bsdf_sheen.h:21
SHADER_CLOSURE_BASE
Definition bsdf_sheen.h:19
float x
float y
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
float3 Spectrum