Blender V4.5
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 ShaderData *sd,
126 ccl_private float *stack,
127 const uint fac_offset)
128{
130 {
131 const float3 dP = stack_load_float3(stack, fac_offset);
132 sd->P += dP;
133 }
134}
135
136template<uint node_feature_mask>
138 ccl_private ShaderData *sd,
139 ccl_private float *stack,
140 const uint4 node)
141{
143 {
144 uint height_offset;
145 uint midlevel_offset;
146 uint scale_offset;
147 uint normal_offset;
149 node.y, &height_offset, &midlevel_offset, &scale_offset, &normal_offset);
150
151 const float height = stack_load_float(stack, height_offset);
152 const float midlevel = stack_load_float(stack, midlevel_offset);
153 const float scale = stack_load_float(stack, scale_offset);
154 const float3 normal = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) :
155 sd->N;
156 const uint space = node.w;
157
158 float3 dP = normal;
159
160 if (space == NODE_NORMAL_MAP_OBJECT) {
161 /* Object space. */
163 dP *= (height - midlevel) * scale;
164 object_dir_transform(kg, sd, &dP);
165 }
166 else {
167 /* World space. */
168 dP *= (height - midlevel) * scale;
169 }
170
171 stack_store_float3(stack, node.z, dP);
172 }
173 else {
174 stack_store_float3(stack, node.z, zero_float3());
175 }
176}
177
178template<uint node_feature_mask>
180 ccl_private ShaderData *sd,
181 ccl_private float *stack,
182 const uint4 node,
183 int offset)
184{
185 const uint4 data_node = read_node(kg, &offset);
186 uint vector_offset;
187 uint midlevel_offset;
188 uint scale_offset;
189 uint displacement_offset;
191 node.y, &vector_offset, &midlevel_offset, &scale_offset, &displacement_offset);
192
194 {
195 const uint space = data_node.x;
196
197 const float3 vector = stack_load_float3(stack, vector_offset);
198 const float midlevel = stack_load_float(stack, midlevel_offset);
199 const float scale = stack_load_float(stack, scale_offset);
200 float3 dP = (vector - make_float3(midlevel, midlevel, midlevel)) * scale;
201
202 if (space == NODE_NORMAL_MAP_TANGENT) {
203 /* Tangent space. */
204 float3 normal = sd->N;
205 object_inverse_normal_transform(kg, sd, &normal);
206
207 const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
208 float3 tangent;
209 if (attr.offset != ATTR_STD_NOT_FOUND) {
210 tangent = primitive_surface_attribute<float3>(kg, sd, attr, nullptr, nullptr);
211 }
212 else {
213 tangent = normalize(sd->dPdu);
214 }
215
216 float3 bitangent = safe_normalize(cross(normal, tangent));
217 const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
218 if (attr_sign.offset != ATTR_STD_NOT_FOUND) {
219 const float sign = primitive_surface_attribute<float>(kg, sd, attr_sign, nullptr, nullptr);
220 bitangent *= sign;
221 }
222
223 dP = tangent * dP.x + normal * dP.y + bitangent * dP.z;
224 }
225
226 if (space != NODE_NORMAL_MAP_WORLD) {
227 /* Tangent or object space. */
228 object_dir_transform(kg, sd, &dP);
229 }
230
231 stack_store_float3(stack, displacement_offset, dP);
232 }
233 else {
234 stack_store_float3(stack, displacement_offset, zero_float3());
235 (void)data_node;
236 }
237
238 return offset;
239}
240
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_device
#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 fabsf(x)
#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(KernelGlobals kg, 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:179
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:137
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:15
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)
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
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