Blender V5.0
tex_coord.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
10#include "kernel/geom/object.h"
12
14#include "kernel/svm/types.h"
15#include "kernel/svm/util.h"
16#include "util/math_base.h"
17
19
20/* Texture Coordinate Node */
21
23{
24 float3 data = sd->wi;
25 if (sd->object != OBJECT_NONE) {
26 data = -reflect(data, sd->N);
27 }
28 return data;
29}
30
32 const ccl_private ShaderData *sd,
33 const ccl_private float3 &P)
34{
35 float3 data = P;
36 const Transform tfm = kernel_data.cam.worldtocamera;
37 if (sd->object == OBJECT_NONE) {
38 data += camera_position(kg);
39 }
40 data = transform_point(&tfm, data);
41 return data;
42}
43
45 ccl_private ShaderData *sd,
46 const uint32_t path_flag,
47 ccl_private float *stack,
48 const uint4 node,
49 int offset)
50{
52 const uint type = node.y;
53 const uint out_offset = node.z;
54
55 switch ((NodeTexCoord)type) {
58 data = sd->P;
59 if (type == NODE_TEXCO_OBJECT) {
60 if (sd->object != OBJECT_NONE) {
62 }
63 }
64 else {
65 Transform tfm;
66 tfm.x = read_node_float(kg, &offset);
67 tfm.y = read_node_float(kg, &offset);
68 tfm.z = read_node_float(kg, &offset);
69 data = transform_point(&tfm, data);
70 }
71 break;
72 }
73 case NODE_TEXCO_NORMAL: {
74 data = sd->N;
76 break;
77 }
78 case NODE_TEXCO_CAMERA: {
79 const float3 P = sd->P;
80 data = svm_texco_camera(kg, sd, P);
81 break;
82 }
83 case NODE_TEXCO_WINDOW: {
84 if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
86 {
87 data = camera_world_to_ndc(kg, sd, sd->ray_P);
88 }
89 else {
90 data = camera_world_to_ndc(kg, sd, sd->P);
91 }
92 data.z = 0.0f;
93 break;
94 }
97 break;
98 }
100 data = object_dupli_generated(kg, sd->object);
101 break;
102 }
103 case NODE_TEXCO_DUPLI_UV: {
104 data = object_dupli_uv(kg, sd->object);
105 break;
106 }
108 data = sd->P;
109
110#ifdef __VOLUME__
111 if (sd->object != OBJECT_NONE) {
112 data = volume_normalized_position(kg, sd, data);
113 }
114#endif
115 break;
116 }
117 }
118
119 stack_store_float3(stack, out_offset, data);
120 return offset;
121}
122
124 ccl_private ShaderData *sd,
125 const float u,
126 const float v)
127{
128 float3 N;
129 if ((sd->type & PRIMITIVE_TRIANGLE) && (sd->shader & SHADER_SMOOTH_NORMAL)) {
130 N = (sd->type == PRIMITIVE_TRIANGLE) ?
131 triangle_smooth_normal(kg, zero_float3(), sd->prim, u, v) :
132 motion_triangle_smooth_normal(kg, zero_float3(), sd->object, sd->prim, u, v, sd->time);
133 if (is_zero(N)) {
134 N = sd->Ng;
136 }
137 else {
138 if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) {
139 /* Transform to local space. */
141 }
142 if (sd->flag & SD_BACKFACING) {
143 N = -N;
144 }
145 }
146 }
147 else {
148 /* TODO: implement for curve. */
149 N = sd->N;
151 }
152 return N;
153}
154
156 ccl_private ShaderData *sd,
157 const uint32_t path_flag,
158 ccl_private float *stack,
159 const uint4 node,
160 int offset)
161{
162#ifdef __RAY_DIFFERENTIALS__
164 const uint type = node.y;
165 const uint out_offset = node.z;
166 const float bump_filter_width = __uint_as_float(node.w);
167
168 switch ((NodeTexCoord)type) {
171 data = svm_node_bump_P_dx(sd, bump_filter_width);
172 if (type == NODE_TEXCO_OBJECT) {
173 if (sd->object != OBJECT_NONE) {
175 }
176 }
177 else {
178 Transform tfm;
179 tfm.x = read_node_float(kg, &offset);
180 tfm.y = read_node_float(kg, &offset);
181 tfm.z = read_node_float(kg, &offset);
182 data = transform_point(&tfm, data);
183 }
184 break;
185 }
186 case NODE_TEXCO_NORMAL: {
188 kg, sd, sd->u + sd->du.dx * bump_filter_width, sd->v + sd->dv.dx * bump_filter_width);
189 break;
190 }
191 case NODE_TEXCO_CAMERA: {
192 const float3 P = svm_node_bump_P_dx(sd, bump_filter_width);
193 data = svm_texco_camera(kg, sd, P);
194 break;
195 }
196 case NODE_TEXCO_WINDOW: {
197 if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
199 {
200 data = camera_world_to_ndc(kg, sd, sd->ray_P);
201 }
202 else {
203 data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dx(sd, bump_filter_width));
204 }
205 data.z = 0.0f;
206 break;
207 }
210 break;
211 }
213 data = object_dupli_generated(kg, sd->object);
214 break;
215 }
216 case NODE_TEXCO_DUPLI_UV: {
217 data = object_dupli_uv(kg, sd->object);
218 break;
219 }
221 data = svm_node_bump_P_dx(sd, bump_filter_width);
222
223# ifdef __VOLUME__
224 if (sd->object != OBJECT_NONE) {
225 data = volume_normalized_position(kg, sd, data);
226 }
227# endif
228 break;
229 }
230 }
231
232 stack_store_float3(stack, out_offset, data);
233 return offset;
234#else
235 return svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
236#endif
237}
238
240 ccl_private ShaderData *sd,
241 const uint32_t path_flag,
242 ccl_private float *stack,
243 const uint4 node,
244 int offset)
245{
246#ifdef __RAY_DIFFERENTIALS__
248 const uint type = node.y;
249 const uint out_offset = node.z;
250 const float bump_filter_width = __uint_as_float(node.w);
251
252 switch ((NodeTexCoord)type) {
255 data = svm_node_bump_P_dy(sd, bump_filter_width);
256 if (type == NODE_TEXCO_OBJECT) {
257 if (sd->object != OBJECT_NONE) {
259 }
260 }
261 else {
262 Transform tfm;
263 tfm.x = read_node_float(kg, &offset);
264 tfm.y = read_node_float(kg, &offset);
265 tfm.z = read_node_float(kg, &offset);
266 data = transform_point(&tfm, data);
267 }
268 break;
269 }
270 case NODE_TEXCO_NORMAL: {
272 kg, sd, sd->u + sd->du.dy * bump_filter_width, sd->v + sd->dv.dy * bump_filter_width);
273 break;
274 }
275 case NODE_TEXCO_CAMERA: {
276 const float3 P = svm_node_bump_P_dy(sd, bump_filter_width);
277 data = svm_texco_camera(kg, sd, P);
278 break;
279 }
280 case NODE_TEXCO_WINDOW: {
281 if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
283 {
284 data = camera_world_to_ndc(kg, sd, sd->ray_P);
285 }
286 else {
287 data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dy(sd, bump_filter_width));
288 }
289 data.z = 0.0f;
290 break;
291 }
294 break;
295 }
297 data = object_dupli_generated(kg, sd->object);
298 break;
299 }
300 case NODE_TEXCO_DUPLI_UV: {
301 data = object_dupli_uv(kg, sd->object);
302 break;
303 }
305 data = svm_node_bump_P_dy(sd, bump_filter_width);
306
307# ifdef __VOLUME__
308 if (sd->object != OBJECT_NONE) {
309 data = volume_normalized_position(kg, sd, data);
310 }
311# endif
312 break;
313 }
314 }
315
316 stack_store_float3(stack, out_offset, data);
317 return offset;
318#else
319 return svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
320#endif
321}
322
324 ccl_private ShaderData *sd,
325 ccl_private float *stack,
326 const uint4 node)
327{
328 uint color_offset;
329 uint strength_offset;
330 uint normal_offset;
331 uint space;
332 svm_unpack_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space);
333
334 float3 color = stack_load_float3(stack, color_offset);
335 color = 2.0f * make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
336
337 const bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
338 float3 N;
339 float strength = stack_load_float(stack, strength_offset);
340 bool linear_interpolate_strength = false;
341
342 if (space == NODE_NORMAL_MAP_TANGENT) {
343 /* tangent space */
344 if (sd->object == OBJECT_NONE || (sd->type & PRIMITIVE_TRIANGLE) == 0) {
345 /* Fall back to unperturbed normal. */
346 stack_store_float3(stack, normal_offset, sd->N);
347 return;
348 }
349
350 /* first try to get tangent attribute */
351 const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
352 const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
353
354 if (attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND) {
355 /* Fall back to unperturbed normal. */
356 stack_store_float3(stack, normal_offset, sd->N);
357 return;
358 }
359
360 /* get _unnormalized_ interpolated normal and tangent */
361 const float3 tangent = primitive_surface_attribute<float3>(kg, sd, attr).val;
362 const float sign = primitive_surface_attribute<float>(kg, sd, attr_sign).val;
363 float3 normal;
364
365 if (sd->shader & SHADER_SMOOTH_NORMAL) {
366 const AttributeDescriptor attr_undisplaced_normal = find_attribute(
367 kg, sd->object, sd->prim, ATTR_STD_NORMAL_UNDISPLACED);
368 if (attr_undisplaced_normal.offset != ATTR_STD_NOT_FOUND) {
369 normal =
370 primitive_surface_attribute<float3>(kg, sd, attr_undisplaced_normal, false, false).val;
371 /* Can't interpolate in tangent space as the displaced normal is not used
372 * for the tangent frame. */
373 linear_interpolate_strength = true;
374 }
375 else {
376 normal = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v);
377 }
378 }
379 else {
380 normal = sd->Ng;
381
382 /* the normal is already inverted, which is too soon for the math here */
383 if (is_backfacing) {
384 normal = -normal;
385 }
386
387 object_inverse_normal_transform(kg, sd, &normal);
388 }
389 /* Apply strength in the tangent case. */
390 if (!linear_interpolate_strength) {
391 color.x *= strength;
392 color.y *= strength;
393 color.z = mix(1.0f, color.z, saturatef(strength));
394 }
395
396 /* apply normal map */
397 const float3 B = sign * cross(normal, tangent);
398 N = safe_normalize(to_global(color, tangent, B, normal));
399
400 /* transform to world space */
401 object_normal_transform(kg, sd, &N);
402
403 /* invert normal for backfacing polygons */
404 if (is_backfacing) {
405 N = -N;
406 }
407 }
408 else {
409 linear_interpolate_strength = true;
410
411 /* strange blender convention */
413 color.y = -color.y;
414 color.z = -color.z;
415 }
416
417 /* object, world space */
418 N = color;
419
421 object_normal_transform(kg, sd, &N);
422 }
423 else {
424 N = safe_normalize(N);
425 }
426
427 /* invert normal for backfacing polygons */
428 if (is_backfacing) {
429 N = -N;
430 }
431 }
432
433 /* Use simple linear interpolation if we can't do it in tangent space. */
434 if (linear_interpolate_strength && strength != 1.0f) {
435 strength = max(strength, 0.0f);
436 N = safe_normalize(sd->N + (N - sd->N) * strength);
437 }
438
439 if (is_zero(N) || !isfinite_safe(N)) {
440 N = sd->N;
441 }
442
443 stack_store_float3(stack, normal_offset, N);
444}
445
447 ccl_private ShaderData *sd,
448 ccl_private float *stack,
449 const uint4 node)
450{
451 uint tangent_offset;
452 uint direction_type;
453 uint axis;
454 svm_unpack_node_uchar3(node.y, &tangent_offset, &direction_type, &axis);
455
456 float3 tangent;
457 float3 attribute_value;
458 const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
459 if (desc.offset != ATTR_STD_NOT_FOUND) {
460 if (desc.type == NODE_ATTR_FLOAT2) {
461 const float2 value = primitive_surface_attribute<float2>(kg, sd, desc).val;
462 attribute_value.x = value.x;
463 attribute_value.y = value.y;
464 attribute_value.z = 0.0f;
465 }
466 else {
467 attribute_value = primitive_surface_attribute<float3>(kg, sd, desc).val;
468 }
469 }
470
471 if (direction_type == NODE_TANGENT_UVMAP) {
472 /* UV map */
473 if (desc.offset == ATTR_STD_NOT_FOUND) {
474 stack_store_float3(stack, tangent_offset, zero_float3());
475 return;
476 }
477 tangent = attribute_value;
478 }
479 else {
480 /* radial */
481 float3 generated;
482
483 if (desc.offset == ATTR_STD_NOT_FOUND) {
484 generated = sd->P;
485 }
486 else {
487 generated = attribute_value;
488 }
489
490 if (axis == NODE_TANGENT_AXIS_X) {
491 tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
492 }
493 else if (axis == NODE_TANGENT_AXIS_Y) {
494 tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
495 }
496 else {
497 tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
498 }
499 }
500
501 object_normal_transform(kg, sd, &tangent);
502 tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
503 stack_store_float3(stack, tangent_offset, tangent);
504}
505
unsigned int uint
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
ccl_device_inline float stack_load_float(const ccl_private float *stack, const uint a)
ccl_device_inline float4 read_node_float(KernelGlobals kg, ccl_private int *const offset)
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
ccl_device_forceinline void svm_unpack_node_uchar3(const uint i, ccl_private uint *x, ccl_private uint *y, ccl_private uint *z)
ccl_device_forceinline void svm_unpack_node_uchar4(const uint i, ccl_private uint *x, ccl_private uint *y, ccl_private uint *z, ccl_private uint *w)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 stack_load_float3(const ccl_private float *stack, const uint a)
ccl_device_inline T to_global(const float2 p, const T X, const T Y)
#define kernel_data
#define OBJECT_NONE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define ccl_device_noinline
#define CCL_NAMESPACE_END
#define saturatef(x)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __uint_as_float(x)
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, const float3 Ng, const int prim, const float u, float v)
ccl_device_inline float3 triangle_smooth_normal_unnormalized(KernelGlobals kg, const ccl_private ShaderData *sd, const float3 Ng, const int prim, const float u, float v)
VecBase< T, D > reflect(VecOp< T, D >, VecOp< T, D >) RET
VecBase< float, D > normalize(VecOp< float, D >) RET
constexpr T sign(T) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
ccl_device_inline float3 camera_position(KernelGlobals kg)
ccl_device_inline float3 camera_world_to_ndc(KernelGlobals kg, ccl_private ShaderData *sd, float3 P)
ccl_device_inline float3 object_dupli_uv(KernelGlobals kg, const int object)
ccl_device_inline void object_inverse_position_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *P)
ccl_device_inline void object_normal_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *N)
ccl_device_inline float3 object_dupli_generated(KernelGlobals kg, const int object)
ccl_device_inline void object_inverse_normal_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *N)
ccl_device_forceinline float3 svm_node_bump_P_dx(const ccl_private ShaderData *sd, const float bump_filter_width)
ccl_device_forceinline float3 svm_node_bump_P_dy(const ccl_private ShaderData *sd, const float bump_filter_width)
@ NODE_TANGENT_AXIS_Y
@ NODE_TANGENT_AXIS_X
NodeTexCoord
@ NODE_TEXCO_VOLUME_GENERATED
@ NODE_TEXCO_REFLECTION
@ NODE_TEXCO_WINDOW
@ NODE_TEXCO_OBJECT
@ NODE_TEXCO_DUPLI_UV
@ NODE_TEXCO_OBJECT_WITH_TRANSFORM
@ NODE_TEXCO_DUPLI_GENERATED
@ NODE_TEXCO_CAMERA
@ NODE_TEXCO_NORMAL
@ NODE_ATTR_FLOAT2
@ NODE_TANGENT_UVMAP
@ NODE_NORMAL_MAP_TANGENT
@ NODE_NORMAL_MAP_BLENDER_WORLD
@ NODE_NORMAL_MAP_BLENDER_OBJECT
@ NODE_NORMAL_MAP_OBJECT
@ SD_BACKFACING
@ PRIMITIVE_TRIANGLE
@ ATTR_STD_NOT_FOUND
@ ATTR_STD_NORMAL_UNDISPLACED
@ PATH_RAY_CAMERA
@ SHADER_SMOOTH_NORMAL
@ SD_OBJECT_TRANSFORM_APPLIED
@ CAMERA_ORTHOGRAPHIC
ccl_device_inline bool isfinite_safe(const float f)
Definition math_base.h:348
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
#define N
#define B
ccl_device_inline float3 motion_triangle_smooth_normal(KernelGlobals kg, const float3 Ng, const int object, const uint3 tri_vindex, const int numsteps, const int step, const float t, const float u, const float v)
CCL_NAMESPACE_BEGIN ccl_device_forceinline dual< T > primitive_surface_attribute(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const bool dx=false, const bool dy=false)
Definition primitive.h:32
#define mix
static bool find_attribute(const std::string &attributes, const char *search_attribute)
NodeAttributeType type
float4 y
Definition transform.h:23
float4 x
Definition transform.h:23
float4 z
Definition transform.h:23
float x
float y
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
uint y
Definition types_uint4.h:13
uint z
Definition types_uint4.h:13
uint w
Definition types_uint4.h:13
ccl_device_noinline void svm_node_tangent(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node)
Definition tex_coord.h:446
ccl_device_inline float3 svm_texco_camera(KernelGlobals kg, const ccl_private ShaderData *sd, const ccl_private float3 &P)
Definition tex_coord.h:31
ccl_device_noinline int svm_node_tex_coord_bump_dx(KernelGlobals kg, ccl_private ShaderData *sd, const uint32_t path_flag, ccl_private float *stack, const uint4 node, int offset)
Definition tex_coord.h:155
ccl_device_noinline int svm_node_tex_coord(KernelGlobals kg, ccl_private ShaderData *sd, const uint32_t path_flag, ccl_private float *stack, const uint4 node, int offset)
Definition tex_coord.h:44
CCL_NAMESPACE_BEGIN ccl_device_inline float3 svm_texco_reflection(const ccl_private ShaderData *sd)
Definition tex_coord.h:22
ccl_device_noinline int svm_node_tex_coord_bump_dy(KernelGlobals kg, ccl_private ShaderData *sd, const uint32_t path_flag, ccl_private float *stack, const uint4 node, int offset)
Definition tex_coord.h:239
ccl_device_inline float3 texco_normal_from_uv(KernelGlobals kg, ccl_private ShaderData *sd, const float u, const float v)
Definition tex_coord.h:123
ccl_device_noinline void svm_node_normal_map(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node)
Definition tex_coord.h:323
max
Definition text_draw.cc:251
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56