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