Blender V5.0
displace.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
10
11#include "kernel/svm/util.h"
12
14
16
17/* Bump Node */
18template<uint node_feature_mask>
20 ccl_private ShaderData *sd,
21 ccl_private float *stack,
22 const uint4 node,
23 int offset)
24{
25 uint out_offset;
26 uint bump_state_offset;
27 svm_unpack_node_uchar2(node.w, &out_offset, &bump_state_offset);
28 const uint4 data_node = read_node(kg, &offset);
29 const float bump_filter_width = __uint_as_float(data_node.x);
30
31#ifdef __RAY_DIFFERENTIALS__
33 {
34 /* get normal input */
35 uint normal_offset;
36 uint scale_offset;
38 uint use_object_space;
39 svm_unpack_node_uchar4(node.y, &normal_offset, &scale_offset, &invert, &use_object_space);
40
41 float3 normal_in = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) :
42 sd->N;
43
44 /* If we have saved bump state, read the full differential from there.
45 * Just using the compact form in those cases leads to incorrect normals (see #111588). */
47 if (bump_state_offset == SVM_STACK_INVALID) {
48 dP = differential_from_compact(sd->Ng, sd->dP);
49 }
50 else {
51 dP.dx = stack_load_float3(stack, bump_state_offset + 4);
52 dP.dy = stack_load_float3(stack, bump_state_offset + 7);
53 }
54
55 if (use_object_space) {
56 object_inverse_normal_transform(kg, sd, &normal_in);
59 }
60
61 /* get surface tangents from normal */
62 const float3 Rx = cross(dP.dy, normal_in);
63 const float3 Ry = cross(normal_in, dP.dx);
64
65 /* get bump values */
66 uint c_offset;
67 uint x_offset;
68 uint y_offset;
69 uint strength_offset;
70 svm_unpack_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &strength_offset);
71
72 const float h_c = stack_load_float(stack, c_offset);
73 const float h_x = stack_load_float(stack, x_offset);
74 const float h_y = stack_load_float(stack, y_offset);
75
76 /* compute surface gradient and determinant */
77 const float det = dot(dP.dx, Rx);
78 const float3 surfgrad = (h_x - h_c) * Rx + (h_y - h_c) * Ry;
79
80 const float absdet = fabsf(det);
81
82 float strength = stack_load_float(stack, strength_offset);
83 float scale = stack_load_float(stack, scale_offset);
84
85 if (invert) {
86 scale *= -1.0f;
87 }
88
89 strength = max(strength, 0.0f);
90
91 /* Compute and output perturbed normal.
92 * dP'dx = dPdx + scale * (h_x - h_c) / filter_width * normal
93 * dP'dy = dPdy + scale * (h_y - h_c) / filter_width * normal
94 * N' = cross(dP'dx, dP'dy)
95 * = cross(dPdx, dPdy) - scale * ((h_y - h_c) / filter_width * Ry + (h_x - h_c) /
96 * filter_width * Rx) ≈ det * normal_in - scale * surfgrad / filter_width
97 */
98 float3 normal_out = safe_normalize(bump_filter_width * absdet * normal_in -
99 scale * signf(det) * surfgrad);
100 if (is_zero(normal_out)) {
101 normal_out = normal_in;
102 }
103 else {
104 normal_out = normalize(strength * normal_out + (1.0f - strength) * normal_in);
105 }
106
107 if (use_object_space) {
108 object_normal_transform(kg, sd, &normal_out);
109 }
110
111 stack_store_float3(stack, out_offset, normal_out);
112 }
113 else {
114 stack_store_float3(stack, out_offset, zero_float3());
115 }
116#endif
117
118 return offset;
119}
120
121/* Displacement Node */
122
123template<uint node_feature_mask>
125 ccl_private float *stack,
126 const uint fac_offset)
127{
129 {
130 const float3 dP = stack_load_float3(stack, fac_offset);
131 sd->P += dP;
132 }
133}
134
135template<uint node_feature_mask>
137 ccl_private ShaderData *sd,
138 ccl_private float *stack,
139 const uint4 node)
140{
142 {
143 uint height_offset;
144 uint midlevel_offset;
145 uint scale_offset;
146 uint normal_offset;
148 node.y, &height_offset, &midlevel_offset, &scale_offset, &normal_offset);
149
150 const float height = stack_load_float(stack, height_offset);
151 const float midlevel = stack_load_float(stack, midlevel_offset);
152 const float scale = stack_load_float(stack, scale_offset);
153 const float3 normal = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) :
154 sd->N;
155 const uint space = node.w;
156
157 float3 dP = normal;
158
159 if (space == NODE_NORMAL_MAP_OBJECT) {
160 /* Object space. */
162 dP *= (height - midlevel) * scale;
163 object_dir_transform(kg, sd, &dP);
164 }
165 else {
166 /* World space. */
167 dP *= (height - midlevel) * scale;
168 }
169
170 stack_store_float3(stack, node.z, dP);
171 }
172 else {
173 stack_store_float3(stack, node.z, zero_float3());
174 }
175}
176
177template<uint node_feature_mask>
179 ccl_private ShaderData *sd,
180 ccl_private float *stack,
181 const uint4 node,
182 int offset)
183{
184 const uint4 data_node = read_node(kg, &offset);
185 uint vector_offset;
186 uint midlevel_offset;
187 uint scale_offset;
188 uint displacement_offset;
190 node.y, &vector_offset, &midlevel_offset, &scale_offset, &displacement_offset);
191
193 {
194 const uint space = data_node.x;
195
196 const float3 vector = stack_load_float3(stack, vector_offset);
197 const float midlevel = stack_load_float(stack, midlevel_offset);
198 const float scale = stack_load_float(stack, scale_offset);
199 float3 dP = (vector - make_float3(midlevel, midlevel, midlevel)) * scale;
200
201 if (space == NODE_NORMAL_MAP_TANGENT) {
202 /* Tangent space. */
203 float3 normal = sd->N;
204 object_inverse_normal_transform(kg, sd, &normal);
205
206 const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
207 float3 tangent;
208 if (attr.offset != ATTR_STD_NOT_FOUND) {
209 tangent = primitive_surface_attribute<float3>(kg, sd, attr).val;
210 }
211 else {
212 tangent = normalize(sd->dPdu);
213 }
214
215 float3 bitangent = safe_normalize(cross(normal, tangent));
216 const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
217 if (attr_sign.offset != ATTR_STD_NOT_FOUND) {
218 const float sign = primitive_surface_attribute<float>(kg, sd, attr_sign).val;
219 bitangent *= sign;
220 }
221
222 dP = tangent * dP.x + normal * dP.y + bitangent * dP.z;
223 }
224
225 if (space != NODE_NORMAL_MAP_WORLD) {
226 /* Tangent or object space. */
227 object_dir_transform(kg, sd, &dP);
228 }
229
230 stack_store_float3(stack, displacement_offset, dP);
231 }
232 else {
233 stack_store_float3(stack, displacement_offset, zero_float3());
234 (void)data_node;
235 }
236
237 return offset;
238}
239
MINLINE float signf(float f)
unsigned int uint
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 uint4 read_node(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_uchar2(const uint i, ccl_private uint *x, ccl_private uint *y)
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_device_inline bool stack_valid(const uint a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 stack_load_float3(const ccl_private float *stack, const uint a)
#define IF_KERNEL_NODES_FEATURE(feature)
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define SVM_STACK_INVALID
#define ccl_device_noinline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __uint_as_float(x)
ccl_device_forceinline differential3 differential_from_compact(const float3 D, const float dD)
ccl_device void svm_node_set_displacement(ccl_private ShaderData *sd, ccl_private float *stack, const uint fac_offset)
Definition displace.h:124
ccl_device_noinline int svm_node_vector_displacement(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node, int offset)
Definition displace.h:178
CCL_NAMESPACE_BEGIN ccl_device_noinline int svm_node_set_bump(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node, int offset)
Definition displace.h:19
ccl_device_noinline void svm_node_displacement(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const uint4 node)
Definition displace.h:136
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_NAMESPACE_BEGIN ccl_device float invert(const float color, const float factor)
Definition invert.h:11
ccl_device_inline void object_dir_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *D)
ccl_device_inline void object_normal_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *N)
ccl_device_inline void object_inverse_dir_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *D)
ccl_device_inline void object_inverse_normal_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *N)
@ NODE_NORMAL_MAP_TANGENT
@ NODE_NORMAL_MAP_WORLD
@ NODE_NORMAL_MAP_OBJECT
@ ATTR_STD_NOT_FOUND
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
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 fabsf
#define ccl_device
static bool find_attribute(const std::string &attributes, const char *search_attribute)
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
uint x
Definition types_uint4.h:13
uint y
Definition types_uint4.h:13
uint z
Definition types_uint4.h:13
uint w
Definition types_uint4.h:13
max
Definition text_draw.cc:251