Blender V5.0
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 const float3 localO = to_local(wo, T, B, N);
69
70 const float lenSqr = sqr(a * localO.x + b * localO.z) + sqr(a * localO.y) + sqr(localO.z);
71 const float val = M_1_PI_F * fmaxf(localO.z, 0.0f) * sqr(a / lenSqr);
72
73 *pdf = val;
74 return make_spectrum(val);
75}
76
77ccl_device int bsdf_sheen_sample(const ccl_private ShaderClosure *sc,
78 const float3 Ng,
79 const float3 /*wi*/,
80 const float2 rand,
83 ccl_private float *pdf)
84{
85 const ccl_private SheenBsdf *bsdf = (const ccl_private SheenBsdf *)sc;
86 const float3 N = bsdf->N;
87 const float3 T = bsdf->T;
88 const float3 B = bsdf->B;
89 const float a = bsdf->transformA;
90 const float b = bsdf->transformB;
91
92 const float2 disk = sample_uniform_disk(rand);
93 const float diskZ = safe_sqrtf(1.0f - dot(disk, disk));
94 const float3 localO = normalize(make_float3((disk.x - diskZ * b), disk.y, diskZ * a));
95
96 *wo = to_global(localO, T, B, N);
97
98 if (dot(Ng, *wo) <= 0) {
99 *eval = zero_spectrum();
100 *pdf = 0.0f;
102 }
103
104 const float lenSqr = sqr(a * localO.x + b * localO.z) + sqr(a * localO.y) + sqr(localO.z);
105 const float val = M_1_PI_F * localO.z * sqr(a / lenSqr);
106 *pdf = val;
107 *eval = make_spectrum(val);
108
110}
111
MINLINE float safe_sqrtf(float a)
ccl_device int bsdf_sheen_sample(const ccl_private ShaderClosure *sc, const float3 Ng, const float3, const float2 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf)
Definition bsdf_sheen.h:77
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, 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 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)
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)
#define N
#define T
#define B
#define sqr
#define fabsf
#define ccl_device
#define fmaxf
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_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
float3 Spectrum