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