Blender V4.5
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 ccl_private ShaderData *sd,
24 const uint32_t path_flag,
25 ccl_private float *stack,
26 const uint4 node,
27 int offset)
28{
30 const uint type = node.y;
31 const uint out_offset = node.z;
32
33 switch ((NodeTexCoord)type) {
36 data = sd->P;
37 if (type == NODE_TEXCO_OBJECT) {
38 if (sd->object != OBJECT_NONE) {
40 }
41 }
42 else {
43 Transform tfm;
44 tfm.x = read_node_float(kg, &offset);
45 tfm.y = read_node_float(kg, &offset);
46 tfm.z = read_node_float(kg, &offset);
47 data = transform_point(&tfm, data);
48 }
49 break;
50 }
51 case NODE_TEXCO_NORMAL: {
52 data = sd->N;
54 break;
55 }
56 case NODE_TEXCO_CAMERA: {
57 const Transform tfm = kernel_data.cam.worldtocamera;
58
59 if (sd->object != OBJECT_NONE) {
60 data = transform_point(&tfm, sd->P);
61 }
62 else {
63 data = transform_point(&tfm, sd->P + camera_position(kg));
64 }
65 break;
66 }
67 case NODE_TEXCO_WINDOW: {
68 if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
70 {
71 data = camera_world_to_ndc(kg, sd, sd->ray_P);
72 }
73 else {
74 data = camera_world_to_ndc(kg, sd, sd->P);
75 }
76 data.z = 0.0f;
77 break;
78 }
80 if (sd->object != OBJECT_NONE) {
81 data = 2.0f * dot(sd->N, sd->wi) * sd->N - sd->wi;
82 }
83 else {
84 data = sd->wi;
85 }
86 break;
87 }
89 data = object_dupli_generated(kg, sd->object);
90 break;
91 }
93 data = object_dupli_uv(kg, sd->object);
94 break;
95 }
97 data = sd->P;
98
99#ifdef __VOLUME__
100 if (sd->object != OBJECT_NONE) {
101 data = volume_normalized_position(kg, sd, data);
102 }
103#endif
104 break;
105 }
106 }
107
108 stack_store_float3(stack, out_offset, data);
109 return offset;
110}
111
113 ccl_private ShaderData *sd,
114 const float u,
115 const float v)
116{
117 float3 N;
118 if ((sd->type & PRIMITIVE_TRIANGLE) && (sd->shader & SHADER_SMOOTH_NORMAL)) {
119 N = (sd->type == PRIMITIVE_TRIANGLE) ?
120 triangle_smooth_normal(kg, zero_float3(), sd->prim, u, v) :
121 motion_triangle_smooth_normal(kg, zero_float3(), sd->object, sd->prim, u, v, sd->time);
122 if (is_zero(N)) {
123 N = sd->Ng;
125 }
126 else {
127 if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) {
128 /* Transform to local space. */
130 }
131 if (sd->flag & SD_BACKFACING) {
132 N = -N;
133 }
134 }
135 }
136 else {
137 /* TODO: implement for curve. */
138 N = sd->N;
140 }
141 return N;
142}
143
145 ccl_private ShaderData *sd,
146 const uint32_t path_flag,
147 ccl_private float *stack,
148 const uint4 node,
149 int offset)
150{
151#ifdef __RAY_DIFFERENTIALS__
153 const uint type = node.y;
154 const uint out_offset = node.z;
155 const float bump_filter_width = __uint_as_float(node.w);
156
157 switch ((NodeTexCoord)type) {
160 data = svm_node_bump_P_dx(sd, bump_filter_width);
161 if (type == NODE_TEXCO_OBJECT) {
162 if (sd->object != OBJECT_NONE) {
164 }
165 }
166 else {
167 Transform tfm;
168 tfm.x = read_node_float(kg, &offset);
169 tfm.y = read_node_float(kg, &offset);
170 tfm.z = read_node_float(kg, &offset);
171 data = transform_point(&tfm, data);
172 }
173 break;
174 }
175 case NODE_TEXCO_NORMAL: {
177 kg, sd, sd->u + sd->du.dx * bump_filter_width, sd->v + sd->dv.dx * bump_filter_width);
178 break;
179 }
180 case NODE_TEXCO_CAMERA: {
181 const Transform tfm = kernel_data.cam.worldtocamera;
182
183 if (sd->object != OBJECT_NONE) {
184 data = transform_point(&tfm, svm_node_bump_P_dx(sd, bump_filter_width));
185 }
186 else {
187 data = transform_point(&tfm,
188 svm_node_bump_P_dx(sd, bump_filter_width) + camera_position(kg));
189 }
190 break;
191 }
192 case NODE_TEXCO_WINDOW: {
193 if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
195 {
196 data = camera_world_to_ndc(kg, sd, sd->ray_P);
197 }
198 else {
199 data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dx(sd, bump_filter_width));
200 }
201 data.z = 0.0f;
202 break;
203 }
205 if (sd->object != OBJECT_NONE) {
206 data = 2.0f * dot(sd->N, sd->wi) * sd->N - sd->wi;
207 }
208 else {
209 data = sd->wi;
210 }
211 break;
212 }
214 data = object_dupli_generated(kg, sd->object);
215 break;
216 }
217 case NODE_TEXCO_DUPLI_UV: {
218 data = object_dupli_uv(kg, sd->object);
219 break;
220 }
222 data = svm_node_bump_P_dx(sd, bump_filter_width);
223
224# ifdef __VOLUME__
225 if (sd->object != OBJECT_NONE) {
226 data = volume_normalized_position(kg, sd, data);
227 }
228# endif
229 break;
230 }
231 }
232
233 stack_store_float3(stack, out_offset, data);
234 return offset;
235#else
236 return svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
237#endif
238}
239
241 ccl_private ShaderData *sd,
242 const uint32_t path_flag,
243 ccl_private float *stack,
244 const uint4 node,
245 int offset)
246{
247#ifdef __RAY_DIFFERENTIALS__
249 const uint type = node.y;
250 const uint out_offset = node.z;
251 const float bump_filter_width = __uint_as_float(node.w);
252
253 switch ((NodeTexCoord)type) {
256 data = svm_node_bump_P_dy(sd, bump_filter_width);
257 if (type == NODE_TEXCO_OBJECT) {
258 if (sd->object != OBJECT_NONE) {
260 }
261 }
262 else {
263 Transform tfm;
264 tfm.x = read_node_float(kg, &offset);
265 tfm.y = read_node_float(kg, &offset);
266 tfm.z = read_node_float(kg, &offset);
267 data = transform_point(&tfm, data);
268 }
269 break;
270 }
271 case NODE_TEXCO_NORMAL: {
273 kg, sd, sd->u + sd->du.dy * bump_filter_width, sd->v + sd->dv.dy * bump_filter_width);
274 break;
275 }
276 case NODE_TEXCO_CAMERA: {
277 const Transform tfm = kernel_data.cam.worldtocamera;
278
279 if (sd->object != OBJECT_NONE) {
280 data = transform_point(&tfm, svm_node_bump_P_dy(sd, bump_filter_width));
281 }
282 else {
283 data = transform_point(&tfm,
284 svm_node_bump_P_dy(sd, bump_filter_width) + camera_position(kg));
285 }
286 break;
287 }
288 case NODE_TEXCO_WINDOW: {
289 if ((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE &&
291 {
292 data = camera_world_to_ndc(kg, sd, sd->ray_P);
293 }
294 else {
295 data = camera_world_to_ndc(kg, sd, svm_node_bump_P_dy(sd, bump_filter_width));
296 }
297 data.z = 0.0f;
298 break;
299 }
301 if (sd->object != OBJECT_NONE) {
302 data = 2.0f * dot(sd->N, sd->wi) * sd->N - sd->wi;
303 }
304 else {
305 data = sd->wi;
306 }
307 break;
308 }
310 data = object_dupli_generated(kg, sd->object);
311 break;
312 }
313 case NODE_TEXCO_DUPLI_UV: {
314 data = object_dupli_uv(kg, sd->object);
315 break;
316 }
318 data = svm_node_bump_P_dy(sd, bump_filter_width);
319
320# ifdef __VOLUME__
321 if (sd->object != OBJECT_NONE) {
322 data = volume_normalized_position(kg, sd, data);
323 }
324# endif
325 break;
326 }
327 }
328
329 stack_store_float3(stack, out_offset, data);
330 return offset;
331#else
332 return svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
333#endif
334}
335
337 ccl_private ShaderData *sd,
338 ccl_private float *stack,
339 const uint4 node)
340{
341 uint color_offset;
342 uint strength_offset;
343 uint normal_offset;
344 uint space;
345 svm_unpack_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space);
346
347 float3 color = stack_load_float3(stack, color_offset);
348 color = 2.0f * make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
349
350 const bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
351 float3 N;
352 float strength = stack_load_float(stack, strength_offset);
353 if (space == NODE_NORMAL_MAP_TANGENT) {
354 /* tangent space */
355 if (sd->object == OBJECT_NONE || (sd->type & PRIMITIVE_TRIANGLE) == 0) {
356 /* Fall back to unperturbed normal. */
357 stack_store_float3(stack, normal_offset, sd->N);
358 return;
359 }
360
361 /* first try to get tangent attribute */
362 const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
363 const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
364
365 if (attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND) {
366 /* Fall back to unperturbed normal. */
367 stack_store_float3(stack, normal_offset, sd->N);
368 return;
369 }
370
371 /* get _unnormalized_ interpolated normal and tangent */
372 const float3 tangent = primitive_surface_attribute<float3>(kg, sd, attr, nullptr, nullptr);
373 const float sign = primitive_surface_attribute<float>(kg, sd, attr_sign, nullptr, nullptr);
374 float3 normal;
375
376 if (sd->shader & SHADER_SMOOTH_NORMAL) {
377 normal = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v);
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 color.x *= strength;
391 color.y *= strength;
392 color.z = mix(1.0f, color.z, saturatef(strength));
393
394 /* apply normal map */
395 const float3 B = sign * cross(normal, tangent);
396 N = safe_normalize(to_global(color, tangent, B, normal));
397
398 /* transform to world space */
399 object_normal_transform(kg, sd, &N);
400
401 /* invert normal for backfacing polygons */
402 if (is_backfacing) {
403 N = -N;
404 }
405 }
406 else {
407 /* strange blender convention */
409 color.y = -color.y;
410 color.z = -color.z;
411 }
412
413 /* object, world space */
414 N = color;
415
417 object_normal_transform(kg, sd, &N);
418 }
419 else {
420 N = safe_normalize(N);
421 }
422
423 /* invert normal for backfacing polygons */
424 if (is_backfacing) {
425 N = -N;
426 }
427
428 /* Apply strength in all but tangent space. */
429 if (strength != 1.0f) {
430 strength = max(strength, 0.0f);
431 N = safe_normalize(sd->N + (N - sd->N) * strength);
432 }
433 }
434
435 if (is_zero(N)) {
436 N = sd->N;
437 }
438
439 stack_store_float3(stack, normal_offset, N);
440}
441
443 ccl_private ShaderData *sd,
444 ccl_private float *stack,
445 const uint4 node)
446{
447 uint tangent_offset;
448 uint direction_type;
449 uint axis;
450 svm_unpack_node_uchar3(node.y, &tangent_offset, &direction_type, &axis);
451
452 float3 tangent;
453 float3 attribute_value;
454 const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
455 if (desc.offset != ATTR_STD_NOT_FOUND) {
456 if (desc.type == NODE_ATTR_FLOAT2) {
457 const float2 value = primitive_surface_attribute<float2>(kg, sd, desc, nullptr, nullptr);
458 attribute_value.x = value.x;
459 attribute_value.y = value.y;
460 attribute_value.z = 0.0f;
461 }
462 else {
463 attribute_value = primitive_surface_attribute<float3>(kg, sd, desc, nullptr, nullptr);
464 }
465 }
466
467 if (direction_type == NODE_TANGENT_UVMAP) {
468 /* UV map */
469 if (desc.offset == ATTR_STD_NOT_FOUND) {
470 stack_store_float3(stack, tangent_offset, zero_float3());
471 return;
472 }
473 tangent = attribute_value;
474 }
475 else {
476 /* radial */
477 float3 generated;
478
479 if (desc.offset == ATTR_STD_NOT_FOUND) {
480 generated = sd->P;
481 }
482 else {
483 generated = attribute_value;
484 }
485
486 if (axis == NODE_TANGENT_AXIS_X) {
487 tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
488 }
489 else if (axis == NODE_TANGENT_AXIS_Y) {
490 tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
491 }
492 else {
493 tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
494 }
495 }
496
497 object_normal_transform(kg, sd, &tangent);
498 tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
499 stack_store_float3(stack, tangent_offset, tangent);
500}
501
unsigned int uint
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
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< float, D > normalize(VecOp< float, D >) RET
constexpr T sign(T) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
#define mix(a, b, c)
Definition hash.h:35
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
@ PATH_RAY_CAMERA
@ SHADER_SMOOTH_NORMAL
@ SD_OBJECT_TRANSFORM_APPLIED
@ CAMERA_ORTHOGRAPHIC
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:15
#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 T primitive_surface_attribute(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, ccl_private T *dfdx, ccl_private T *dfdy)
Definition primitive.h:32
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_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
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:442
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:144
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:240
ccl_device_inline float3 texco_normal_from_uv(KernelGlobals kg, ccl_private ShaderData *sd, const float u, const float v)
Definition tex_coord.h:112
CCL_NAMESPACE_BEGIN 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:22
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:336
max
Definition text_draw.cc:251
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56