Blender V4.3
curve.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
9/* Curve Primitive
10 *
11 * Curve primitive for rendering hair and fur. These can be render as flat
12 * ribbons or curves with actual thickness. The curve can also be rendered as
13 * line segments rather than curves for better performance.
14 */
15
16#ifdef __HAIR__
17
18/* Reading attributes on various curve elements */
19
20ccl_device float curve_attribute_float(KernelGlobals kg,
21 ccl_private const ShaderData *sd,
22 const AttributeDescriptor desc,
23 ccl_private float *dx,
24 ccl_private float *dy)
25{
27 KernelCurve curve = kernel_data_fetch(curves, sd->prim);
28 int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
29 int k1 = k0 + 1;
30
31 float f0 = kernel_data_fetch(attributes_float, desc.offset + k0);
32 float f1 = kernel_data_fetch(attributes_float, desc.offset + k1);
33
34# ifdef __RAY_DIFFERENTIALS__
35 if (dx)
36 *dx = sd->du.dx * (f1 - f0);
37 if (dy)
38 *dy = 0.0f;
39# endif
40
41 return (1.0f - sd->u) * f0 + sd->u * f1;
42 }
43 else {
44# ifdef __RAY_DIFFERENTIALS__
45 if (dx)
46 *dx = 0.0f;
47 if (dy)
48 *dy = 0.0f;
49# endif
50
52 const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
53 desc.offset;
54 return kernel_data_fetch(attributes_float, offset);
55 }
56 else {
57 return 0.0f;
58 }
59 }
60}
61
62ccl_device float2 curve_attribute_float2(KernelGlobals kg,
63 ccl_private const ShaderData *sd,
64 const AttributeDescriptor desc,
67{
69 KernelCurve curve = kernel_data_fetch(curves, sd->prim);
70 int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
71 int k1 = k0 + 1;
72
73 float2 f0 = kernel_data_fetch(attributes_float2, desc.offset + k0);
74 float2 f1 = kernel_data_fetch(attributes_float2, desc.offset + k1);
75
76# ifdef __RAY_DIFFERENTIALS__
77 if (dx)
78 *dx = sd->du.dx * (f1 - f0);
79 if (dy)
80 *dy = make_float2(0.0f, 0.0f);
81# endif
82
83 return (1.0f - sd->u) * f0 + sd->u * f1;
84 }
85 else {
86 /* idea: we can't derive any useful differentials here, but for tiled
87 * mipmap image caching it would be useful to avoid reading the highest
88 * detail level always. maybe a derivative based on the hair density
89 * could be computed somehow? */
90# ifdef __RAY_DIFFERENTIALS__
91 if (dx)
92 *dx = make_float2(0.0f, 0.0f);
93 if (dy)
94 *dy = make_float2(0.0f, 0.0f);
95# endif
96
98 const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
99 desc.offset;
100 return kernel_data_fetch(attributes_float2, offset);
101 }
102 else {
103 return make_float2(0.0f, 0.0f);
104 }
105 }
106}
107
108ccl_device float3 curve_attribute_float3(KernelGlobals kg,
109 ccl_private const ShaderData *sd,
110 const AttributeDescriptor desc,
113{
115 KernelCurve curve = kernel_data_fetch(curves, sd->prim);
116 int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
117 int k1 = k0 + 1;
118
119 float3 f0 = kernel_data_fetch(attributes_float3, desc.offset + k0);
120 float3 f1 = kernel_data_fetch(attributes_float3, desc.offset + k1);
121
122# ifdef __RAY_DIFFERENTIALS__
123 if (dx)
124 *dx = sd->du.dx * (f1 - f0);
125 if (dy)
126 *dy = make_float3(0.0f, 0.0f, 0.0f);
127# endif
128
129 return (1.0f - sd->u) * f0 + sd->u * f1;
130 }
131 else {
132# ifdef __RAY_DIFFERENTIALS__
133 if (dx)
134 *dx = make_float3(0.0f, 0.0f, 0.0f);
135 if (dy)
136 *dy = make_float3(0.0f, 0.0f, 0.0f);
137# endif
138
140 const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
141 desc.offset;
142 return kernel_data_fetch(attributes_float3, offset);
143 }
144 else {
145 return make_float3(0.0f, 0.0f, 0.0f);
146 }
147 }
148}
149
150ccl_device float4 curve_attribute_float4(KernelGlobals kg,
151 ccl_private const ShaderData *sd,
152 const AttributeDescriptor desc,
153 ccl_private float4 *dx,
154 ccl_private float4 *dy)
155{
157 KernelCurve curve = kernel_data_fetch(curves, sd->prim);
158 int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
159 int k1 = k0 + 1;
160
161 float4 f0 = kernel_data_fetch(attributes_float4, desc.offset + k0);
162 float4 f1 = kernel_data_fetch(attributes_float4, desc.offset + k1);
163
164# ifdef __RAY_DIFFERENTIALS__
165 if (dx)
166 *dx = sd->du.dx * (f1 - f0);
167 if (dy)
168 *dy = zero_float4();
169# endif
170
171 return (1.0f - sd->u) * f0 + sd->u * f1;
172 }
173 else {
174# ifdef __RAY_DIFFERENTIALS__
175 if (dx)
176 *dx = zero_float4();
177 if (dy)
178 *dy = zero_float4();
179# endif
180
182 const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
183 desc.offset;
184 return kernel_data_fetch(attributes_float4, offset);
185 }
186 else {
187 return zero_float4();
188 }
189 }
190}
191
192/* Curve thickness */
193
194ccl_device float curve_thickness(KernelGlobals kg, ccl_private const ShaderData *sd)
195{
196 float r = 0.0f;
197
198 if (sd->type & PRIMITIVE_CURVE) {
199 KernelCurve curve = kernel_data_fetch(curves, sd->prim);
200 int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
201 int k1 = k0 + 1;
202
203 float4 P_curve[2];
204
205# ifdef __OBJECT_MOTION__
206 if (sd->type & PRIMITIVE_MOTION) {
207 motion_curve_keys_linear(kg, sd->object, sd->time, k0, k1, P_curve);
208 }
209 else
210# endif
211 {
212 P_curve[0] = kernel_data_fetch(curve_keys, k0);
213 P_curve[1] = kernel_data_fetch(curve_keys, k1);
214 }
215
216 r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
217 }
218
219 return r * 2.0f;
220}
221
222/* Curve random */
223
224ccl_device float curve_random(KernelGlobals kg, ccl_private const ShaderData *sd)
225{
226 if (sd->type & PRIMITIVE_CURVE) {
228 return (desc.offset != ATTR_STD_NOT_FOUND) ? curve_attribute_float(kg, sd, desc, NULL, NULL) :
229 0.0f;
230 }
231 return 0.0f;
232}
233
234/* Curve location for motion pass, linear interpolation between keys and
235 * ignoring radius because we do the same for the motion keys */
236
237ccl_device float3 curve_motion_center_location(KernelGlobals kg, ccl_private const ShaderData *sd)
238{
239 KernelCurve curve = kernel_data_fetch(curves, sd->prim);
240 int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
241 int k1 = k0 + 1;
242
243 float4 P_curve[2];
244
245 P_curve[0] = kernel_data_fetch(curve_keys, k0);
246 P_curve[1] = kernel_data_fetch(curve_keys, k1);
247
248 return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u);
249}
250
251/* Curve tangent normal */
252
253ccl_device float3 curve_tangent_normal(KernelGlobals kg, ccl_private const ShaderData *sd)
254{
255 float3 tgN = make_float3(0.0f, 0.0f, 0.0f);
256
257 if (sd->type & PRIMITIVE_CURVE) {
258
259 tgN = -(-sd->wi - sd->dPdu * (dot(sd->dPdu, -sd->wi) / len_squared(sd->dPdu)));
260 tgN = normalize(tgN);
261
262 /* need to find suitable scaled gd for corrected normal */
263# if 0
264 tgN = normalize(tgN - gd * sd->dPdu);
265# endif
266 }
267
268 return tgN;
269}
270
271/* Curve bounds utility function */
272
274 ccl_private float *upper,
275 ccl_private float *extremta,
276 ccl_private float *extrema,
277 ccl_private float *extremtb,
278 ccl_private float *extremb,
279 float p0,
280 float p1,
281 float p2,
282 float p3)
283{
284 float halfdiscroot = (p2 * p2 - 3 * p3 * p1);
285 float ta = -1.0f;
286 float tb = -1.0f;
287
288 *extremta = -1.0f;
289 *extremtb = -1.0f;
290 *upper = p0;
291 *lower = (p0 + p1) + (p2 + p3);
292 *extrema = *upper;
293 *extremb = *lower;
294
295 if (*lower >= *upper) {
296 *upper = *lower;
297 *lower = p0;
298 }
299
300 if (halfdiscroot >= 0) {
301 float inv3p3 = (1.0f / 3.0f) / p3;
302 halfdiscroot = sqrtf(halfdiscroot);
303 ta = (-p2 - halfdiscroot) * inv3p3;
304 tb = (-p2 + halfdiscroot) * inv3p3;
305 }
306
307 float t2;
308 float t3;
309
310 if (ta > 0.0f && ta < 1.0f) {
311 t2 = ta * ta;
312 t3 = t2 * ta;
313 *extremta = ta;
314 *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0;
315
316 *upper = fmaxf(*extrema, *upper);
317 *lower = fminf(*extrema, *lower);
318 }
319
320 if (tb > 0.0f && tb < 1.0f) {
321 t2 = tb * tb;
322 t3 = t2 * tb;
323 *extremtb = tb;
324 *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0;
325
326 *upper = fmaxf(*extremb, *upper);
327 *lower = fminf(*extremb, *lower);
328 }
329}
330
331#endif /* __HAIR__ */
332
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_device
#define ccl_private
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define NULL
#define fmaxf(x, y)
#define fminf(x, y)
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define sqrtf(x)
@ PRIMITIVE_MOTION
@ PRIMITIVE_CURVE
@ ATTR_STD_NOT_FOUND
@ ATTR_STD_CURVE_RANDOM
#define PRIMITIVE_UNPACK_SEGMENT(type)
ShaderData
@ ATTR_ELEMENT_CURVE_KEY
@ ATTR_ELEMENT_CURVE_KEY_MOTION
@ ATTR_ELEMENT_OBJECT
@ ATTR_ELEMENT_MESH
@ ATTR_ELEMENT_CURVE
ccl_device_inline float len_squared(const float2 a)
CCL_NAMESPACE_BEGIN ccl_device_inline float4 zero_float4()
Definition math_float4.h:15
VecBase< float, 4 > float4
CCL_NAMESPACE_BEGIN void curvebounds(float *lower, float *upper, float3 *p, int dim)
static bool find_attribute(const std::string &attributes, const char *search_attribute)
AttributeElement element
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition util/math.h:535