Blender  V3.3
curve.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
7 
8 /* Curve Primitive
9  *
10  * Curve primitive for rendering hair and fur. These can be render as flat
11  * ribbons or curves with actual thickness. The curve can also be rendered as
12  * line segments rather than curves for better performance.
13  */
14 
15 #ifdef __HAIR__
16 
17 /* Reading attributes on various curve elements */
18 
19 ccl_device float curve_attribute_float(KernelGlobals kg,
20  ccl_private const ShaderData *sd,
21  const AttributeDescriptor desc,
22  ccl_private float *dx,
23  ccl_private float *dy)
24 {
27  int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
28  int k1 = k0 + 1;
29 
30  float f0 = kernel_data_fetch(attributes_float, desc.offset + k0);
31  float f1 = kernel_data_fetch(attributes_float, desc.offset + k1);
32 
33 # ifdef __RAY_DIFFERENTIALS__
34  if (dx)
35  *dx = sd->du.dx * (f1 - f0);
36  if (dy)
37  *dy = 0.0f;
38 # endif
39 
40  return (1.0f - sd->u) * f0 + sd->u * f1;
41  }
42  else {
43 # ifdef __RAY_DIFFERENTIALS__
44  if (dx)
45  *dx = 0.0f;
46  if (dy)
47  *dy = 0.0f;
48 # endif
49 
51  const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
52  desc.offset;
53  return kernel_data_fetch(attributes_float, offset);
54  }
55  else {
56  return 0.0f;
57  }
58  }
59 }
60 
61 ccl_device float2 curve_attribute_float2(KernelGlobals kg,
62  ccl_private const ShaderData *sd,
63  const AttributeDescriptor desc,
64  ccl_private float2 *dx,
65  ccl_private float2 *dy)
66 {
69  int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
70  int k1 = k0 + 1;
71 
72  float2 f0 = kernel_data_fetch(attributes_float2, desc.offset + k0);
73  float2 f1 = kernel_data_fetch(attributes_float2, desc.offset + k1);
74 
75 # ifdef __RAY_DIFFERENTIALS__
76  if (dx)
77  *dx = sd->du.dx * (f1 - f0);
78  if (dy)
79  *dy = make_float2(0.0f, 0.0f);
80 # endif
81 
82  return (1.0f - sd->u) * f0 + sd->u * f1;
83  }
84  else {
85  /* idea: we can't derive any useful differentials here, but for tiled
86  * mipmap image caching it would be useful to avoid reading the highest
87  * detail level always. maybe a derivative based on the hair density
88  * could be computed somehow? */
89 # ifdef __RAY_DIFFERENTIALS__
90  if (dx)
91  *dx = make_float2(0.0f, 0.0f);
92  if (dy)
93  *dy = make_float2(0.0f, 0.0f);
94 # endif
95 
97  const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
98  desc.offset;
99  return kernel_data_fetch(attributes_float2, offset);
100  }
101  else {
102  return make_float2(0.0f, 0.0f);
103  }
104  }
105 }
106 
107 ccl_device float3 curve_attribute_float3(KernelGlobals kg,
108  ccl_private const ShaderData *sd,
109  const AttributeDescriptor desc,
110  ccl_private float3 *dx,
111  ccl_private float3 *dy)
112 {
115  int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
116  int k1 = k0 + 1;
117 
118  float3 f0 = kernel_data_fetch(attributes_float3, desc.offset + k0);
119  float3 f1 = kernel_data_fetch(attributes_float3, desc.offset + k1);
120 
121 # ifdef __RAY_DIFFERENTIALS__
122  if (dx)
123  *dx = sd->du.dx * (f1 - f0);
124  if (dy)
125  *dy = make_float3(0.0f, 0.0f, 0.0f);
126 # endif
127 
128  return (1.0f - sd->u) * f0 + sd->u * f1;
129  }
130  else {
131 # ifdef __RAY_DIFFERENTIALS__
132  if (dx)
133  *dx = make_float3(0.0f, 0.0f, 0.0f);
134  if (dy)
135  *dy = make_float3(0.0f, 0.0f, 0.0f);
136 # endif
137 
139  const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
140  desc.offset;
141  return kernel_data_fetch(attributes_float3, offset);
142  }
143  else {
144  return make_float3(0.0f, 0.0f, 0.0f);
145  }
146  }
147 }
148 
149 ccl_device float4 curve_attribute_float4(KernelGlobals kg,
150  ccl_private const ShaderData *sd,
151  const AttributeDescriptor desc,
152  ccl_private float4 *dx,
153  ccl_private float4 *dy)
154 {
157  int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
158  int k1 = k0 + 1;
159 
160  float4 f0 = kernel_data_fetch(attributes_float4, desc.offset + k0);
161  float4 f1 = kernel_data_fetch(attributes_float4, desc.offset + k1);
162 
163 # ifdef __RAY_DIFFERENTIALS__
164  if (dx)
165  *dx = sd->du.dx * (f1 - f0);
166  if (dy)
167  *dy = zero_float4();
168 # endif
169 
170  return (1.0f - sd->u) * f0 + sd->u * f1;
171  }
172  else {
173 # ifdef __RAY_DIFFERENTIALS__
174  if (dx)
175  *dx = zero_float4();
176  if (dy)
177  *dy = zero_float4();
178 # endif
179 
181  const int offset = (desc.element == ATTR_ELEMENT_CURVE) ? desc.offset + sd->prim :
182  desc.offset;
183  return kernel_data_fetch(attributes_float4, offset);
184  }
185  else {
186  return zero_float4();
187  }
188  }
189 }
190 
191 /* Curve thickness */
192 
193 ccl_device float curve_thickness(KernelGlobals kg, ccl_private const ShaderData *sd)
194 {
195  float r = 0.0f;
196 
197  if (sd->type & PRIMITIVE_CURVE) {
199  int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
200  int k1 = k0 + 1;
201 
202  float4 P_curve[2];
203 
204  if (!(sd->type & PRIMITIVE_MOTION)) {
205  P_curve[0] = kernel_data_fetch(curve_keys, k0);
206  P_curve[1] = kernel_data_fetch(curve_keys, k1);
207  }
208  else {
209  motion_curve_keys_linear(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
210  }
211 
212  r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
213  }
214 
215  return r * 2.0f;
216 }
217 
218 /* Curve random */
219 
220 ccl_device float curve_random(KernelGlobals kg, ccl_private const ShaderData *sd)
221 {
222  if (sd->type & PRIMITIVE_CURVE) {
224  return (desc.offset != ATTR_STD_NOT_FOUND) ? curve_attribute_float(kg, sd, desc, NULL, NULL) :
225  0.0f;
226  }
227  return 0.0f;
228 }
229 
230 /* Curve location for motion pass, linear interpolation between keys and
231  * ignoring radius because we do the same for the motion keys */
232 
233 ccl_device float3 curve_motion_center_location(KernelGlobals kg, ccl_private const ShaderData *sd)
234 {
236  int k0 = curve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
237  int k1 = k0 + 1;
238 
239  float4 P_curve[2];
240 
241  P_curve[0] = kernel_data_fetch(curve_keys, k0);
242  P_curve[1] = kernel_data_fetch(curve_keys, k1);
243 
244  return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u);
245 }
246 
247 /* Curve tangent normal */
248 
249 ccl_device float3 curve_tangent_normal(KernelGlobals kg, ccl_private const ShaderData *sd)
250 {
251  float3 tgN = make_float3(0.0f, 0.0f, 0.0f);
252 
253  if (sd->type & PRIMITIVE_CURVE) {
254 
255  tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu, -sd->I) / len_squared(sd->dPdu)));
256  tgN = normalize(tgN);
257 
258  /* need to find suitable scaled gd for corrected normal */
259 # if 0
260  tgN = normalize(tgN - gd * sd->dPdu);
261 # endif
262  }
263 
264  return tgN;
265 }
266 
267 /* Curve bounds utility function */
268 
269 ccl_device_inline void curvebounds(ccl_private float *lower,
270  ccl_private float *upper,
271  ccl_private float *extremta,
272  ccl_private float *extrema,
273  ccl_private float *extremtb,
274  ccl_private float *extremb,
275  float p0,
276  float p1,
277  float p2,
278  float p3)
279 {
280  float halfdiscroot = (p2 * p2 - 3 * p3 * p1);
281  float ta = -1.0f;
282  float tb = -1.0f;
283 
284  *extremta = -1.0f;
285  *extremtb = -1.0f;
286  *upper = p0;
287  *lower = (p0 + p1) + (p2 + p3);
288  *extrema = *upper;
289  *extremb = *lower;
290 
291  if (*lower >= *upper) {
292  *upper = *lower;
293  *lower = p0;
294  }
295 
296  if (halfdiscroot >= 0) {
297  float inv3p3 = (1.0f / 3.0f) / p3;
298  halfdiscroot = sqrtf(halfdiscroot);
299  ta = (-p2 - halfdiscroot) * inv3p3;
300  tb = (-p2 + halfdiscroot) * inv3p3;
301  }
302 
303  float t2;
304  float t3;
305 
306  if (ta > 0.0f && ta < 1.0f) {
307  t2 = ta * ta;
308  t3 = t2 * ta;
309  *extremta = ta;
310  *extrema = p3 * t3 + p2 * t2 + p1 * ta + p0;
311 
312  *upper = fmaxf(*extrema, *upper);
313  *lower = fminf(*extrema, *lower);
314  }
315 
316  if (tb > 0.0f && tb < 1.0f) {
317  t2 = tb * tb;
318  t3 = t2 * tb;
319  *extremtb = tb;
320  *extremb = p3 * t3 + p2 * t2 + p1 * tb + p0;
321 
322  *upper = fmaxf(*extremb, *upper);
323  *lower = fminf(*extremb, *lower);
324  }
325 }
326 
327 #endif /* __HAIR__ */
328 
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
float float4[4]
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 Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
Curve curve
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, ccl_private const ShaderData *sd, uint id)
@ PRIMITIVE_MOTION
Definition: kernel/types.h:558
@ PRIMITIVE_CURVE
Definition: kernel/types.h:564
@ ATTR_STD_NOT_FOUND
Definition: kernel/types.h:647
@ ATTR_STD_CURVE_RANDOM
Definition: kernel/types.h:629
#define PRIMITIVE_UNPACK_SEGMENT(type)
Definition: kernel/types.h:579
ShaderData
Definition: kernel/types.h:925
@ ATTR_ELEMENT_CURVE_KEY
Definition: kernel/types.h:607
@ ATTR_ELEMENT_CURVE_KEY_MOTION
Definition: kernel/types.h:608
@ ATTR_ELEMENT_OBJECT
Definition: kernel/types.h:599
@ ATTR_ELEMENT_MESH
Definition: kernel/types.h:600
@ ATTR_ELEMENT_CURVE
Definition: kernel/types.h:606
ccl_device_inline float len_squared(const float3 a)
Definition: math_float3.h:423
ccl_device_inline float4 zero_float4()
Definition: math_float4.h:92
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define make_float2(x, y)
Definition: metal/compat.h:203
#define fminf(x, y)
Definition: metal/compat.h:229
#define sqrtf(x)
Definition: metal/compat.h:243
#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)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
CCL_NAMESPACE_BEGIN void curvebounds(float *lower, float *upper, float3 *p, int dim)
AttributeElement element
Definition: kernel/types.h:656
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500