Blender  V3.3
bsdf_toon.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Adapted from Open Shading Language
4  * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
5  * All Rights Reserved.
6  *
7  * Modifications Copyright 2011-2022 Blender Foundation. */
8 
9 #pragma once
10 
12 
13 typedef struct ToonBsdf {
15 
16  float size;
17  float smooth;
19 
20 static_assert(sizeof(ShaderClosure) >= sizeof(ToonBsdf), "ToonBsdf is too large!");
21 
22 /* DIFFUSE TOON */
23 
25 {
26  bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
27  bsdf->size = saturatef(bsdf->size);
28  bsdf->smooth = saturatef(bsdf->smooth);
29 
30  return SD_BSDF | SD_BSDF_HAS_EVAL;
31 }
32 
33 ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
34 {
35  float is;
36 
37  if (angle < max_angle)
38  is = 1.0f;
39  else if (angle < (max_angle + smooth) && smooth != 0.0f)
40  is = (1.0f - (angle - max_angle) / smooth);
41  else
42  is = 0.0f;
43 
44  return make_float3(is, is, is);
45 }
46 
47 ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
48 {
49  return fminf(max_angle + smooth, M_PI_2_F);
50 }
51 
53  const float3 I,
54  const float3 omega_in,
55  ccl_private float *pdf)
56 {
57  ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
58  float max_angle = bsdf->size * M_PI_2_F;
59  float smooth = bsdf->smooth * M_PI_2_F;
60  float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
61 
62  float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
63 
64  if (eval.x > 0.0f) {
65  float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
66 
67  *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
68  return *pdf * eval;
69  }
70  *pdf = 0.0f;
71  return make_float3(0.0f, 0.0f, 0.0f);
72 }
73 
75  const float3 I,
76  const float3 omega_in,
77  ccl_private float *pdf)
78 {
79  *pdf = 0.0f;
80  return make_float3(0.0f, 0.0f, 0.0f);
81 }
82 
84  float3 Ng,
85  float3 I,
86  float3 dIdx,
87  float3 dIdy,
88  float randu,
89  float randv,
90  ccl_private float3 *eval,
91  ccl_private float3 *omega_in,
92  ccl_private float3 *domega_in_dx,
93  ccl_private float3 *domega_in_dy,
94  ccl_private float *pdf)
95 {
96  ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
97  float max_angle = bsdf->size * M_PI_2_F;
98  float smooth = bsdf->smooth * M_PI_2_F;
99  float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
100  float angle = sample_angle * randu;
101 
102  if (sample_angle > 0.0f) {
103  sample_uniform_cone(bsdf->N, sample_angle, randu, randv, omega_in, pdf);
104 
105  if (dot(Ng, *omega_in) > 0.0f) {
106  *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
107 
108 #ifdef __RAY_DIFFERENTIALS__
109  // TODO: find a better approximation for the bounce
110  *domega_in_dx = (2.0f * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
111  *domega_in_dy = (2.0f * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
112 #endif
113  }
114  else {
115  *eval = make_float3(0.f, 0.f, 0.f);
116  *pdf = 0.0f;
117  }
118  }
119  else {
120  *eval = make_float3(0.f, 0.f, 0.f);
121  *pdf = 0.0f;
122  }
123 
124  return LABEL_REFLECT | LABEL_DIFFUSE;
125 }
126 
127 /* GLOSSY TOON */
128 
130 {
131  bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
132  bsdf->size = saturatef(bsdf->size);
133  bsdf->smooth = saturatef(bsdf->smooth);
134 
135  return SD_BSDF | SD_BSDF_HAS_EVAL;
136 }
137 
139  const float3 I,
140  const float3 omega_in,
141  ccl_private float *pdf)
142 {
143  ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
144  float max_angle = bsdf->size * M_PI_2_F;
145  float smooth = bsdf->smooth * M_PI_2_F;
146  float cosNI = dot(bsdf->N, omega_in);
147  float cosNO = dot(bsdf->N, I);
148 
149  if (cosNI > 0 && cosNO > 0) {
150  /* reflect the view vector */
151  float3 R = (2 * cosNO) * bsdf->N - I;
152  float cosRI = dot(R, omega_in);
153 
154  float angle = safe_acosf(fmaxf(cosRI, 0.0f));
155 
156  float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
157  float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
158 
159  *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
160  return *pdf * eval;
161  }
162  *pdf = 0.0f;
163  return make_float3(0.0f, 0.0f, 0.0f);
164 }
165 
167  const float3 I,
168  const float3 omega_in,
169  ccl_private float *pdf)
170 {
171  *pdf = 0.0f;
172  return make_float3(0.0f, 0.0f, 0.0f);
173 }
174 
176  float3 Ng,
177  float3 I,
178  float3 dIdx,
179  float3 dIdy,
180  float randu,
181  float randv,
182  ccl_private float3 *eval,
183  ccl_private float3 *omega_in,
184  ccl_private float3 *domega_in_dx,
185  ccl_private float3 *domega_in_dy,
186  ccl_private float *pdf)
187 {
188  ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
189  float max_angle = bsdf->size * M_PI_2_F;
190  float smooth = bsdf->smooth * M_PI_2_F;
191  float cosNO = dot(bsdf->N, I);
192 
193  if (cosNO > 0) {
194  /* reflect the view vector */
195  float3 R = (2 * cosNO) * bsdf->N - I;
196 
197  float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
198  float angle = sample_angle * randu;
199 
200  sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
201 
202  if (dot(Ng, *omega_in) > 0.0f) {
203  float cosNI = dot(bsdf->N, *omega_in);
204 
205  /* make sure the direction we chose is still in the right hemisphere */
206  if (cosNI > 0) {
207  *eval = *pdf * bsdf_toon_get_intensity(max_angle, smooth, angle);
208 
209 #ifdef __RAY_DIFFERENTIALS__
210  *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx;
211  *domega_in_dy = (2 * dot(bsdf->N, dIdy)) * bsdf->N - dIdy;
212 #endif
213  }
214  else {
215  *pdf = 0.0f;
216  *eval = make_float3(0.0f, 0.0f, 0.0f);
217  }
218  }
219  else {
220  *pdf = 0.0f;
221  *eval = make_float3(0.0f, 0.0f, 0.0f);
222  }
223  }
224 
225  return LABEL_GLOSSY | LABEL_REFLECT;
226 }
227 
MINLINE float safe_acosf(float a)
ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, ccl_private float3 *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, ccl_private float *pdf)
Definition: bsdf_toon.h:175
ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, ccl_private float3 *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, ccl_private float *pdf)
Definition: bsdf_toon.h:83
ccl_device int bsdf_diffuse_toon_setup(ccl_private ToonBsdf *bsdf)
Definition: bsdf_toon.h:24
ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
Definition: bsdf_toon.h:47
ccl_device float3 bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf)
Definition: bsdf_toon.h:74
CCL_NAMESPACE_BEGIN struct ToonBsdf ToonBsdf
ccl_device float3 bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf)
Definition: bsdf_toon.h:166
ccl_device float3 bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf)
Definition: bsdf_toon.h:138
ccl_device float3 bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf)
Definition: bsdf_toon.h:52
ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf)
Definition: bsdf_toon.h:129
ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle)
Definition: bsdf_toon.h:33
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define cosf(x)
Definition: cuda/compat.h:101
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
@ CLOSURE_BSDF_DIFFUSE_TOON_ID
@ CLOSURE_BSDF_GLOSSY_TOON_ID
@ SD_BSDF_HAS_EVAL
Definition: kernel/types.h:744
@ SD_BSDF
Definition: kernel/types.h:742
@ LABEL_DIFFUSE
Definition: kernel/types.h:319
@ LABEL_GLOSSY
Definition: kernel/types.h:320
@ LABEL_REFLECT
Definition: kernel/types.h:318
ShaderClosure
Definition: kernel/types.h:726
#define R
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define fminf(x, y)
Definition: metal/compat.h:229
#define make_float3(x, y, z)
Definition: metal/compat.h:204
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
#define I
smooth(Type::FLOAT, "mask_weight")
ccl_device_inline void sample_uniform_cone(const float3 N, float angle, float randu, float randv, ccl_private float3 *omega_in, ccl_private float *pdf)
float smooth
Definition: bsdf_toon.h:17
float size
Definition: bsdf_toon.h:16
SHADER_CLOSURE_BASE
Definition: bsdf_toon.h:14
float x
#define M_PI_2_F
Definition: util/math.h:37
ccl_device_inline float saturatef(float a)
Definition: util/math.h:404
#define M_1_PI_F
Definition: util/math.h:43