Blender V4.3
mesh_displace.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "device/device.h"
6
8
9#include "scene/mesh.h"
10#include "scene/object.h"
11#include "scene/scene.h"
12#include "scene/shader.h"
13
14#include "util/foreach.h"
15#include "util/map.h"
16#include "util/progress.h"
17#include "util/set.h"
18
20
22{
23 float3 v0 = verts[t.v[0]];
24 float3 v1 = verts[t.v[1]];
25 float3 v2 = verts[t.v[2]];
26
27 float3 norm = cross(v1 - v0, v2 - v0);
28 float normlen = len(norm);
29
30 if (normlen == 0.0f) {
31 return make_float3(1.0f, 0.0f, 0.0f);
32 }
33
34 return norm / normlen;
35}
36
37/* Fill in coordinates for mesh displacement shader evaluation on device. */
38static int fill_shader_input(const Scene *scene,
39 const Mesh *mesh,
40 const size_t object_index,
42{
43 int d_input_size = 0;
44 KernelShaderEvalInput *d_input_data = d_input.data();
45
46 const array<int> &mesh_shaders = mesh->get_shader();
47 const array<Node *> &mesh_used_shaders = mesh->get_used_shaders();
48 const array<float3> &mesh_verts = mesh->get_verts();
49
50 const int num_verts = mesh_verts.size();
51 vector<bool> done(num_verts, false);
52
53 int num_triangles = mesh->num_triangles();
54 for (int i = 0; i < num_triangles; i++) {
55 Mesh::Triangle t = mesh->get_triangle(i);
56 int shader_index = mesh_shaders[i];
57 Shader *shader = (shader_index < mesh_used_shaders.size()) ?
58 static_cast<Shader *>(mesh_used_shaders[shader_index]) :
59 scene->default_surface;
60
61 if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) {
62 continue;
63 }
64
65 for (int j = 0; j < 3; j++) {
66 if (done[t.v[j]]) {
67 continue;
68 }
69
70 done[t.v[j]] = true;
71
72 /* set up object, primitive and barycentric coordinates */
73 int object = object_index;
74 int prim = mesh->prim_offset + i;
75 float u, v;
76
77 switch (j) {
78 case 0:
79 u = 0.0f;
80 v = 0.0f;
81 break;
82 case 1:
83 u = 1.0f;
84 v = 0.0f;
85 break;
86 default:
87 u = 0.0f;
88 v = 1.0f;
89 break;
90 }
91
92 /* back */
94 in.object = object;
95 in.prim = prim;
96 in.u = u;
97 in.v = v;
98 d_input_data[d_input_size++] = in;
99 }
100 }
101
102 return d_input_size;
103}
104
105/* Read back mesh displacement shader output. */
106static void read_shader_output(const Scene *scene,
107 Mesh *mesh,
108 const device_vector<float> &d_output)
109{
110 const array<int> &mesh_shaders = mesh->get_shader();
111 const array<Node *> &mesh_used_shaders = mesh->get_used_shaders();
112 array<float3> &mesh_verts = mesh->get_verts();
113
114 const int num_verts = mesh_verts.size();
115 const int num_motion_steps = mesh->get_motion_steps();
116 vector<bool> done(num_verts, false);
117
118 const float *d_output_data = d_output.data();
119 int d_output_index = 0;
120
121 Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
122 int num_triangles = mesh->num_triangles();
123 for (int i = 0; i < num_triangles; i++) {
124 Mesh::Triangle t = mesh->get_triangle(i);
125 int shader_index = mesh_shaders[i];
126 Shader *shader = (shader_index < mesh_used_shaders.size()) ?
127 static_cast<Shader *>(mesh_used_shaders[shader_index]) :
128 scene->default_surface;
129
130 if (!shader->has_displacement || shader->get_displacement_method() == DISPLACE_BUMP) {
131 continue;
132 }
133
134 for (int j = 0; j < 3; j++) {
135 if (!done[t.v[j]]) {
136 done[t.v[j]] = true;
137 float3 off = make_float3(d_output_data[d_output_index + 0],
138 d_output_data[d_output_index + 1],
139 d_output_data[d_output_index + 2]);
140 d_output_index += 3;
141
142 /* Avoid illegal vertex coordinates. */
143 off = ensure_finite(off);
144 mesh_verts[t.v[j]] += off;
145 if (attr_mP != NULL) {
146 for (int step = 0; step < num_motion_steps - 1; step++) {
147 float3 *mP = attr_mP->data_float3() + step * num_verts;
148 mP[t.v[j]] += off;
149 }
150 }
151 }
152 }
153 }
154}
155
156bool GeometryManager::displace(Device *device, Scene *scene, Mesh *mesh, Progress &progress)
157{
158 /* verify if we have a displacement shader */
159 if (!mesh->has_true_displacement()) {
160 return false;
161 }
162
163 const size_t num_verts = mesh->verts.size();
164 const size_t num_triangles = mesh->num_triangles();
165
166 if (num_triangles == 0) {
167 return false;
168 }
169
170 string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
171 progress.set_status("Updating Mesh", msg);
172
173 /* find object index. todo: is arbitrary */
174 size_t object_index = OBJECT_NONE;
175
176 for (size_t i = 0; i < scene->objects.size(); i++) {
177 if (scene->objects[i]->get_geometry() == mesh) {
178 object_index = i;
179 break;
180 }
181 }
182
183 /* Evaluate shader on device. */
184 ShaderEval shader_eval(device, progress);
185 if (!shader_eval.eval(SHADER_EVAL_DISPLACE,
186 num_verts,
187 3,
188 function_bind(&fill_shader_input, scene, mesh, object_index, _1),
189 function_bind(&read_shader_output, scene, mesh, _1)))
190 {
191 return false;
192 }
193
194 /* stitch */
195 unordered_set<int> stitch_keys;
196 for (pair<int, int> i : mesh->vert_to_stitching_key_map) {
197 stitch_keys.insert(i.second); /* stitching index */
198 }
199
200 typedef unordered_multimap<int, int>::iterator map_it_t;
201
202 for (int key : stitch_keys) {
203 pair<map_it_t, map_it_t> verts = mesh->vert_stitching_map.equal_range(key);
204
206 int num = 0;
207
208 for (map_it_t v = verts.first; v != verts.second; ++v) {
209 int vert = v->second;
210
211 pos += mesh->verts[vert];
212 num++;
213 }
214
215 if (num <= 1) {
216 continue;
217 }
218
219 pos *= 1.0f / num;
220
221 for (map_it_t v = verts.first; v != verts.second; ++v) {
222 mesh->verts[v->second] = pos;
223 }
224 }
225
226 /* for displacement method both, we only need to recompute the face
227 * normals, as bump mapping in the shader will already alter the
228 * vertex normal, so we start from the non-displaced vertex normals
229 * to avoid applying the perturbation twice. */
230 mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
231 mesh->add_face_normals();
232
233 bool need_recompute_vertex_normals = false;
234
235 foreach (Node *node, mesh->get_used_shaders()) {
236 Shader *shader = static_cast<Shader *>(node);
237 if (shader->has_displacement && shader->get_displacement_method() == DISPLACE_TRUE) {
238 need_recompute_vertex_normals = true;
239 break;
240 }
241 }
242
243 if (need_recompute_vertex_normals) {
244 bool flip = mesh->transform_negative_scaled;
245 vector<bool> tri_has_true_disp(num_triangles, false);
246
247 for (size_t i = 0; i < num_triangles; i++) {
248 int shader_index = mesh->shader[i];
249 Shader *shader = (shader_index < mesh->used_shaders.size()) ?
250 static_cast<Shader *>(mesh->used_shaders[shader_index]) :
251 scene->default_surface;
252
253 tri_has_true_disp[i] = shader->has_displacement &&
254 shader->get_displacement_method() == DISPLACE_TRUE;
255 }
256
257 /* static vertex normals */
258
259 /* get attributes */
260 Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
261 Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
262
263 float3 *fN = attr_fN->data_float3();
264 float3 *vN = attr_vN->data_float3();
265
266 /* compute vertex normals */
267
268 /* zero vertex normals on triangles with true displacement */
269 for (size_t i = 0; i < num_triangles; i++) {
270 if (tri_has_true_disp[i]) {
271 for (size_t j = 0; j < 3; j++) {
272 vN[mesh->get_triangle(i).v[j]] = zero_float3();
273 }
274 }
275 }
276
277 /* add face normals to vertex normals */
278 for (size_t i = 0; i < num_triangles; i++) {
279 if (tri_has_true_disp[i]) {
280 for (size_t j = 0; j < 3; j++) {
281 int vert = mesh->get_triangle(i).v[j];
282 vN[vert] += fN[i];
283
284 /* add face normals to stitched vertices */
285 if (stitch_keys.size()) {
286 map_it_t key = mesh->vert_to_stitching_key_map.find(vert);
287
288 if (key != mesh->vert_to_stitching_key_map.end()) {
289 pair<map_it_t, map_it_t> verts = mesh->vert_stitching_map.equal_range(key->second);
290
291 for (map_it_t v = verts.first; v != verts.second; ++v) {
292 if (v->second == vert) {
293 continue;
294 }
295
296 vN[v->second] += fN[i];
297 }
298 }
299 }
300 }
301 }
302 }
303
304 /* normalize vertex normals */
305 vector<bool> done(num_verts, false);
306
307 for (size_t i = 0; i < num_triangles; i++) {
308 if (tri_has_true_disp[i]) {
309 for (size_t j = 0; j < 3; j++) {
310 int vert = mesh->get_triangle(i).v[j];
311
312 if (done[vert]) {
313 continue;
314 }
315
316 vN[vert] = normalize(vN[vert]);
317 if (flip) {
318 vN[vert] = -vN[vert];
319 }
320
321 done[vert] = true;
322 }
323 }
324 }
325
326 /* motion vertex normals */
327 Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
328 Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
329
330 if (mesh->has_motion_blur() && attr_mP && attr_mN) {
331 for (int step = 0; step < mesh->motion_steps - 1; step++) {
332 float3 *mP = attr_mP->data_float3() + step * mesh->verts.size();
333 float3 *mN = attr_mN->data_float3() + step * mesh->verts.size();
334
335 /* compute */
336
337 /* zero vertex normals on triangles with true displacement */
338 for (size_t i = 0; i < num_triangles; i++) {
339 if (tri_has_true_disp[i]) {
340 for (size_t j = 0; j < 3; j++) {
341 mN[mesh->get_triangle(i).v[j]] = zero_float3();
342 }
343 }
344 }
345
346 /* add face normals to vertex normals */
347 for (size_t i = 0; i < num_triangles; i++) {
348 if (tri_has_true_disp[i]) {
349 for (size_t j = 0; j < 3; j++) {
350 int vert = mesh->get_triangle(i).v[j];
351 float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
352 mN[vert] += fN;
353
354 /* add face normals to stitched vertices */
355 if (stitch_keys.size()) {
356 map_it_t key = mesh->vert_to_stitching_key_map.find(vert);
357
358 if (key != mesh->vert_to_stitching_key_map.end()) {
359 pair<map_it_t, map_it_t> verts = mesh->vert_stitching_map.equal_range(
360 key->second);
361
362 for (map_it_t v = verts.first; v != verts.second; ++v) {
363 if (v->second == vert) {
364 continue;
365 }
366
367 mN[v->second] += fN;
368 }
369 }
370 }
371 }
372 }
373 }
374
375 /* normalize vertex normals */
376 vector<bool> done(num_verts, false);
377
378 for (size_t i = 0; i < num_triangles; i++) {
379 if (tri_has_true_disp[i]) {
380 for (size_t j = 0; j < 3; j++) {
381 int vert = mesh->get_triangle(i).v[j];
382
383 if (done[vert]) {
384 continue;
385 }
386
387 mN[vert] = normalize(mN[vert]);
388 if (flip) {
389 mN[vert] = -mN[vert];
390 }
391
392 done[vert] = true;
393 }
394 }
395 }
396 }
397 }
398 }
399
400 return true;
401}
402
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
float3 * data_float3()
bool displace(Device *device, Scene *scene, Mesh *mesh, Progress &progress)
void set_status(const string &status_, const string &substatus_="")
Definition progress.h:263
bool eval(const ShaderEvalType type, const int max_num_inputs, const int num_channels, const function< int(device_vector< KernelShaderEvalInput > &)> &fill_input, const function< void(device_vector< float > &)> &read_output)
size_t size() const
OperationNode * node
#define function_bind
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define NULL
int len
static float verts[][3]
static void read_shader_output(float *shadow_transparency, bool &is_fully_opaque, const device_vector< float > &d_output)
Definition hair.cpp:583
static int fill_shader_input(const Hair *hair, const size_t object_index, device_vector< KernelShaderEvalInput > &d_input)
Definition hair.cpp:557
@ ATTR_STD_MOTION_VERTEX_NORMAL
@ ATTR_STD_VERTEX_NORMAL
@ ATTR_STD_MOTION_VERTEX_POSITION
@ ATTR_STD_FACE_NORMAL
#define OBJECT_NONE
ccl_device_inline float cross(const float2 a, const float2 b)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:15
static void read_shader_output(const Scene *scene, Mesh *mesh, const device_vector< float > &d_output)
static CCL_NAMESPACE_BEGIN float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
static int fill_shader_input(const Scene *scene, const Mesh *mesh, const size_t object_index, device_vector< KernelShaderEvalInput > &d_input)
@ DISPLACE_BUMP
@ DISPLACE_TRUE
@ SHADER_EVAL_DISPLACE
Definition shader_eval.h:19
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
ccl_device_inline float ensure_finite(float v)
Definition util/math.h:373