Blender  V3.3
primitive.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 /* Primitive Utilities
5  *
6  * Generic functions to look up mesh, curve and volume primitive attributes for
7  * shading and render passes. */
8 
9 #pragma once
10 
12 
14 
15 /* Surface Attributes
16  *
17  * Read geometry attributes for surface shading. This is distinct from volume
18  * attributes for performance, mainly for GPU performance to avoid bringing in
19  * heavy volume interpolation code. */
20 
22  ccl_private const ShaderData *sd,
23  const AttributeDescriptor desc,
24  ccl_private float *dx,
25  ccl_private float *dy)
26 {
27  if (sd->type & PRIMITIVE_TRIANGLE) {
28  if (subd_triangle_patch(kg, sd) == ~0)
29  return triangle_attribute_float(kg, sd, desc, dx, dy);
30  else
31  return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
32  }
33 #ifdef __HAIR__
34  else if (sd->type & PRIMITIVE_CURVE) {
35  return curve_attribute_float(kg, sd, desc, dx, dy);
36  }
37 #endif
38 #ifdef __POINTCLOUD__
39  else if (sd->type & PRIMITIVE_POINT) {
40  return point_attribute_float(kg, sd, desc, dx, dy);
41  }
42 #endif
43  else {
44  if (dx)
45  *dx = 0.0f;
46  if (dy)
47  *dy = 0.0f;
48  return 0.0f;
49  }
50 }
51 
53  ccl_private const ShaderData *sd,
54  const AttributeDescriptor desc,
55  ccl_private float2 *dx,
56  ccl_private float2 *dy)
57 {
58  if (sd->type & PRIMITIVE_TRIANGLE) {
59  if (subd_triangle_patch(kg, sd) == ~0)
60  return triangle_attribute_float2(kg, sd, desc, dx, dy);
61  else
62  return subd_triangle_attribute_float2(kg, sd, desc, dx, dy);
63  }
64 #ifdef __HAIR__
65  else if (sd->type & PRIMITIVE_CURVE) {
66  return curve_attribute_float2(kg, sd, desc, dx, dy);
67  }
68 #endif
69 #ifdef __POINTCLOUD__
70  else if (sd->type & PRIMITIVE_POINT) {
71  return point_attribute_float2(kg, sd, desc, dx, dy);
72  }
73 #endif
74  else {
75  if (dx)
76  *dx = make_float2(0.0f, 0.0f);
77  if (dy)
78  *dy = make_float2(0.0f, 0.0f);
79  return make_float2(0.0f, 0.0f);
80  }
81 }
82 
84  ccl_private const ShaderData *sd,
85  const AttributeDescriptor desc,
86  ccl_private float3 *dx,
87  ccl_private float3 *dy)
88 {
89  if (sd->type & PRIMITIVE_TRIANGLE) {
90  if (subd_triangle_patch(kg, sd) == ~0)
91  return triangle_attribute_float3(kg, sd, desc, dx, dy);
92  else
93  return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
94  }
95 #ifdef __HAIR__
96  else if (sd->type & PRIMITIVE_CURVE) {
97  return curve_attribute_float3(kg, sd, desc, dx, dy);
98  }
99 #endif
100 #ifdef __POINTCLOUD__
101  else if (sd->type & PRIMITIVE_POINT) {
102  return point_attribute_float3(kg, sd, desc, dx, dy);
103  }
104 #endif
105  else {
106  if (dx)
107  *dx = make_float3(0.0f, 0.0f, 0.0f);
108  if (dy)
109  *dy = make_float3(0.0f, 0.0f, 0.0f);
110  return make_float3(0.0f, 0.0f, 0.0f);
111  }
112 }
113 
115  ccl_private const ShaderData *sd,
116  const AttributeDescriptor desc,
117  ccl_private float4 *dx,
118  ccl_private float4 *dy)
119 {
120  if (sd->type & PRIMITIVE_TRIANGLE) {
121  if (subd_triangle_patch(kg, sd) == ~0)
122  return triangle_attribute_float4(kg, sd, desc, dx, dy);
123  else
124  return subd_triangle_attribute_float4(kg, sd, desc, dx, dy);
125  }
126 #ifdef __HAIR__
127  else if (sd->type & PRIMITIVE_CURVE) {
128  return curve_attribute_float4(kg, sd, desc, dx, dy);
129  }
130 #endif
131 #ifdef __POINTCLOUD__
132  else if (sd->type & PRIMITIVE_POINT) {
133  return point_attribute_float4(kg, sd, desc, dx, dy);
134  }
135 #endif
136  else {
137  if (dx)
138  *dx = zero_float4();
139  if (dy)
140  *dy = zero_float4();
141  return zero_float4();
142  }
143 }
144 
145 #ifdef __VOLUME__
146 /* Volume Attributes
147  *
148  * Read geometry attributes for volume shading. This is distinct from surface
149  * attributes for performance, mainly for GPU performance to avoid bringing in
150  * heavy volume interpolation code. */
151 
152 ccl_device_forceinline bool primitive_is_volume_attribute(ccl_private const ShaderData *sd,
153  const AttributeDescriptor desc)
154 {
155  return sd->type == PRIMITIVE_VOLUME;
156 }
157 
158 ccl_device_forceinline float primitive_volume_attribute_float(KernelGlobals kg,
159  ccl_private const ShaderData *sd,
160  const AttributeDescriptor desc)
161 {
162  if (primitive_is_volume_attribute(sd, desc)) {
163  return volume_attribute_value_to_float(volume_attribute_float4(kg, sd, desc));
164  }
165  else {
166  return 0.0f;
167  }
168 }
169 
170 ccl_device_forceinline float3 primitive_volume_attribute_float3(KernelGlobals kg,
171  ccl_private const ShaderData *sd,
172  const AttributeDescriptor desc)
173 {
174  if (primitive_is_volume_attribute(sd, desc)) {
175  return volume_attribute_value_to_float3(volume_attribute_float4(kg, sd, desc));
176  }
177  else {
178  return make_float3(0.0f, 0.0f, 0.0f);
179  }
180 }
181 
182 ccl_device_forceinline float4 primitive_volume_attribute_float4(KernelGlobals kg,
183  ccl_private const ShaderData *sd,
184  const AttributeDescriptor desc)
185 {
186  if (primitive_is_volume_attribute(sd, desc)) {
187  return volume_attribute_float4(kg, sd, desc);
188  }
189  else {
190  return zero_float4();
191  }
192 }
193 #endif
194 
195 /* Default UV coordinate */
196 
198 {
199  const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_UV);
200 
201  if (desc.offset == ATTR_STD_NOT_FOUND)
202  return make_float3(0.0f, 0.0f, 0.0f);
203 
204  float2 uv = primitive_surface_attribute_float2(kg, sd, desc, NULL, NULL);
205  return make_float3(uv.x, uv.y, 1.0f);
206 }
207 
208 /* Ptex coordinates */
209 
212  ccl_private float2 *uv,
213  ccl_private int *face_id)
214 {
215  /* storing ptex data as attributes is not memory efficient but simple for tests */
216  const AttributeDescriptor desc_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID);
217  const AttributeDescriptor desc_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV);
218 
219  if (desc_face_id.offset == ATTR_STD_NOT_FOUND || desc_uv.offset == ATTR_STD_NOT_FOUND)
220  return false;
221 
222  float3 uv3 = primitive_surface_attribute_float3(kg, sd, desc_uv, NULL, NULL);
223  float face_id_f = primitive_surface_attribute_float(kg, sd, desc_face_id, NULL, NULL);
224 
225  *uv = make_float2(uv3.x, uv3.y);
226  *face_id = (int)face_id_f;
227 
228  return true;
229 }
230 
231 /* Surface tangent */
232 
234 {
235 #if defined(__HAIR__) || defined(__POINTCLOUD__)
236  if (sd->type & (PRIMITIVE_CURVE | PRIMITIVE_POINT))
237 # ifdef __DPDU__
238  return normalize(sd->dPdu);
239 # else
240  return make_float3(0.0f, 0.0f, 0.0f);
241 # endif
242 #endif
243 
244  /* try to create spherical tangent from generated coordinates */
246 
247  if (desc.offset != ATTR_STD_NOT_FOUND) {
249  data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
250  object_normal_transform(kg, sd, &data);
251  return cross(sd->N, normalize(cross(data, sd->N)));
252  }
253  else {
254  /* otherwise use surface derivatives */
255 #ifdef __DPDU__
256  return normalize(sd->dPdu);
257 #else
258  return make_float3(0.0f, 0.0f, 0.0f);
259 #endif
260  }
261 }
262 
263 /* Motion vector for motion pass */
264 
266  ccl_private const ShaderData *sd)
267 {
268  /* center position */
269  float3 center;
270 
271 #if defined(__HAIR__) || defined(__POINTCLOUD__)
272  bool is_curve_or_point = sd->type & (PRIMITIVE_CURVE | PRIMITIVE_POINT);
273  if (is_curve_or_point) {
274  center = make_float3(0.0f, 0.0f, 0.0f);
275 
276  if (sd->type & PRIMITIVE_CURVE) {
277 # if defined(__HAIR__)
278  center = curve_motion_center_location(kg, sd);
279 # endif
280  }
281  else if (sd->type & PRIMITIVE_POINT) {
282 # if defined(__POINTCLOUD__)
283  center = point_motion_center_location(kg, sd);
284 # endif
285  }
286 
287  if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
289  }
290  }
291  else
292 #endif
293  {
294  center = sd->P;
295  }
296 
297  float3 motion_pre = center, motion_post = center;
298 
299  /* deformation motion */
301 
302  if (desc.offset != ATTR_STD_NOT_FOUND) {
303  /* get motion info */
304  int numverts, numkeys;
305  object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
306 
307 #if defined(__HAIR__) || defined(__POINTCLOUD__)
308  if (is_curve_or_point) {
309  motion_pre = float4_to_float3(curve_attribute_float4(kg, sd, desc, NULL, NULL));
310  desc.offset += numkeys;
311  motion_post = float4_to_float3(curve_attribute_float4(kg, sd, desc, NULL, NULL));
312 
313  /* Curve */
314  if ((sd->object_flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
315  object_position_transform(kg, sd, &motion_pre);
316  object_position_transform(kg, sd, &motion_post);
317  }
318  }
319  else
320 #endif
321  if (sd->type & PRIMITIVE_TRIANGLE) {
322  /* Triangle */
323  if (subd_triangle_patch(kg, sd) == ~0) {
324  motion_pre = triangle_attribute_float3(kg, sd, desc, NULL, NULL);
325  desc.offset += numverts;
326  motion_post = triangle_attribute_float3(kg, sd, desc, NULL, NULL);
327  }
328  else {
329  motion_pre = subd_triangle_attribute_float3(kg, sd, desc, NULL, NULL);
330  desc.offset += numverts;
331  motion_post = subd_triangle_attribute_float3(kg, sd, desc, NULL, NULL);
332  }
333  }
334  }
335 
336  /* object motion. note that depending on the mesh having motion vectors, this
337  * transformation was set match the world/object space of motion_pre/post */
338  Transform tfm;
339 
341  motion_pre = transform_point(&tfm, motion_pre);
342 
344  motion_post = transform_point(&tfm, motion_post);
345 
346  float3 motion_center;
347 
348  /* camera motion, for perspective/orthographic motion.pre/post will be a
349  * world-to-raster matrix, for panorama it's world-to-camera */
350  if (kernel_data.cam.type != CAMERA_PANORAMA) {
351  ProjectionTransform projection = kernel_data.cam.worldtoraster;
352  motion_center = transform_perspective(&projection, center);
353 
354  projection = kernel_data.cam.perspective_pre;
355  motion_pre = transform_perspective(&projection, motion_pre);
356 
357  projection = kernel_data.cam.perspective_post;
358  motion_post = transform_perspective(&projection, motion_post);
359  }
360  else {
361  tfm = kernel_data.cam.worldtocamera;
362  motion_center = normalize(transform_point(&tfm, center));
363  motion_center = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_center));
364  motion_center.x *= kernel_data.cam.width;
365  motion_center.y *= kernel_data.cam.height;
366 
367  tfm = kernel_data.cam.motion_pass_pre;
368  motion_pre = normalize(transform_point(&tfm, motion_pre));
369  motion_pre = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_pre));
370  motion_pre.x *= kernel_data.cam.width;
371  motion_pre.y *= kernel_data.cam.height;
372 
373  tfm = kernel_data.cam.motion_pass_post;
374  motion_post = normalize(transform_point(&tfm, motion_post));
375  motion_post = float2_to_float3(direction_to_panorama(&kernel_data.cam, motion_post));
376  motion_post.x *= kernel_data.cam.width;
377  motion_post.y *= kernel_data.cam.height;
378  }
379 
380  motion_pre = motion_pre - motion_center;
381  motion_post = motion_center - motion_post;
382 
383  return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
384 }
385 
NSNotificationCenter * center
float float4[4]
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#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
ccl_device_inline float2 direction_to_panorama(ccl_constant KernelCamera *cam, float3 dir)
ccl_device_inline float3 transform_perspective(ccl_private const ProjectionTransform *t, const float3 a)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, ccl_private const ShaderData *sd, uint id)
CCL_NAMESPACE_BEGIN ccl_device_inline uint subd_triangle_patch(KernelGlobals kg, ccl_private const ShaderData *sd)
ccl_device_inline void object_motion_info(KernelGlobals kg, int object, ccl_private int *numsteps, ccl_private int *numverts, ccl_private int *numkeys)
ccl_device_inline void object_position_transform(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private float3 *P)
ccl_device_inline Transform object_fetch_motion_pass_transform(KernelGlobals kg, int object, enum ObjectVectorTransform type)
@ OBJECT_PASS_MOTION_PRE
@ OBJECT_PASS_MOTION_POST
ccl_device_inline void object_normal_transform(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private float3 *N)
@ PRIMITIVE_VOLUME
Definition: kernel/types.h:555
@ PRIMITIVE_CURVE
Definition: kernel/types.h:564
@ PRIMITIVE_TRIANGLE
Definition: kernel/types.h:551
@ PRIMITIVE_POINT
Definition: kernel/types.h:554
@ ATTR_STD_UV
Definition: kernel/types.h:616
@ ATTR_STD_NOT_FOUND
Definition: kernel/types.h:647
@ ATTR_STD_PTEX_FACE_ID
Definition: kernel/types.h:631
@ ATTR_STD_MOTION_VERTEX_POSITION
Definition: kernel/types.h:624
@ ATTR_STD_PTEX_UV
Definition: kernel/types.h:632
@ ATTR_STD_GENERATED
Definition: kernel/types.h:620
ShaderData
Definition: kernel/types.h:925
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel/types.h:808
@ SD_OBJECT_HAS_VERTEX_MOTION
Definition: kernel/types.h:816
@ CAMERA_PANORAMA
Definition: kernel/types.h:466
ccl_device_inline float4 zero_float4()
Definition: math_float4.h:92
#define make_float2(x, y)
Definition: metal/compat.h:203
#define make_float4(x, y, z, w)
Definition: metal/compat.h:205
#define make_float3(x, y, z)
Definition: metal/compat.h:204
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
ccl_device_forceinline float3 primitive_surface_attribute_float3(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float3 *dx, ccl_private float3 *dy)
Definition: primitive.h:83
ccl_device_forceinline float2 primitive_surface_attribute_float2(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float2 *dx, ccl_private float2 *dy)
Definition: primitive.h:52
ccl_device_forceinline float4 primitive_motion_vector(KernelGlobals kg, ccl_private const ShaderData *sd)
Definition: primitive.h:265
ccl_device_forceinline float3 primitive_uv(KernelGlobals kg, ccl_private const ShaderData *sd)
Definition: primitive.h:197
ccl_device_forceinline float4 primitive_surface_attribute_float4(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float4 *dx, ccl_private float4 *dy)
Definition: primitive.h:114
CCL_NAMESPACE_BEGIN ccl_device_forceinline float primitive_surface_attribute_float(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float *dx, ccl_private float *dy)
Definition: primitive.h:21
ccl_device float3 primitive_tangent(KernelGlobals kg, ccl_private ShaderData *sd)
Definition: primitive.h:233
ccl_device bool primitive_ptex(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float2 *uv, ccl_private int *face_id)
Definition: primitive.h:210
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float y
float x
ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float3 *dx, ccl_private float3 *dy)
ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float4 *dx, ccl_private float4 *dy)
ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float *dx, ccl_private float *dy)
Definition: subd_triangle.h:84
ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float2 *dx, ccl_private float2 *dy)
ccl_device float triangle_attribute_float(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float *dx, ccl_private float *dy)
Definition: triangle.h:146
ccl_device float2 triangle_attribute_float2(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float2 *dx, ccl_private float2 *dy)
Definition: triangle.h:196
ccl_device float4 triangle_attribute_float4(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float4 *dx, ccl_private float4 *dy)
Definition: triangle.h:296
ccl_device float3 triangle_attribute_float3(KernelGlobals kg, ccl_private const ShaderData *sd, const AttributeDescriptor desc, ccl_private float3 *dx, ccl_private float3 *dy)
Definition: triangle.h:246
ccl_device_inline float3 float2_to_float3(const float2 a)
Definition: util/math.h:495
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500