Blender V5.0
shader_data.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/* Functions to initialize ShaderData given.
6 *
7 * Could be from an incoming ray, intersection or sampled position. */
8
9#pragma once
10
11#include "kernel/globals.h"
12
15#include "kernel/geom/object.h"
18
20
22
23/* ShaderData setup from incoming ray */
24
26 ccl_private ShaderData *ccl_restrict sd,
27 const float time)
28{
29#ifdef __OBJECT_MOTION__
30 if (sd->object_flag & SD_OBJECT_MOTION) {
31 sd->ob_tfm_motion = object_fetch_transform_motion(kg, sd->object, time);
32 sd->ob_itfm_motion = transform_inverse(sd->ob_tfm_motion);
33 }
34#endif
35}
36
37/* TODO: break this up if it helps reduce register pressure to load data from
38 * global memory as we write it to shader-data. */
40 ccl_private ShaderData *ccl_restrict sd,
41 const ccl_private Ray *ccl_restrict ray,
43{
44 /* Read intersection data into shader globals.
45 *
46 * TODO: this is redundant, could potentially remove some of this from
47 * ShaderData but would need to ensure that it also works for shadow
48 * shader evaluation. */
49 sd->u = isect->u;
50 sd->v = isect->v;
51 sd->ray_length = isect->t;
52 sd->type = isect->type;
53 sd->object = isect->object;
54 sd->object_flag = kernel_data_fetch(object_flag, sd->object);
55 sd->prim = isect->prim;
56 sd->flag = 0;
57
58 /* Read matrices and time. */
59 sd->time = ray->time;
60
61#ifdef __OBJECT_MOTION__
62 shader_setup_object_transforms(kg, sd, ray->time);
63#endif
64
65 /* Read ray data into shader globals. */
66 sd->wi = -ray->D;
67
68#ifdef __HAIR__
69 if (sd->type & PRIMITIVE_CURVE) {
70 /* curve */
71 curve_shader_setup(kg, sd, ray->P, ray->D, isect->t, isect->prim);
72 }
73 else
74#endif
75#ifdef __POINTCLOUD__
76 if (sd->type & PRIMITIVE_POINT)
77 {
78 /* point */
79 point_shader_setup(kg, sd, isect, ray);
80 }
81 else
82#endif
83 {
84 if (sd->type == PRIMITIVE_TRIANGLE) {
85 /* static triangle */
87 }
88 else {
90 /* motion triangle */
92 }
93
94 if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
95 /* instance transform */
96 object_normal_transform_auto(kg, sd, &sd->N);
97 object_normal_transform_auto(kg, sd, &sd->Ng);
98#ifdef __DPDU__
99 object_dir_transform_auto(kg, sd, &sd->dPdu);
100 object_dir_transform_auto(kg, sd, &sd->dPdv);
101#endif
102 }
103 }
104
105 sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags;
106
107 /* backfacing test */
108 const bool backfacing = (dot(sd->Ng, sd->wi) < 0.0f);
109
110 if (backfacing) {
111 sd->flag |= SD_BACKFACING;
112 sd->Ng = -sd->Ng;
113 sd->N = -sd->N;
114#ifdef __DPDU__
115 sd->dPdu = -sd->dPdu;
116 sd->dPdv = -sd->dPdv;
117#endif
118 }
119
120#ifdef __RAY_DIFFERENTIALS__
121 /* differentials */
122 sd->dP = differential_transfer_compact(ray->dP, ray->D, ray->dD, sd->ray_length);
123 sd->dI = differential_incoming_compact(ray->dD);
124 differential_dudv_compact(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
125#endif
126}
127
128/* ShaderData setup from position sampled on mesh */
129
131 ccl_private ShaderData *ccl_restrict sd,
132 const float3 P,
133 const float3 Ng,
134 const float3 I,
135 const int shader,
136 const int object,
137 const int prim,
138 const float u,
139 const float v,
140 const float t,
141 const float time,
142 const bool object_space,
143 const bool is_lamp)
144{
145 /* vectors */
146 sd->P = P;
147 sd->N = Ng;
148 sd->Ng = Ng;
149 sd->wi = I;
150 sd->shader = shader;
151 if (is_lamp) {
152 sd->type = PRIMITIVE_LAMP;
153 }
154 else if (prim != PRIM_NONE) {
155 sd->type = PRIMITIVE_TRIANGLE;
156 }
157 else {
158 sd->type = PRIMITIVE_NONE;
159 }
160
161 /* primitive */
162 sd->object = object;
163 /* Currently no access to bvh prim index for strand sd->prim. */
164 sd->prim = prim;
165 sd->u = u;
166 sd->v = v;
167 sd->time = time;
168 sd->ray_length = t;
169
170 sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags;
171 sd->object_flag = 0;
172 if (sd->object != OBJECT_NONE) {
173 sd->object_flag |= kernel_data_fetch(object_flag, sd->object);
174
175#ifdef __OBJECT_MOTION__
176 shader_setup_object_transforms(kg, sd, time);
177#endif
178
179 /* transform into world space */
180 if (object_space) {
181 object_position_transform_auto(kg, sd, &sd->P);
182 object_normal_transform_auto(kg, sd, &sd->Ng);
183 sd->N = sd->Ng;
184 object_dir_transform_auto(kg, sd, &sd->wi);
185 }
186
187 if (sd->type == PRIMITIVE_TRIANGLE) {
188 /* smooth normal */
189 if (sd->shader & SHADER_SMOOTH_NORMAL) {
190 sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
191
192 if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
193 object_normal_transform_auto(kg, sd, &sd->N);
194 }
195 }
196
197 /* dPdu/dPdv */
198#ifdef __DPDU__
199 triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
200
201 if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
202 object_dir_transform_auto(kg, sd, &sd->dPdu);
203 object_dir_transform_auto(kg, sd, &sd->dPdv);
204 }
205#endif
206 }
207 else {
208#ifdef __DPDU__
209 sd->dPdu = zero_float3();
210 sd->dPdv = zero_float3();
211#endif
212 }
213 }
214 else {
215#ifdef __DPDU__
216 sd->dPdu = zero_float3();
217 sd->dPdv = zero_float3();
218#endif
219 }
220
221 /* backfacing test */
222 if (sd->prim != PRIM_NONE) {
223 const bool backfacing = (dot(sd->Ng, sd->wi) < 0.0f);
224
225 if (backfacing) {
226 sd->flag |= SD_BACKFACING;
227 sd->Ng = -sd->Ng;
228 sd->N = -sd->N;
229#ifdef __DPDU__
230 sd->dPdu = -sd->dPdu;
231 sd->dPdv = -sd->dPdv;
232#endif
233 }
234 }
235
236#ifdef __RAY_DIFFERENTIALS__
237 /* no ray differentials here yet */
238 sd->dP = differential_zero_compact();
239 sd->dI = differential_zero_compact();
240 sd->du = differential_zero();
241 sd->dv = differential_zero();
242#endif
243}
244
245/* ShaderData setup for displacement */
246
248 ccl_private ShaderData *ccl_restrict sd,
249 const int object,
250 const int prim,
251 const float u,
252 const float v)
253{
254 float3 P;
255 float3 Ng;
256 const float3 I = zero_float3();
257 int shader;
258
259 triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
260
261 /* force smooth shading for displacement */
262 shader |= SHADER_SMOOTH_NORMAL;
263
265 sd,
266 P,
267 Ng,
268 I,
269 shader,
270 object,
271 prim,
272 u,
273 v,
274 0.0f,
275 0.5f,
276 !(kernel_data_fetch(object_flag, object) & SD_OBJECT_TRANSFORM_APPLIED),
277 false);
278
279 /* Assign some incoming direction to avoid division by zero. */
280 sd->wi = sd->N;
281}
282
283/* ShaderData setup for point on curve. */
284
285#ifdef __HAIR__
286ccl_device void shader_setup_from_curve(KernelGlobals kg,
287 ccl_private ShaderData *ccl_restrict sd,
288 const int object,
289 const int prim,
290 const int segment,
291 const float u)
292{
293 /* Primitive */
295 sd->prim = prim;
296 sd->u = u;
297 sd->v = 0.0f;
298 sd->time = 0.5f;
299 sd->ray_length = 0.0f;
300
301 /* Shader */
302 sd->shader = kernel_data_fetch(curves, prim).shader_id;
303 sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags;
304
305 /* Object */
306 sd->object = object;
307 sd->object_flag = kernel_data_fetch(object_flag, sd->object);
308# ifdef __OBJECT_MOTION__
309 shader_setup_object_transforms(kg, sd, sd->time);
310# endif
311
312 /* Get control points. */
313 const KernelCurve kcurve = kernel_data_fetch(curves, prim);
314
315 const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
316 const int k1 = k0 + 1;
317 const int ka = max(k0 - 1, kcurve.first_key);
318 const int kb = min(k1 + 1, kcurve.first_key + kcurve.num_keys - 1);
319
320 float4 P_curve[4];
321
322 P_curve[0] = kernel_data_fetch(curve_keys, ka);
323 P_curve[1] = kernel_data_fetch(curve_keys, k0);
324 P_curve[2] = kernel_data_fetch(curve_keys, k1);
325 P_curve[3] = kernel_data_fetch(curve_keys, kb);
326
327 /* Interpolate position and tangent. */
328 sd->P = (sd->type & PRIMITIVE_CURVE) == PRIMITIVE_CURVE_THICK_LINEAR ?
329 make_float3(linear_basis_eval(P_curve, sd->u)) :
330 make_float3(catmull_rom_basis_eval(P_curve, sd->u));
331# ifdef __DPDU__
332 sd->dPdu = (sd->type & PRIMITIVE_CURVE) == PRIMITIVE_CURVE_THICK_LINEAR ?
333 make_float3(linear_basis_derivative(P_curve, sd->u)) :
334 make_float3(catmull_rom_basis_derivative(P_curve, sd->u));
335# endif
336
337 /* Transform into world space */
338 if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
339 object_position_transform_auto(kg, sd, &sd->P);
340# ifdef __DPDU__
341 object_dir_transform_auto(kg, sd, &sd->dPdu);
342# endif
343 }
344
345 /* Pick arbitrary view direction, normals and bitangent to avoid NaNs elsewhere. */
346 sd->wi = normalize(cross(make_float3(0, 1, 0), sd->dPdu));
347 sd->N = sd->wi;
348 sd->Ng = sd->wi;
349# ifdef __DPDU__
350 sd->dPdv = cross(sd->dPdu, sd->Ng);
351# endif
352
353 /* No ray differentials currently. */
354# ifdef __RAY_DIFFERENTIALS__
355 sd->dP = differential_zero_compact();
356 sd->dI = differential_zero_compact();
357 sd->du = differential_zero();
358 sd->dv = differential_zero();
359# endif
360}
361#endif /* __HAIR__ */
362
363/* ShaderData setup from ray into background */
364
366 ccl_private ShaderData *ccl_restrict sd,
367 const float3 ray_P,
368 const float3 ray_D,
369 const float ray_time)
370{
371 /* for NDC coordinates */
372 sd->ray_P = ray_P;
373
374 /* vectors */
375 sd->P = ray_D;
376 sd->N = -ray_D;
377 sd->Ng = -ray_D;
378 sd->wi = -ray_D;
379 sd->shader = kernel_data.background.surface_shader;
380 sd->flag = kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags;
381 sd->object_flag = 0;
382 sd->time = ray_time;
383 sd->ray_length = FLT_MAX;
384
385 sd->object = OBJECT_NONE;
386 sd->prim = PRIM_NONE;
387 sd->type = PRIMITIVE_NONE;
388 sd->u = 0.0f;
389 sd->v = 0.0f;
390
391#ifdef __DPDU__
392 /* dPdu/dPdv */
393 sd->dPdu = zero_float3();
394 sd->dPdv = zero_float3();
395#endif
396
397#ifdef __RAY_DIFFERENTIALS__
398 /* differentials */
399 sd->dP = differential_zero_compact(); /* TODO: ray->dP */
400 sd->dI = differential_zero_compact();
401 sd->du = differential_zero();
402 sd->dv = differential_zero();
403#endif
404}
405
406/* ShaderData setup from point inside volume */
407
408#ifdef __VOLUME__
409ccl_device_inline void shader_setup_from_volume(ccl_private ShaderData *ccl_restrict sd,
410 const ccl_private Ray *ccl_restrict ray,
411 const int object)
412{
413
414 /* vectors */
415 sd->P = ray->P + ray->D * ray->tmin;
416 sd->N = -ray->D;
417 sd->Ng = -ray->D;
418 sd->wi = -ray->D;
419 sd->shader = SHADER_NONE;
420 sd->flag = 0;
421 sd->object_flag = 0;
422 sd->time = ray->time;
423 sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */
424
425 /* TODO: fill relevant fields for texture coordinates. */
426 sd->object = object;
427 sd->prim = PRIM_NONE;
428 sd->type = PRIMITIVE_VOLUME;
429
430 sd->u = 0.0f;
431 sd->v = 0.0f;
432
433# ifdef __DPDU__
434 /* dPdu/dPdv */
435 sd->dPdu = zero_float3();
436 sd->dPdv = zero_float3();
437# endif
438
439# ifdef __RAY_DIFFERENTIALS__
440 /* differentials */
441 sd->dP = differential_zero_compact(); /* TODO ray->dD */
442 sd->dI = differential_zero_compact();
443 sd->du = differential_zero();
444 sd->dv = differential_zero();
445# endif
446
447 /* for NDC coordinates */
448 sd->ray_P = ray->P;
449}
450#endif /* __VOLUME__ */
451
ATTR_WARN_UNUSED_RESULT const BMVert * v
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define kernel_assert(cond)
#define PRIMITIVE_PACK_SEGMENT(type, segment)
#define kernel_data
#define ccl_restrict
#define kernel_data_fetch(name, index)
#define SHADER_NONE
#define PRIM_NONE
#define PRIMITIVE_UNPACK_SEGMENT(type)
#define OBJECT_NONE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_forceinline float differential_transfer_compact(const float ray_dP, const float3, const float ray_dD, const float ray_t)
ccl_device_forceinline float differential_incoming_compact(const float dD)
ccl_device differential differential_zero()
ccl_device void differential_dudv_compact(ccl_private differential *du, ccl_private differential *dv, const float3 dPdu, const float3 dPdv, const float dP, const float3 Ng)
ccl_device_forceinline float differential_zero_compact()
ccl_device_inline void triangle_dPdudv(KernelGlobals kg, const int prim, ccl_private float3 *dPdu, ccl_private float3 *dPdv)
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, const float3 Ng, const int prim, const float u, float v)
ccl_device_inline void triangle_point_normal(KernelGlobals kg, const int object, const int prim, const float u, const float v, ccl_private float3 *P, ccl_private float3 *Ng, ccl_private int *shader)
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
#define object_normal_transform_auto
#define object_position_transform_auto
#define object_dir_transform_auto
@ SD_BACKFACING
@ PRIMITIVE_LAMP
@ PRIMITIVE_CURVE_THICK_LINEAR
@ PRIMITIVE_MOTION_TRIANGLE
@ PRIMITIVE_NONE
@ PRIMITIVE_VOLUME
@ PRIMITIVE_CURVE
@ PRIMITIVE_CURVE_THICK
@ PRIMITIVE_TRIANGLE
@ PRIMITIVE_POINT
@ SHADER_SMOOTH_NORMAL
@ SHADER_MASK
@ SD_OBJECT_MOTION
@ SD_OBJECT_TRANSFORM_APPLIED
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
CCL_NAMESPACE_BEGIN ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg, ccl_private ShaderData *sd)
#define I
#define ccl_device
ccl_device_inline void shader_setup_from_sample(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const float3 P, const float3 Ng, const float3 I, const int shader, const int object, const int prim, const float u, const float v, const float t, const float time, const bool object_space, const bool is_lamp)
ccl_device void shader_setup_from_displace(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const int object, const int prim, const float u, const float v)
ccl_device_inline void shader_setup_from_background(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const float3 ray_P, const float3 ray_D, const float ray_time)
ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const ccl_private Ray *ccl_restrict ray, const ccl_private Intersection *ccl_restrict isect)
Definition shader_data.h:39
CCL_NAMESPACE_BEGIN ccl_device void shader_setup_object_transforms(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const float time)
Definition shader_data.h:25
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
max
Definition text_draw.cc:251
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:525
ccl_device_inline void triangle_shader_setup(KernelGlobals kg, ccl_private ShaderData *sd)