Blender V5.0
multires_bake.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012-2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
67
68#include "RE_multires_bake.h"
69
70#include <atomic>
71
72#include "DNA_mesh_types.h"
73#include "DNA_modifier_types.h"
74
75#include "BLI_array.hh"
76#include "BLI_listbase.h"
77#include "BLI_math_base.hh"
78#include "BLI_math_geom.h"
79#include "BLI_math_matrix.hh"
80#include "BLI_math_vector.hh"
81#include "BLI_span.hh"
82#include "BLI_task.hh"
83#include "BLI_threads.h"
84
85#include "BKE_attribute.hh"
86#include "BKE_customdata.hh"
87#include "BKE_global.hh"
88#include "BKE_image.hh"
89#include "BKE_lib_id.hh"
90#include "BKE_mesh.hh"
91#include "BKE_mesh_tangent.hh"
92#include "BKE_multires.hh"
93#include "BKE_subdiv.hh"
94#include "BKE_subdiv_ccg.hh"
95#include "BKE_subdiv_eval.hh"
96#include "BKE_subdiv_foreach.hh"
97#include "BKE_subdiv_mesh.hh"
98
99#include "IMB_imbuf.hh"
100#include "IMB_imbuf_types.hh"
101
102#include "DEG_depsgraph.hh"
103
104#include "RE_texture_margin.h"
105
106namespace blender::render {
107namespace {
108
109namespace subdiv = bke::subdiv;
110
111/* -------------------------------------------------------------------- */
115
116template<class T> T interp_barycentric_triangle(const T data[3], const float2 &uv)
117{
118 return data[0] * uv.x + data[1] * uv.y + data[2] * (1.0f - uv.x - uv.y);
119}
120
121template<class T>
122T interp_bilinear_quad(
123 const float u, const float v, const T &p0, const T &p1, const T &p2, const T &p3)
124{
125 const float w0 = (1 - u) * (1 - v);
126 const float w1 = u * (1 - v);
127 const float w2 = u * v;
128 const float w3 = (1 - u) * v;
129
130 return p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3;
131}
132
133float2 resolve_tri_uv(const float2 &st, const float2 &st0, const float2 &st1, const float2 &st2)
134{
135 float2 uv;
136 resolve_tri_uv_v2(uv, st, st0, st1, st2);
137 return uv;
138}
139
141
142/* -------------------------------------------------------------------- */
145
146template<class T> class Grid {
147 Span<T> data_;
148 int side_size_;
149
150 T get_element(const int x, const int y) const
151 {
152 const int64_t index = int64_t(y) * side_size_ + x;
153 return data_[index];
154 }
155
156 public:
157 Grid(const Span<T> data, const int side_size) : data_(data), side_size_(side_size)
158 {
159 BLI_assert(data.size() == side_size_ * side_size_);
160 }
161
162 T sample(const float2 uv) const
163 {
164 const float2 xy = uv * (side_size_ - 1);
165
166 const int x0 = int(xy.x);
167 const int x1 = x0 >= (side_size_ - 1) ? (side_size_ - 1) : (x0 + 1);
168
169 const int y0 = int(xy.y);
170 const int y1 = y0 >= (side_size_ - 1) ? (side_size_ - 1) : (y0 + 1);
171
172 const float u = xy.x - x0;
173 const float v = xy.y - y0;
174
175 return interp_bilinear_quad(
176 u, v, get_element(x0, y0), get_element(x1, y0), get_element(x1, y1), get_element(x0, y1));
177 }
178};
179
180template<class T>
181Grid<T> get_subdiv_ccg_grid(const SubdivCCG &subdiv_ccg, const int grid_index, const Span<T> data)
182{
183 const int64_t offset = int64_t(grid_index) * subdiv_ccg.grid_area;
184 return Grid(Span(data.data() + offset, subdiv_ccg.grid_area), subdiv_ccg.grid_size);
185}
186
187float3 sample_position_on_subdiv_ccg(const SubdivCCG &subdiv_ccg,
188 const int grid_index,
189 const float2 grid_uv)
190{
191 const Grid<float3> grid = get_subdiv_ccg_grid(
192 subdiv_ccg, grid_index, subdiv_ccg.positions.as_span());
193 return grid.sample(grid_uv);
194}
195
196float3 sample_normal_on_subdiv_ccg(const SubdivCCG &subdiv_ccg,
197 const int grid_index,
198 const float2 grid_uv)
199{
200 /* TODO(sergey): Support flat normals.
201 * It seems that the baker always used smooth interpolation for CCG. */
202 const Grid<float3> grid = get_subdiv_ccg_grid(
203 subdiv_ccg, grid_index, subdiv_ccg.normals.as_span());
204 return grid.sample(grid_uv);
205}
206
208
209/* -------------------------------------------------------------------- */
212
213struct MeshArrays {
214 Span<float3> vert_positions;
215 Span<float3> vert_normals;
216
217 Span<int> corner_verts;
218 Span<int3> corner_tris;
219 Span<float3> corner_normals;
220
221 Span<int> tri_faces;
222
223 OffsetIndices<int> faces;
224 Span<float3> face_normals;
225 VArraySpan<bool> sharp_faces;
226
227 VArraySpan<float2> uv_map;
228
229 VArraySpan<int> material_indices;
230
231 MeshArrays() = default;
232
233 explicit MeshArrays(const Mesh &mesh)
234 {
235 bke::AttributeAccessor attributes = mesh.attributes();
236
237 const StringRef active_uv_map = CustomData_get_active_layer_name(&mesh.corner_data,
239 vert_positions = mesh.vert_positions();
240 vert_normals = mesh.vert_normals();
241
242 corner_verts = mesh.corner_verts();
243 corner_tris = mesh.corner_tris();
244 corner_normals = mesh.corner_normals();
245
246 tri_faces = mesh.corner_tri_faces();
247
248 faces = mesh.faces();
249 face_normals = mesh.face_normals();
250 sharp_faces = *attributes.lookup_or_default<bool>("sharp_face", bke::AttrDomain::Face, false);
251
252 uv_map = *attributes.lookup<float2>(active_uv_map, bke::AttrDomain::Corner);
253
254 material_indices = *attributes.lookup_or_default<int>(
255 "material_index", bke::AttrDomain::Face, 0);
256 }
257};
258
259/* Calculate UV map coordinates at the center of the face (grid coordinates (0, 0)). */
260static float2 face_center_tex_uv_calc(const MeshArrays &mesh_arrays, const int face_index)
261{
262 const IndexRange &face = mesh_arrays.faces[face_index];
263 float2 tex_uv_acc(0.0f, 0.0f);
264 for (const int corner : face) {
265 tex_uv_acc += mesh_arrays.uv_map[corner];
266 }
267 return tex_uv_acc / face.size();
268}
269
270/* Calculate smooth normal coordinates at the center of the face (grid coordinates (0, 0)).
271 * NOTE: The returned value is not normalized to allow linear interpolation with other grid
272 * elements. */
273static float3 face_center_smooth_normal_calc(const MeshArrays &mesh_arrays, const int face_index)
274{
275 const IndexRange &face = mesh_arrays.faces[face_index];
276 float3 normal_acc(0.0f, 0.0f, 0.0f);
277 for (const int corner : face) {
278 normal_acc += mesh_arrays.vert_normals[mesh_arrays.corner_verts[corner]];
279 }
280 /* NOTE: No normalization here: do it after interpolation at the baking point.
281 *
282 * This preserves linearity of operation. If normalization is done here interpolation will go
283 * wrong. */
284 return normal_acc / face.size();
285}
286
287/* Calculate tangent space for the given mesh state. */
288Array<float4> calc_uv_tangents(const MeshArrays &mesh_arrays)
289{
290 Array<Array<float4>> tangent_data = bke::mesh::calc_uv_tangents(mesh_arrays.vert_positions,
291 mesh_arrays.faces,
292 mesh_arrays.corner_verts,
293 mesh_arrays.corner_tris,
294 mesh_arrays.tri_faces,
295 mesh_arrays.sharp_faces,
296 mesh_arrays.vert_normals,
297 mesh_arrays.face_normals,
298 mesh_arrays.corner_normals,
299 {mesh_arrays.uv_map});
300
301 return tangent_data[0];
302}
303
304/* Calculate tangent space at the center of the face (grid coordinates (0, 0)). */
305static float4 face_center_uv_tangent_calc(const MeshArrays &mesh_arrays,
306 const Span<float4> uv_tangents,
307 const int face_index)
308{
309 const IndexRange &face = mesh_arrays.faces[face_index];
310 float4 tex_uv_acc(0.0f, 0.0f, 0.0f, 0.0f);
311 for (const int corner : face) {
312 tex_uv_acc += uv_tangents[corner];
313 }
314 return tex_uv_acc / face.size();
315}
316
318
319/* -------------------------------------------------------------------- */
322
323struct ExtraBuffers {
324 Array<float> displacement_buffer;
325 Array<char> mask_buffer;
326};
327
328struct RasterizeTile {
329 ImBuf *ibuf = nullptr; /* Image buffer of the tile. */
330 ExtraBuffers *extra_buffers = nullptr;
331 float2 uv_offset; /* UV coordinate of the tile origin. */
332};
333
334struct RasterizeTriangle {
335 /* UV coordinates with the CCG. All vertices belong to the same grid. */
336 int grid_index;
337 float2 grid_uvs[3];
338
339 /* UV texture coordinates of the triangle vertices within the tile. */
340 float2 tex_uvs[3];
341
342 /* Positions and normals of the vertices, at the bake level. */
343 float3 positions[3];
344 float3 normals[3];
345
346 /* Triangle is shaded flat: it has the same normal at every point of its surface.
347 * Face normal is stored in all elements of the normals array. */
348 bool is_flat;
349
350 /* Optional tangents.
351 * The uv_tangents might be uninitialized if has_uv_tangents=false. */
352 bool has_uv_tangents;
353 float4 uv_tangents[3];
354
355 float3 get_position(const float2 &uv) const
356 {
357 return interp_barycentric_triangle(positions, uv);
358 }
359
360 float3 get_normal(const float2 &uv) const
361 {
362 if (is_flat) {
363 return normals[0];
364 }
365 return math::normalize(interp_barycentric_triangle(normals, uv));
366 }
367};
368
369struct RasterizeQuad {
370 /* UV coordinates with the CCG. All vertices belong to the same grid. */
371 int grid_index;
372 float2 grid_uvs[4];
373
374 /* UV texture coordinates of the triangle vertices within the tile. */
375 float2 tex_uvs[4];
376
377 /* Positions and normals of the vertices, at the bake level. */
378 float3 positions[4];
379 float3 normals[4];
380
381 /* Quad is shaded flat: it has the same normal at every point of its surface.
382 * Face normal is stored in all elements of the normals array. */
383 bool is_flat;
384
385 /* Optional tangents.
386 * The uv_tangents might be uninitialized if has_uv_tangents=false. */
387 bool has_uv_tangents;
388 float4 uv_tangents[4];
389};
390
391struct RasterizeResult {
392 float height_min = FLT_MAX;
393 float height_max = -FLT_MAX;
394};
395
396struct BakedImBuf {
397 Image *image;
398 ImBuf *ibuf;
399 ExtraBuffers extra_buffers;
400 float2 uv_offset;
401};
402
403struct MultiresBakeResult {
404 Vector<BakedImBuf> baked_ibufs;
405
406 /* Bake-level mesh subdivided to the final multi-resolution level.
407 * It is created by displacement baker that used "Use Low Resolution Mesh" OFF.
408 *
409 * This mesh is to be used to filter baked images. */
410 const Mesh *highres_bake_mesh = nullptr;
411
412 /* Minimum and maximum height during displacement baking. */
413 float height_min = FLT_MAX;
414 float height_max = -FLT_MAX;
415};
416
417class MultiresBaker {
418 public:
419 virtual ~MultiresBaker() = default;
420
421 virtual float3 bake_pixel(const RasterizeTriangle &triangle,
422 const float2 &bary_uv,
423 const float2 &grid_uv,
424 RasterizeResult &result) const = 0;
425
426 virtual void write_pixel(const RasterizeTile &tile,
427 const int2 &coord,
428 const float3 &value) const = 0;
429
430 protected:
431 void write_pixel_to_image_buffer(ImBuf &ibuf, const int2 &coord, const float3 &value) const
432 {
433 const int64_t pixel = int64_t(ibuf.x) * coord.y + coord.x;
434
435 if (ibuf.float_buffer.data) {
436 /* TODO(sergey): Properly tackle ibuf.channels. */
437 BLI_assert(ibuf.channels == 4);
438 float *rrgbf = ibuf.float_buffer.data + pixel * 4;
439 rrgbf[0] = value[0];
440 rrgbf[1] = value[1];
441 rrgbf[2] = value[2];
442 rrgbf[3] = 1.0f;
444 }
445
446 if (ibuf.byte_buffer.data) {
447 uchar *rrgb = ibuf.byte_buffer.data + pixel * 4;
448 unit_float_to_uchar_clamp_v3(rrgb, value);
449 rrgb[3] = 255;
450 }
451
453 }
454};
455
456static bool multiresbake_test_break(const MultiresBakeRender &bake)
457{
458 if (!bake.stop) {
459 /* This means baker is executed outside from job system (for example, from Python API).
460 * In this case there is no need to cancel, as it will be quite strange to cancel out
461 * execution of a script. */
462 return false;
463 }
464 return *bake.stop || G.is_break;
465}
466
467static float2 get_tile_uv(Image &image, ImageTile &tile)
468{
469 float uv_offset[2];
470 BKE_image_get_tile_uv(&image, tile.tile_number, uv_offset);
471 return uv_offset;
472}
473
474static bool need_tangent(const MultiresBakeRender &bake)
475{
476 return (bake.type == R_BAKE_NORMALS) || (bake.type == R_BAKE_VECTOR_DISPLACEMENT &&
478}
479
480/* Get matrix which converts tangent space to object space in the (tangent, bitangent, normal)
481 * convention. */
482static float3x3 get_from_tangent_matrix_tbn(const RasterizeTriangle &triangle,
483 const float2 &bary_uv)
484{
485 if (!triangle.has_uv_tangents) {
486 return float3x3::identity();
487 }
488
489 const float u = bary_uv.x;
490 const float v = bary_uv.y;
491 const float w = 1 - u - v;
492
493 const float3 &no0 = triangle.normals[0];
494 const float3 &no1 = triangle.normals[1];
495 const float3 &no2 = triangle.normals[2];
496
497 const float4 &tang0 = triangle.uv_tangents[0];
498 const float4 &tang1 = triangle.uv_tangents[1];
499 const float4 &tang2 = triangle.uv_tangents[2];
500
501 /* The sign is the same at all face vertices for any non-degenerate face.
502 * Just in case we clamp the interpolated value though. */
503 const float sign = (tang0.w * u + tang1.w * v + tang2.w * w) < 0 ? (-1.0f) : 1.0f;
504
505 /* x - tangent
506 * y - bitangent (B = sign * cross(N, T))
507 * z - normal */
508 float3x3 from_tangent;
509 from_tangent.x = tang0.xyz() * u + tang1.xyz() * v + tang2.xyz() * w;
510 from_tangent.z = no0.xyz() * u + no1.xyz() * v + no2.xyz() * w;
511 from_tangent.y = sign * math::cross(from_tangent.z, from_tangent.x);
512
513 return from_tangent;
514}
515
516/* Get matrix which converts object space to tangent space in the (tangent, bitangent, normal)
517 * convention. */
518static float3x3 get_to_tangent_matrix_tbn(const RasterizeTriangle &triangle, const float2 &bary_uv)
519{
520 const float3x3 from_tangent = get_from_tangent_matrix_tbn(triangle, bary_uv);
521 return math::invert(from_tangent);
522}
523
524/* Get matrix which converts object space to tangent space in the (tangent, normal, bitangent)
525 * convention. */
526static float3x3 get_to_tangent_matrix_tnb(const RasterizeTriangle &triangle, const float2 &bary_uv)
527{
528 float3x3 from_tangent = get_from_tangent_matrix_tbn(triangle, bary_uv);
529 std::swap(from_tangent.y, from_tangent.z);
530 return math::invert(from_tangent);
531}
532
534
535/* -------------------------------------------------------------------- */
538
539static void flush_pixel(const MultiresBaker &baker,
540 const RasterizeTile &tile,
541 const RasterizeTriangle &triangle,
542 const int x,
543 const int y,
544 RasterizeResult &result)
545{
546 const float2 st{(x + 0.5f) / tile.ibuf->x, (y + 0.5f) / tile.ibuf->y};
547
548 const float2 bary_uv = resolve_tri_uv(
549 st, triangle.tex_uvs[0], triangle.tex_uvs[1], triangle.tex_uvs[2]);
550 const float2 grid_uv = interp_barycentric_triangle(triangle.grid_uvs, bary_uv);
551
552 const float3 baked_pixel = baker.bake_pixel(triangle, bary_uv, grid_uv, result);
553 baker.write_pixel(tile, int2(x, y), baked_pixel);
554}
555
556static void set_rast_triangle(const MultiresBaker &baker,
557 const RasterizeTile &tile,
558 const RasterizeTriangle &triangle,
559 const int x,
560 const int y,
561 RasterizeResult &result)
562{
563 const int w = tile.ibuf->x;
564 const int h = tile.ibuf->y;
565
566 if (x >= 0 && x < w && y >= 0 && y < h) {
567 const int64_t pixel = int64_t(y) * w + x;
568 if (tile.extra_buffers->mask_buffer[pixel] == FILTER_MASK_NULL) {
569 tile.extra_buffers->mask_buffer[pixel] = FILTER_MASK_USED;
570 flush_pixel(baker, tile, triangle, x, y, result);
571 }
572 }
573}
574
575static void rasterize_half(const MultiresBaker &baker,
576 const RasterizeTile &tile,
577 const RasterizeTriangle &triangle,
578 const float2 &s0,
579 const float2 &s1,
580 const float2 &l0,
581 const float2 &l1,
582 const int y0_in,
583 const int y1_in,
584 const bool is_mid_right,
585 RasterizeResult &result)
586{
587 const bool s_stable = fabsf(s1.y - s0.y) > FLT_EPSILON;
588 const bool l_stable = fabsf(l1.y - l0.y) > FLT_EPSILON;
589 const int w = tile.ibuf->x;
590 const int h = tile.ibuf->y;
591
592 if (y1_in <= 0 || y0_in >= h) {
593 return;
594 }
595
596 const int y0 = y0_in < 0 ? 0 : y0_in;
597 const int y1 = y1_in >= h ? h : y1_in;
598
599 for (int y = y0; y < y1; y++) {
600 /*-b(x-x0) + a(y-y0) = 0 */
601 float x_l = s_stable ? (s0.x + (((s1.x - s0.x) * (y - s0.y)) / (s1.y - s0.y))) : s0.x;
602 float x_r = l_stable ? (l0.x + (((l1.x - l0.x) * (y - l0.y)) / (l1.y - l0.y))) : l0.x;
603 if (is_mid_right) {
604 std::swap(x_l, x_r);
605 }
606
607 int iXl = int(ceilf(x_l));
608 int iXr = int(ceilf(x_r));
609
610 if (iXr > 0 && iXl < w) {
611 iXl = iXl < 0 ? 0 : iXl;
612 iXr = iXr >= w ? w : iXr;
613
614 for (int x = iXl; x < iXr; x++) {
615 set_rast_triangle(baker, tile, triangle, x, y, result);
616 }
617 }
618 }
619}
620
621static void rasterize_triangle(const MultiresBaker &baker,
622 const RasterizeTile &tile,
623 const RasterizeTriangle &triangle,
624 RasterizeResult &result)
625{
626 const float2 ibuf_size(tile.ibuf->x, tile.ibuf->y);
627
628 const float2 &st0_in = triangle.tex_uvs[0];
629 const float2 &st1_in = triangle.tex_uvs[1];
630 const float2 &st2_in = triangle.tex_uvs[2];
631
632 float2 p_low = st0_in * ibuf_size - 0.5f;
633 float2 p_mid = st1_in * ibuf_size - 0.5f;
634 float2 p_high = st2_in * ibuf_size - 0.5f;
635
636 /* Skip degenerates. */
637 if ((p_low.x == p_mid.x && p_low.y == p_mid.y) || (p_low.x == p_mid.x && p_low.y == p_high.y) ||
638 (p_mid.x == p_high.x && p_mid.y == p_high.y))
639 {
640 return;
641 }
642
643 /* Sort by T. */
644 if (p_low.y > p_mid.y && p_low.y > p_high.y) {
645 std::swap(p_high.x, p_low.x);
646 std::swap(p_high.y, p_low.y);
647 }
648 else if (p_mid.y > p_high.y) {
649 std::swap(p_high.x, p_mid.x);
650 std::swap(p_high.y, p_mid.y);
651 }
652
653 if (p_low.y > p_mid.y) {
654 std::swap(p_low.x, p_mid.x);
655 std::swap(p_low.y, p_mid.y);
656 }
657
658 /* Check if mid-point is to the left or to the right of the lo-hi edge. */
659 const bool is_mid_right = math::cross(p_mid - p_high, p_high - p_low) > 0;
660 const int ylo = int(ceilf(p_low.y));
661 const int yhi_beg = int(ceilf(p_mid.y));
662 const int yhi = int(ceilf(p_high.y));
663
664 rasterize_half(
665 baker, tile, triangle, p_low, p_mid, p_low, p_high, ylo, yhi_beg, is_mid_right, result);
666 rasterize_half(
667 baker, tile, triangle, p_mid, p_high, p_low, p_high, yhi_beg, yhi, is_mid_right, result);
668}
669
670static void rasterize_quad(const MultiresBaker &baker,
671 const RasterizeTile &tile,
672 const RasterizeQuad &quad,
673 RasterizeResult &result)
674{
675 RasterizeTriangle triangle;
676 triangle.grid_index = quad.grid_index;
677 triangle.is_flat = quad.is_flat;
678 triangle.has_uv_tangents = quad.has_uv_tangents;
679
680 const int3 quad_split_data[2] = {{0, 1, 2}, {2, 3, 0}};
681 for (const int3 &triangle_idx : Span(quad_split_data, 2)) {
682 triangle.grid_uvs[0] = quad.grid_uvs[triangle_idx.x];
683 triangle.grid_uvs[1] = quad.grid_uvs[triangle_idx.y];
684 triangle.grid_uvs[2] = quad.grid_uvs[triangle_idx.z];
685
686 triangle.tex_uvs[0] = quad.tex_uvs[triangle_idx.x];
687 triangle.tex_uvs[1] = quad.tex_uvs[triangle_idx.y];
688 triangle.tex_uvs[2] = quad.tex_uvs[triangle_idx.z];
689
690 triangle.positions[0] = quad.positions[triangle_idx.x];
691 triangle.positions[1] = quad.positions[triangle_idx.y];
692 triangle.positions[2] = quad.positions[triangle_idx.z];
693
694 triangle.normals[0] = quad.normals[triangle_idx.x];
695 triangle.normals[1] = quad.normals[triangle_idx.y];
696 triangle.normals[2] = quad.normals[triangle_idx.z];
697
698 if (triangle.has_uv_tangents) {
699 triangle.uv_tangents[0] = quad.uv_tangents[triangle_idx.x];
700 triangle.uv_tangents[1] = quad.uv_tangents[triangle_idx.y];
701 triangle.uv_tangents[2] = quad.uv_tangents[triangle_idx.z];
702 }
703
704 rasterize_triangle(baker, tile, triangle, result);
705 }
706}
707
709
710/* -------------------------------------------------------------------- */
713
714class MultiresDisplacementBaker : public MultiresBaker {
715 const SubdivCCG &high_subdiv_ccg_;
716
717 public:
718 MultiresDisplacementBaker(const SubdivCCG &subdiv_ccg,
719 const ImBuf &ibuf,
720 ExtraBuffers &extra_buffers)
721 : high_subdiv_ccg_(subdiv_ccg)
722 {
723 extra_buffers.displacement_buffer.reinitialize(IMB_get_pixel_count(&ibuf));
724 extra_buffers.displacement_buffer.fill(0);
725 }
726
727 float3 bake_pixel(const RasterizeTriangle &triangle,
728 const float2 &bary_uv,
729 const float2 &grid_uv,
730 RasterizeResult &result) const override
731 {
732 const float3 bake_level_position = triangle.get_position(bary_uv);
733 const float3 bake_level_normal = triangle.get_normal(bary_uv);
734 const float3 high_level_position = sample_position_on_subdiv_ccg(
735 high_subdiv_ccg_, triangle.grid_index, grid_uv);
736
737 const float length = math::dot(bake_level_normal, (high_level_position - bake_level_position));
738
739 result.height_min = math::min(result.height_min, length);
740 result.height_max = math::max(result.height_max, length);
741
742 return {length, length, length};
743 }
744
745 void write_pixel(const RasterizeTile &tile,
746 const int2 &coord,
747 const float3 &value) const override
748 {
749 const ImBuf &ibuf = *tile.ibuf;
750
751 const int64_t pixel = int64_t(ibuf.x) * coord.y + coord.x;
752 tile.extra_buffers->displacement_buffer[pixel] = value.x;
753
754 write_pixel_to_image_buffer(*tile.ibuf, coord, value);
755 }
756};
757
758class MultiresVectorDisplacementBaker : public MultiresBaker {
759 const SubdivCCG &high_subdiv_ccg_;
760 eBakeSpace space_;
761
762 public:
763 MultiresVectorDisplacementBaker(const SubdivCCG &subdiv_ccg, const eBakeSpace space)
764 : high_subdiv_ccg_(subdiv_ccg), space_(space)
765 {
766 }
767
768 float3 bake_pixel(const RasterizeTriangle &triangle,
769 const float2 &bary_uv,
770 const float2 &grid_uv,
771 RasterizeResult & /*result*/) const override
772 {
773 const float3 bake_level_position = triangle.get_position(bary_uv);
774
775 const float3 high_level_position = sample_position_on_subdiv_ccg(
776 high_subdiv_ccg_, triangle.grid_index, grid_uv);
777
778 const float3 displacement = high_level_position - bake_level_position;
779
780 if (space_ == R_BAKE_SPACE_TANGENT) {
781 const float3x3 to_tangent = get_to_tangent_matrix_tnb(triangle, bary_uv);
782 return to_tangent * displacement;
783 }
784
785 return displacement;
786 }
787
788 void write_pixel(const RasterizeTile &tile,
789 const int2 &coord,
790 const float3 &value) const override
791 {
792 write_pixel_to_image_buffer(*tile.ibuf, coord, value);
793 }
794};
795
797
798/* -------------------------------------------------------------------- */
801
802class MultiresNormalsBaker : public MultiresBaker {
803 const SubdivCCG &subdiv_ccg_;
804
805 public:
806 explicit MultiresNormalsBaker(const SubdivCCG &subdiv_ccg) : subdiv_ccg_(subdiv_ccg) {}
807
808 float3 bake_pixel(const RasterizeTriangle &triangle,
809 const float2 &bary_uv,
810 const float2 &grid_uv,
811 RasterizeResult & /*result*/) const override
812 {
813 const float3x3 to_tangent = get_to_tangent_matrix_tbn(triangle, bary_uv);
814 const float3 normal = sample_normal_on_subdiv_ccg(subdiv_ccg_, triangle.grid_index, grid_uv);
815 return math::normalize(to_tangent * normal) * 0.5f + float3(0.5f, 0.5f, 0.5f);
816 }
817
818 void write_pixel(const RasterizeTile &tile,
819 const int2 &coord,
820 const float3 &value) const override
821 {
822 write_pixel_to_image_buffer(*tile.ibuf, coord, value);
823 }
824};
825
827
828/* -------------------------------------------------------------------- */
831
832static void initialize_images(MultiresBakeRender &bake)
833{
834 bake.images.clear();
835
836 for (Image *image : bake.ob_image) {
837 if (image) {
838 bake.images.add(image);
839 }
840 }
841}
842
844
845/* -------------------------------------------------------------------- */
848
849static std::unique_ptr<MultiresBaker> create_baker(const MultiresBakeRender &bake,
850 const SubdivCCG &subdiv_ccg,
851 const ImBuf &ibuf,
852 ExtraBuffers &extra_buffers)
853{
854 switch (bake.type) {
855 case R_BAKE_NORMALS:
856 return std::make_unique<MultiresNormalsBaker>(subdiv_ccg);
858 return std::make_unique<MultiresDisplacementBaker>(subdiv_ccg, ibuf, extra_buffers);
860 return std::make_unique<MultiresVectorDisplacementBaker>(subdiv_ccg,
861 bake.displacement_space);
862 case R_BAKE_AO:
863 /* Not implemented, should not be used. */
864 break;
865 }
867 return nullptr;
868}
869
870static void rasterize_base_face(const MultiresBaker &baker,
871 const RasterizeTile &tile,
872 const MeshArrays &mesh_arrays,
873 const Span<float4> uv_tangents,
874 const int face_index,
875 RasterizeResult &result)
876{
877 const IndexRange &face = mesh_arrays.faces[face_index];
878 const Span<int> face_verts = mesh_arrays.corner_verts.slice(face);
879
880 RasterizeQuad quad;
881
882 /* - Grid coordinate (0, 0): face center.
883 * - Grid axis U points from the face center to the middle of the edge connecting corner to
884 * next_corner.
885 * - Grid axis V points from the face center to the middle of the edge connecting prev_corner to
886 * corner. */
887 quad.grid_uvs[0] = float2(0.0f, 0.0f);
888 quad.grid_uvs[1] = float2(1.0f, 0.0f);
889 quad.grid_uvs[2] = float2(1.0f, 1.0f);
890 quad.grid_uvs[3] = float2(0.0f, 1.0f);
891
892 quad.tex_uvs[0] = face_center_tex_uv_calc(mesh_arrays, face_index) - tile.uv_offset;
893 quad.positions[0] = bke::mesh::face_center_calc(mesh_arrays.vert_positions, face_verts);
894
895 /* TODO(sergey): Support corner normals. */
896
897 quad.is_flat = mesh_arrays.sharp_faces[face_index];
898 if (quad.is_flat) {
899 quad.normals[0] = mesh_arrays.face_normals[face_index];
900 }
901 else {
902 quad.normals[0] = face_center_smooth_normal_calc(mesh_arrays, face_index);
903 }
904
905 quad.has_uv_tangents = !uv_tangents.is_empty();
906 if (quad.has_uv_tangents) {
907 quad.uv_tangents[0] = face_center_uv_tangent_calc(mesh_arrays, uv_tangents, face_index);
908 }
909
910 for (const int corner : face) {
911 const int prev_corner = bke::mesh::face_corner_prev(face, corner);
912 const int next_corner = bke::mesh::face_corner_next(face, corner);
913
914 const float3 &position = mesh_arrays.vert_positions[mesh_arrays.corner_verts[corner]];
915 const float3 &next_position =
916 mesh_arrays.vert_positions[mesh_arrays.corner_verts[next_corner]];
917 const float3 &prev_position =
918 mesh_arrays.vert_positions[mesh_arrays.corner_verts[prev_corner]];
919
920 quad.grid_index = corner;
921
922 quad.tex_uvs[1] = (mesh_arrays.uv_map[corner] + mesh_arrays.uv_map[next_corner]) * 0.5f -
923 tile.uv_offset;
924 quad.tex_uvs[2] = mesh_arrays.uv_map[corner] - tile.uv_offset;
925 quad.tex_uvs[3] = (mesh_arrays.uv_map[prev_corner] + mesh_arrays.uv_map[corner]) * 0.5f -
926 tile.uv_offset;
927
928 quad.positions[1] = (position + next_position) * 0.5f;
929 quad.positions[2] = position;
930 quad.positions[3] = (prev_position + position) * 0.5f;
931
932 if (quad.is_flat) {
933 quad.normals[1] = quad.normals[0];
934 quad.normals[2] = quad.normals[0];
935 quad.normals[3] = quad.normals[0];
936 }
937 else {
938 const float3 &normal = mesh_arrays.vert_normals[mesh_arrays.corner_verts[corner]];
939 const float3 &next_normal = mesh_arrays.vert_normals[mesh_arrays.corner_verts[next_corner]];
940 const float3 &prev_normal = mesh_arrays.vert_normals[mesh_arrays.corner_verts[prev_corner]];
941
942 /* NOTE: No normalization here: do it after interpolation at the baking point.
943 *
944 * This preserves linearity of operation. If normalization is done here interpolation will go
945 * wrong. */
946 quad.normals[1] = (normal + next_normal) * 0.5f;
947 quad.normals[2] = normal;
948 quad.normals[3] = (prev_normal + normal) * 0.5f;
949 }
950
951 if (quad.has_uv_tangents) {
952 const float4 &tangent = uv_tangents[corner];
953 const float4 &next_tangent = uv_tangents[next_corner];
954 const float4 &prev_tangent = uv_tangents[prev_corner];
955
956 quad.uv_tangents[1] = (tangent + next_tangent) * 0.5f;
957 quad.uv_tangents[2] = tangent;
958 quad.uv_tangents[3] = (prev_tangent + tangent) * 0.5f;
959 }
960
961 rasterize_quad(baker, tile, quad, result);
962 }
963}
964
965static void bake_single_image_to_base_mesh(MultiresBakeRender &bake,
966 const Mesh &bake_level_mesh,
967 const SubdivCCG &subdiv_ccg,
968 Image &image,
969 ImageTile &image_tile,
970 ImBuf &ibuf,
971 ExtraBuffers &extra_buffers,
972 MultiresBakeResult &result)
973{
974 std::unique_ptr<MultiresBaker> baker = create_baker(bake, subdiv_ccg, ibuf, extra_buffers);
975 if (!baker) {
976 return;
977 }
978
979 MeshArrays mesh_arrays(bake_level_mesh);
980 Array<float4> uv_tangents;
981 if (need_tangent(bake)) {
982 uv_tangents = calc_uv_tangents(mesh_arrays);
983 }
984
985 RasterizeTile tile;
986 tile.ibuf = &ibuf;
987 tile.extra_buffers = &extra_buffers;
988 tile.uv_offset = get_tile_uv(image, image_tile);
989
990 SpinLock spin_lock;
991 BLI_spin_init(&spin_lock);
992 std::atomic<int> num_baked_faces = 0;
993 threading::parallel_for(mesh_arrays.faces.index_range(), 1, [&](const IndexRange range) {
994 for (const int64_t face_index : range) {
995 if (multiresbake_test_break(bake)) {
996 return;
997 }
998
999 /* Check whether the face is to be baked into the current image. */
1000 const int mat_nr = mesh_arrays.material_indices[face_index];
1001 const Image *face_image = mat_nr < bake.ob_image.size() ? bake.ob_image[mat_nr] : nullptr;
1002 if (face_image != &image) {
1003 continue;
1004 }
1005
1006 RasterizeResult rasterize_result;
1007 rasterize_base_face(*baker, tile, mesh_arrays, uv_tangents, face_index, rasterize_result);
1008
1009 ++num_baked_faces;
1010 BLI_spin_lock(&spin_lock);
1011 result.height_min = std::min(result.height_min, rasterize_result.height_min);
1012 result.height_max = std::max(result.height_max, rasterize_result.height_max);
1013 if (bake.do_update) {
1014 *bake.do_update = true;
1015 }
1016 if (bake.progress) {
1017 *bake.progress = (float(bake.num_baked_objects) +
1018 float(num_baked_faces) / mesh_arrays.faces.size()) /
1019 bake.num_total_objects;
1020 }
1021 BLI_spin_unlock(&spin_lock);
1022 }
1023 });
1024 BLI_spin_end(&spin_lock);
1025}
1026
1028
1029/* -------------------------------------------------------------------- */
1032
1033struct GridCoord {
1034 int grid_index;
1035 float2 uv;
1036};
1037
1038static Array<GridCoord> get_subdivided_corner_grid_coords(subdiv::Subdiv &subdiv,
1039 const Mesh &coarse_mesh,
1040 const int level)
1041{
1042 struct SubdividedCornerGridCoordData {
1043 MeshArrays coarse_mesh_arrays;
1044 Array<GridCoord> corner_grid_coords;
1045 };
1046
1047 subdiv::ToMeshSettings mesh_settings;
1048 mesh_settings.resolution = (1 << level) + 1;
1049
1050 SubdividedCornerGridCoordData data;
1051 data.coarse_mesh_arrays = MeshArrays(coarse_mesh);
1052
1053 subdiv::ForeachContext foreach_context;
1054 foreach_context.user_data = &data;
1055
1056 foreach_context.topology_info = [](const subdiv::ForeachContext *context,
1057 const int /*num_vertices*/,
1058 const int /*num_edges*/,
1059 const int num_corners,
1060 const int /*num_faces*/,
1061 const int * /*subdiv_face_offset*/) -> bool {
1062 SubdividedCornerGridCoordData *data = static_cast<SubdividedCornerGridCoordData *>(
1063 context->user_data);
1064 data->corner_grid_coords.reinitialize(num_corners);
1065 return true;
1066 };
1067
1068 foreach_context.loop = [](const subdiv::ForeachContext *context,
1069 void * /*tls*/,
1070 const int /*ptex_face_index*/,
1071 const float u,
1072 const float v,
1073 const int /*coarse_corner_index*/,
1074 const int coarse_face_index,
1075 const int coarse_corner,
1076 const int subdiv_corner_index,
1077 const int /*subdiv_vertex_index*/,
1078 const int /*subdiv_edge_index*/) {
1079 SubdividedCornerGridCoordData *data = static_cast<SubdividedCornerGridCoordData *>(
1080 context->user_data);
1081
1082 const float2 ptex_uv(u, v);
1083 const IndexRange coarse_face = data->coarse_mesh_arrays.faces[coarse_face_index];
1084
1085 GridCoord &corner_grid_coord = data->corner_grid_coords[subdiv_corner_index];
1086 corner_grid_coord.grid_index = coarse_face.start() + coarse_corner;
1087
1088 if (coarse_face.size() == 4) {
1089 corner_grid_coord.uv = subdiv::ptex_face_uv_to_grid_uv(
1090 subdiv::rotate_quad_to_corner(coarse_corner, ptex_uv));
1091 }
1092 else {
1093 corner_grid_coord.uv = subdiv::ptex_face_uv_to_grid_uv(ptex_uv);
1094 }
1095 };
1096
1097 foreach_subdiv_geometry(&subdiv, &foreach_context, &mesh_settings, &coarse_mesh);
1098
1099 return data.corner_grid_coords;
1100}
1101
1102static void rasterize_subdivided_face(const MultiresBaker &baker,
1103 const RasterizeTile &tile,
1104 const MeshArrays &mesh_arrays,
1105 const Span<GridCoord> &corner_grid_coords,
1106 const Span<float4> uv_tangents,
1107 const int face_index,
1108 RasterizeResult &result)
1109{
1110 const IndexRange &face = mesh_arrays.faces[face_index];
1111
1112 /* This code operates with mesh with at leats one subdivision level applied. Such mesh only has
1113 * quad faces as per how subdivision works. */
1114 BLI_assert(face.size() == 4);
1115
1116 RasterizeQuad quad;
1117
1118 /* TODO(sergey): Support corner normals. */
1119
1120 quad.is_flat = mesh_arrays.sharp_faces[face_index];
1121 quad.has_uv_tangents = !uv_tangents.is_empty();
1122 quad.grid_index = corner_grid_coords[face.start()].grid_index;
1123
1124 for (int i = 0; i < 4; ++i) {
1125 const int corner = face[i];
1126 const int vertex = mesh_arrays.corner_verts[corner];
1127
1128 BLI_assert(corner_grid_coords[corner].grid_index == quad.grid_index);
1129 quad.grid_uvs[i] = corner_grid_coords[corner].uv;
1130
1131 quad.tex_uvs[i] = mesh_arrays.uv_map[corner] - tile.uv_offset;
1132 quad.positions[i] = mesh_arrays.vert_positions[vertex];
1133 if (!quad.is_flat) {
1134 quad.normals[i] = mesh_arrays.vert_normals[vertex];
1135 }
1136
1137 if (quad.has_uv_tangents) {
1138 quad.uv_tangents[i] = uv_tangents[corner];
1139 }
1140 }
1141
1142 if (quad.is_flat) {
1143 quad.normals[0] = mesh_arrays.face_normals[face_index];
1144 quad.normals[1] = quad.normals[0];
1145 quad.normals[2] = quad.normals[0];
1146 quad.normals[3] = quad.normals[0];
1147 }
1148
1149 rasterize_quad(baker, tile, quad, result);
1150}
1151
1152static void bake_single_image_to_subdivided_mesh(MultiresBakeRender &bake,
1153 const Mesh &bake_level_mesh,
1154 const SubdivCCG &subdiv_ccg,
1155 Image &image,
1156 ImageTile &image_tile,
1157 ImBuf &ibuf,
1158 ExtraBuffers &extra_buffers,
1159 MultiresBakeResult &result)
1160{
1161 std::unique_ptr<MultiresBaker> baker = create_baker(bake, subdiv_ccg, ibuf, extra_buffers);
1162 if (!baker) {
1163 return;
1164 }
1165
1166 MeshArrays mesh_arrays(bake_level_mesh);
1167 Array<float4> uv_tangents;
1168 if (need_tangent(bake)) {
1169 uv_tangents = calc_uv_tangents(mesh_arrays);
1170 }
1171
1172 RasterizeTile tile;
1173 tile.ibuf = &ibuf;
1174 tile.extra_buffers = &extra_buffers;
1175 tile.uv_offset = get_tile_uv(image, image_tile);
1176
1177 const Array<GridCoord> corner_grid_coords = get_subdivided_corner_grid_coords(
1178 *subdiv_ccg.subdiv, *bake.base_mesh, bake.multires_modifier->lvl);
1179
1180 SpinLock spin_lock;
1181 BLI_spin_init(&spin_lock);
1182 std::atomic<int> num_baked_faces = 0;
1183 threading::parallel_for(mesh_arrays.faces.index_range(), 1, [&](const IndexRange range) {
1184 for (const int64_t face_index : range) {
1185 if (multiresbake_test_break(bake)) {
1186 return;
1187 }
1188
1189 /* Check whether the face is to be baked into the current image. */
1190 const int mat_nr = mesh_arrays.material_indices[face_index];
1191 const Image *face_image = mat_nr < bake.ob_image.size() ? bake.ob_image[mat_nr] : nullptr;
1192 if (face_image != &image) {
1193 continue;
1194 }
1195
1196 RasterizeResult rasterize_result;
1197 rasterize_subdivided_face(*baker,
1198 tile,
1199 mesh_arrays,
1200 corner_grid_coords,
1201 uv_tangents,
1202 face_index,
1203 rasterize_result);
1204
1205 ++num_baked_faces;
1206 BLI_spin_lock(&spin_lock);
1207 result.height_min = std::min(result.height_min, rasterize_result.height_min);
1208 result.height_max = std::max(result.height_max, rasterize_result.height_max);
1209 if (bake.do_update) {
1210 *bake.do_update = true;
1211 }
1212 if (bake.progress) {
1213 *bake.progress = (float(bake.num_baked_objects) +
1214 float(num_baked_faces) / mesh_arrays.faces.size()) /
1215 bake.num_total_objects;
1216 }
1217 BLI_spin_unlock(&spin_lock);
1218 }
1219 });
1220 BLI_spin_end(&spin_lock);
1221}
1222
1224
1225/* -------------------------------------------------------------------- */
1229
1230/* Subdivide bake_level_mesh to the level of `total level - viewport level`.
1231 * Essentially bring the bake_level_mesh to the same resolution level as the top multi-resolution
1232 * level. */
1233static const Mesh *create_highres_mesh(const Mesh &bake_level_mesh,
1234 const MultiresModifierData &multires_modifier)
1235{
1236 const int top_level = multires_modifier.totlvl;
1237 const int bake_level = multires_modifier.lvl;
1238 const int subdivide_level = top_level - bake_level;
1239 if (subdivide_level == 0) {
1240 return &bake_level_mesh;
1241 }
1242
1243 subdiv::Settings subdiv_settings;
1244 BKE_multires_subdiv_settings_init(&subdiv_settings, &multires_modifier);
1245 subdiv::Subdiv *subdiv = subdiv::update_from_mesh(nullptr, &subdiv_settings, &bake_level_mesh);
1246
1247 subdiv::ToMeshSettings mesh_settings;
1248 mesh_settings.resolution = (1 << subdivide_level) + 1;
1249
1250 Mesh *result = subdiv::subdiv_to_mesh(subdiv, &mesh_settings, &bake_level_mesh);
1251
1252 subdiv::free(subdiv);
1253
1254 return result;
1255}
1256
1257/* Get grid coordinates for every corner of the highres_bake_mesh. */
1258static Array<GridCoord> get_highres_mesh_loop_grid_coords(
1259 subdiv::Subdiv &subdiv,
1260 const MultiresModifierData &multires_modifier,
1261 const Mesh &base_mesh,
1262 const Mesh &bake_level_mesh,
1263 const Mesh &highres_bake_mesh)
1264{
1265 UNUSED_VARS_NDEBUG(highres_bake_mesh);
1266
1267 if (multires_modifier.lvl == 0) {
1268 /* Simple case: baking from subdivided mesh highres_bake_mesh to the base mesh. */
1269 return get_subdivided_corner_grid_coords(
1270 subdiv, bake_level_mesh, multires_modifier.totlvl - multires_modifier.lvl);
1271 }
1272
1273 /* More tricky case:
1274 * - The base_mesh is first subdivided to the viewport level (bake_level_mesh)
1275 * - The bake_level_mesh is then further subdivided (highres_bake_mesh).
1276 *
1277 * This case needs an extra level of indirection: map loops from the highres_bake_mesh to the
1278 * faces of the bake_level_mesh, and then interpolate the grid coordinates calculated for the
1279 * bake_level_mesh to get grid coordinates.
1280 *
1281 * The coarse mesh here is the same as bake_level_mesh, and the subdiv mesh is the same as
1282 * highres_bake_mesh.
1283 *
1284 * It is possible to optimize the memory usage here by utilizing an implicit knowledge about
1285 * how faces in the high-res mesh are created from the bake level mesh: Since the bake level
1286 * mesh has some amount of subdivisions in this branch all its faces are quads. So all the
1287 * faces in the high-res mesh are also quads, created in the grid pattern from the bake level
1288 * faces. */
1289
1290 struct HighresCornerGridCoordData {
1291 MeshArrays bake_level_mesh_arrays;
1292 Array<GridCoord> bake_level_corner_grid_coords;
1293
1294 Array<GridCoord> corner_grid_coords;
1295 };
1296
1297 const int top_level = multires_modifier.totlvl;
1298 const int bake_level = multires_modifier.lvl;
1299 const int subdivide_level = top_level - bake_level;
1300
1301 subdiv::ToMeshSettings mesh_settings;
1302 mesh_settings.resolution = (1 << subdivide_level) + 1;
1303
1304 HighresCornerGridCoordData data;
1305 data.bake_level_mesh_arrays = MeshArrays(bake_level_mesh);
1306 data.bake_level_corner_grid_coords = get_subdivided_corner_grid_coords(
1307 subdiv, base_mesh, multires_modifier.lvl);
1308
1309 subdiv::ForeachContext foreach_context;
1310 foreach_context.user_data = &data;
1311
1312 foreach_context.topology_info = [](const subdiv::ForeachContext *context,
1313 const int /*num_vertices*/,
1314 const int /*num_edges*/,
1315 const int num_corners,
1316 const int /*num_faces*/,
1317 const int * /*subdiv_face_offset*/) -> bool {
1318 HighresCornerGridCoordData *data = static_cast<HighresCornerGridCoordData *>(
1319 context->user_data);
1320 data->corner_grid_coords.reinitialize(num_corners);
1321 return true;
1322 };
1323
1324 foreach_context.loop = [](const subdiv::ForeachContext *context,
1325 void * /*tls*/,
1326 const int /*ptex_face_index*/,
1327 const float u,
1328 const float v,
1329 const int /*bake_level_corner_index*/,
1330 const int bake_level_face_index,
1331 const int /*bake_level_corner*/,
1332 const int highres_corner_index,
1333 const int /*highres_vertex_index*/,
1334 const int /*highres_edge_index*/) {
1335 HighresCornerGridCoordData *data = static_cast<HighresCornerGridCoordData *>(
1336 context->user_data);
1337
1338 const Span<GridCoord> bake_level_corner_grid_coords = data->bake_level_corner_grid_coords;
1339
1340 const IndexRange bake_level_face = data->bake_level_mesh_arrays.faces[bake_level_face_index];
1341 BLI_assert(bake_level_face.size() == 4);
1342
1343 const int bake_level_face_start = bake_level_face.start();
1344
1345 GridCoord &corner_grid_coord = data->corner_grid_coords[highres_corner_index];
1346 corner_grid_coord.grid_index = bake_level_corner_grid_coords[bake_level_face_start].grid_index;
1347 corner_grid_coord.uv = interp_bilinear_quad(
1348 u,
1349 v,
1350 bake_level_corner_grid_coords[bake_level_face_start + 0].uv,
1351 bake_level_corner_grid_coords[bake_level_face_start + 1].uv,
1352 bake_level_corner_grid_coords[bake_level_face_start + 2].uv,
1353 bake_level_corner_grid_coords[bake_level_face_start + 3].uv);
1354
1355 /* Loops of the bake level mesh are supposed to be in the same grid. */
1356 BLI_assert(corner_grid_coord.grid_index ==
1357 bake_level_corner_grid_coords[bake_level_face_start + 1].grid_index);
1358 BLI_assert(corner_grid_coord.grid_index ==
1359 bake_level_corner_grid_coords[bake_level_face_start + 2].grid_index);
1360 BLI_assert(corner_grid_coord.grid_index ==
1361 bake_level_corner_grid_coords[bake_level_face_start + 3].grid_index);
1362 };
1363
1364 foreach_subdiv_geometry(&subdiv, &foreach_context, &mesh_settings, &bake_level_mesh);
1365
1366 BLI_assert(data.corner_grid_coords.size() == highres_bake_mesh.corners_num);
1367 return data.corner_grid_coords;
1368}
1369
1370static void bake_single_image_displacement(MultiresBakeRender &bake,
1371 const Mesh &bake_level_mesh,
1372 const SubdivCCG &subdiv_ccg,
1373 Image &image,
1374 ImageTile &image_tile,
1375 ImBuf &ibuf,
1376 ExtraBuffers &extra_buffers,
1377 MultiresBakeResult &result)
1378{
1379 std::unique_ptr<MultiresBaker> baker = create_baker(bake, subdiv_ccg, ibuf, extra_buffers);
1380 if (!baker) {
1381 return;
1382 }
1383
1384 const Mesh *highres_bake_mesh = result.highres_bake_mesh;
1385 if (!highres_bake_mesh) {
1386 highres_bake_mesh = create_highres_mesh(bake_level_mesh, *bake.multires_modifier);
1387 result.highres_bake_mesh = highres_bake_mesh;
1388 }
1389
1390 const Array<GridCoord> corner_grid_coords = get_highres_mesh_loop_grid_coords(
1391 *subdiv_ccg.subdiv,
1392 *bake.multires_modifier,
1393 *bake.base_mesh,
1394 bake_level_mesh,
1395 *highres_bake_mesh);
1396
1397 MeshArrays mesh_arrays(*highres_bake_mesh);
1398 Array<float4> uv_tangents;
1399 if (need_tangent(bake)) {
1400 uv_tangents = calc_uv_tangents(mesh_arrays);
1401 }
1402
1403 RasterizeTile tile;
1404 tile.ibuf = &ibuf;
1405 tile.extra_buffers = &extra_buffers;
1406 tile.uv_offset = get_tile_uv(image, image_tile);
1407
1408 SpinLock spin_lock;
1409 BLI_spin_init(&spin_lock);
1410 std::atomic<int> num_baked_faces = 0;
1411 threading::parallel_for(mesh_arrays.faces.index_range(), 1, [&](const IndexRange range) {
1412 for (const int64_t face_index : range) {
1413 if (multiresbake_test_break(bake)) {
1414 return;
1415 }
1416
1417 /* Check whether the face is to be baked into the current image. */
1418 const int mat_nr = mesh_arrays.material_indices[face_index];
1419 const Image *face_image = mat_nr < bake.ob_image.size() ? bake.ob_image[mat_nr] : nullptr;
1420 if (face_image != &image) {
1421 continue;
1422 }
1423
1424 RasterizeResult rasterize_result;
1425 rasterize_subdivided_face(*baker,
1426 tile,
1427 mesh_arrays,
1428 corner_grid_coords,
1429 uv_tangents,
1430 face_index,
1431 rasterize_result);
1432
1433 ++num_baked_faces;
1434 BLI_spin_lock(&spin_lock);
1435 result.height_min = std::min(result.height_min, rasterize_result.height_min);
1436 result.height_max = std::max(result.height_max, rasterize_result.height_max);
1437 if (bake.do_update) {
1438 *bake.do_update = true;
1439 }
1440 if (bake.progress) {
1441 *bake.progress = (float(bake.num_baked_objects) +
1442 float(num_baked_faces) / mesh_arrays.faces.size()) /
1443 bake.num_total_objects;
1444 }
1445 BLI_spin_unlock(&spin_lock);
1446 }
1447 });
1448 BLI_spin_end(&spin_lock);
1449}
1450
1452
1453/* -------------------------------------------------------------------- */
1456
1457static void bake_single_image(MultiresBakeRender &bake,
1458 const Mesh &bake_level_mesh,
1459 const SubdivCCG &subdiv_ccg,
1460 Image &image,
1461 ImageTile &image_tile,
1462 ImBuf &ibuf,
1463 ExtraBuffers &extra_buffers,
1464 MultiresBakeResult &result)
1465{
1467 !bake.use_low_resolution_mesh &&
1468 bake.multires_modifier->lvl != bake.multires_modifier->totlvl)
1469 {
1470 bake_single_image_displacement(
1471 bake, bake_level_mesh, subdiv_ccg, image, image_tile, ibuf, extra_buffers, result);
1472 return;
1473 }
1474
1475 if (bake.multires_modifier->lvl == 0) {
1476 bake_single_image_to_base_mesh(
1477 bake, bake_level_mesh, subdiv_ccg, image, image_tile, ibuf, extra_buffers, result);
1478 return;
1479 }
1480
1481 bake_single_image_to_subdivided_mesh(
1482 bake, bake_level_mesh, subdiv_ccg, image, image_tile, ibuf, extra_buffers, result);
1483}
1484
1485static void bake_images(MultiresBakeRender &bake,
1486 const Mesh &bake_level_mesh,
1487 const SubdivCCG &subdiv_ccg,
1488 MultiresBakeResult &result)
1489{
1490 for (Image *image : bake.images) {
1491 LISTBASE_FOREACH (ImageTile *, image_tile, &image->tiles) {
1492 ImageUser iuser;
1493 BKE_imageuser_default(&iuser);
1494 iuser.tile = image_tile->tile_number;
1495
1496 ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, nullptr);
1497 if (ibuf && ibuf->x > 0 && ibuf->y > 0) {
1498 result.baked_ibufs.append({});
1499
1500 BakedImBuf &baked_ibuf = result.baked_ibufs.last();
1501 baked_ibuf.image = image;
1502 baked_ibuf.ibuf = ibuf;
1503 baked_ibuf.uv_offset = get_tile_uv(*image, *image_tile);
1504
1505 ExtraBuffers &extra_buffers = baked_ibuf.extra_buffers;
1506 extra_buffers.mask_buffer.reinitialize(int64_t(ibuf->y) * ibuf->x);
1507 extra_buffers.mask_buffer.fill(FILTER_MASK_NULL);
1508
1509 bake_single_image(
1510 bake, bake_level_mesh, subdiv_ccg, *image, *image_tile, *ibuf, extra_buffers, result);
1511 }
1512 }
1513 }
1514}
1515
1517
1518/* -------------------------------------------------------------------- */
1521
1522static void bake_ibuf_normalize_displacement(ImBuf &ibuf,
1523 const MutableSpan<float> displacement,
1524 const Span<char> mask,
1525 const float displacement_min,
1526 const float displacement_max)
1527{
1528 const float *current_displacement = displacement.data();
1529 const char *current_mask = mask.data();
1530 const float max_distance = math::max(math::abs(displacement_min), math::abs(displacement_max));
1531
1532 if (max_distance <= 1e-5f) {
1533 const float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
1534 IMB_rectfill(&ibuf, col);
1535 return;
1536 }
1537
1538 /* TODO(sergey): Look into multi-threading this loop. */
1539 const size_t ibuf_pixel_count = IMB_get_pixel_count(&ibuf);
1540 for (size_t i = 0; i < ibuf_pixel_count; i++) {
1541 if (*current_mask == FILTER_MASK_USED) {
1542 const float normalized_displacement = (*current_displacement + max_distance) /
1543 (max_distance * 2);
1544
1545 if (ibuf.float_buffer.data) {
1546 /* TODO(sergey): Properly tackle ibuf.channels. */
1547 BLI_assert(ibuf.channels == 4);
1548 float *fp = ibuf.float_buffer.data + int64_t(i) * 4;
1549 fp[0] = fp[1] = fp[2] = normalized_displacement;
1550 fp[3] = 1.0f;
1551 }
1552
1553 if (ibuf.byte_buffer.data) {
1554 uchar *cp = ibuf.byte_buffer.data + int64_t(i) * 4;
1555 cp[0] = cp[1] = cp[2] = unit_float_to_uchar_clamp(normalized_displacement);
1556 cp[3] = 255;
1557 }
1558 }
1559
1560 current_displacement++;
1561 current_mask++;
1562 }
1563}
1564
1565static void bake_ibuf_filter(ImBuf &ibuf,
1566 const MutableSpan<char> mask,
1567 const Mesh &bake_level_mesh,
1568 const int margin,
1569 const eBakeMarginType margin_type,
1570 const float2 uv_offset)
1571{
1572 /* NOTE: Must check before filtering. */
1573 const bool is_new_alpha = (ibuf.planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(&ibuf);
1574
1575 if (margin) {
1576 switch (margin_type) {
1577 case R_BAKE_ADJACENT_FACES: {
1578 const char *active_uv_map = CustomData_get_active_layer_name(&bake_level_mesh.corner_data,
1581 &ibuf, mask.data(), margin, &bake_level_mesh, active_uv_map, uv_offset);
1582 break;
1583 }
1584 default:
1585 /* Fall through. */
1586 case R_BAKE_EXTEND:
1587 IMB_filter_extend(&ibuf, mask.data(), margin);
1588 break;
1589 }
1590 }
1591
1592 /* If the bake results in new alpha then change the image setting. */
1593 if (is_new_alpha) {
1595 }
1596 else {
1597 if (margin && ibuf.planes != R_IMF_PLANES_RGBA) {
1598 /* Clear alpha added by filtering. */
1599 IMB_rectfill_alpha(&ibuf, 1.0f);
1600 }
1601 }
1602}
1603
1604static void finish_images(MultiresBakeRender &bake,
1605 const Mesh &bake_level_mesh,
1606 MultiresBakeResult &result)
1607{
1608 const bool use_displacement_buffer = bake.type == R_BAKE_DISPLACEMENT;
1609
1610 for (BakedImBuf &baked_ibuf : result.baked_ibufs) {
1611 Image *image = baked_ibuf.image;
1612 ImBuf *ibuf = baked_ibuf.ibuf;
1613
1614 if (use_displacement_buffer) {
1615 bake_ibuf_normalize_displacement(*ibuf,
1616 baked_ibuf.extra_buffers.displacement_buffer,
1617 baked_ibuf.extra_buffers.mask_buffer,
1618 result.height_min,
1619 result.height_max);
1620 }
1621
1622 bake_ibuf_filter(*ibuf,
1623 baked_ibuf.extra_buffers.mask_buffer,
1624 bake_level_mesh,
1625 bake.bake_margin,
1626 bake.bake_margin_type,
1627 baked_ibuf.uv_offset);
1628
1630 BKE_image_mark_dirty(image, ibuf);
1631
1632 if (ibuf->float_buffer.data) {
1633 ibuf->userflags |= IB_RECT_INVALID;
1634 }
1635
1636 BKE_image_release_ibuf(image, ibuf, nullptr);
1637 DEG_id_tag_update(&image->id, 0);
1638 }
1639}
1640
1642
1643/* -------------------------------------------------------------------- */
1646
1647static subdiv::Subdiv *create_subdiv(const Mesh &mesh,
1648 const MultiresModifierData &multires_modifier)
1649{
1650 subdiv::Settings subdiv_settings;
1651 BKE_multires_subdiv_settings_init(&subdiv_settings, &multires_modifier);
1652 subdiv::Subdiv *subdiv = subdiv::update_from_mesh(nullptr, &subdiv_settings, &mesh);
1653 subdiv::displacement_attach_from_multires(subdiv, &mesh, &multires_modifier);
1654
1655 /* Initialization evaluation of the limit surface and the displacement. */
1656 if (!subdiv::eval_begin_from_mesh(subdiv, &mesh, subdiv::SUBDIV_EVALUATOR_TYPE_CPU)) {
1657 subdiv::free(subdiv);
1658 return nullptr;
1659 }
1660 subdiv::eval_init_displacement(subdiv);
1661
1662 return subdiv;
1663}
1664
1665static std::unique_ptr<SubdivCCG> create_subdiv_ccg(const Mesh &mesh,
1666 const MultiresModifierData &multires_modifier)
1667{
1668 subdiv::Subdiv *subdiv = create_subdiv(mesh, multires_modifier);
1669 if (!subdiv) {
1670 return nullptr;
1671 }
1672
1673 SubdivToCCGSettings settings;
1674 settings.resolution = (1 << multires_modifier.totlvl) + 1;
1675 settings.need_normal = true;
1676 settings.need_mask = false;
1677
1678 return BKE_subdiv_to_ccg(*subdiv, settings, mesh);
1679}
1680
1681static Mesh *create_bake_level_mesh(const Mesh &base_mesh,
1682 const MultiresModifierData &multires_modifier)
1683{
1684 subdiv::Subdiv *subdiv = create_subdiv(base_mesh, multires_modifier);
1685 if (!subdiv) {
1686 return nullptr;
1687 }
1688
1689 subdiv::ToMeshSettings mesh_settings;
1690 mesh_settings.resolution = (1 << multires_modifier.lvl) + 1;
1691 subdiv::displacement_attach_from_multires(subdiv, &base_mesh, &multires_modifier);
1692 Mesh *result = subdiv::subdiv_to_mesh(subdiv, &mesh_settings, &base_mesh);
1693 subdiv::free(subdiv);
1694 return result;
1695}
1696
1698
1699} // namespace
1700} // namespace blender::render
1701
1703{
1704 using namespace blender::render;
1705
1706 std::unique_ptr<SubdivCCG> subdiv_ccg = create_subdiv_ccg(*bake.base_mesh,
1707 *bake.multires_modifier);
1708
1709 Mesh *bake_level_mesh = bake.base_mesh;
1710 if (bake.multires_modifier->lvl != 0) {
1711 bake_level_mesh = create_bake_level_mesh(*bake.base_mesh, *bake.multires_modifier);
1712 }
1713
1714 MultiresBakeResult result;
1715 initialize_images(bake);
1716 bake_images(bake, *bake_level_mesh, *subdiv_ccg, result);
1717
1718 const Mesh *filter_mesh = result.highres_bake_mesh ? result.highres_bake_mesh : bake_level_mesh;
1719 finish_images(bake, *filter_mesh, result);
1720
1721 if (result.highres_bake_mesh && result.highres_bake_mesh != bake_level_mesh) {
1722 BKE_id_free(nullptr, const_cast<Mesh *>(result.highres_bake_mesh));
1723 }
1724 if (bake_level_mesh != bake.base_mesh) {
1725 BKE_id_free(nullptr, bake_level_mesh);
1726 }
1727}
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_mark_dirty(Image *image, ImBuf *ibuf)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
void BKE_image_get_tile_uv(const Image *ima, const int tile_number, float r_uv[2])
bool BKE_imbuf_alpha_test(ImBuf *ibuf)
void BKE_imageuser_default(ImageUser *iuser)
void BKE_id_free(Main *bmain, void *idv)
void BKE_multires_subdiv_settings_init(blender::bke::subdiv::Settings *settings, const MultiresModifierData *mmd)
std::unique_ptr< SubdivCCG > BKE_subdiv_to_ccg(blender::bke::subdiv::Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh, SubdivCCGMaskEvaluator *mask_evaluator=nullptr)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void resolve_tri_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2])
unsigned char uchar
pthread_spinlock_t SpinLock
void BLI_spin_init(SpinLock *spin)
Definition threads.cc:391
void BLI_spin_end(SpinLock *spin)
Definition threads.cc:445
#define UNUSED_VARS_NDEBUG(...)
#define ELEM(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ CD_PROP_FLOAT2
struct ImageTile ImageTile
struct Image Image
struct Mesh Mesh
@ R_BAKE_NORMALS
@ R_BAKE_AO
@ R_BAKE_DISPLACEMENT
@ R_BAKE_VECTOR_DISPLACEMENT
eBakeSpace
@ R_BAKE_SPACE_TANGENT
eBakeMarginType
@ R_BAKE_ADJACENT_FACES
@ R_BAKE_EXTEND
@ R_IMF_PLANES_RGBA
void IMB_rectfill_alpha(ImBuf *ibuf, float value)
Definition rectop.cc:1122
#define FILTER_MASK_USED
Definition IMB_imbuf.hh:290
#define FILTER_MASK_NULL
Definition IMB_imbuf.hh:288
size_t IMB_get_pixel_count(const ImBuf *ibuf)
Get the length of the data of the given image buffer in pixels.
void IMB_rectfill(ImBuf *drect, const float col[4])
Definition rectop.cc:978
void IMB_filter_extend(ImBuf *ibuf, char *mask, int filter)
Definition filter.cc:200
@ IB_RECT_INVALID
@ IB_DISPLAY_BUFFER_INVALID
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
long long int int64_t
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
AttributeSet attributes
constexpr int64_t size() const
constexpr int64_t start() const
constexpr T * data() const
Definition BLI_span.hh:539
bool add(const Key &key)
Definition BLI_set.hh:248
void clear()
Definition BLI_set.hh:551
constexpr bool is_empty() const
Definition BLI_span.hh:260
blender::gpu::Batch * quad
uint col
constexpr T sign(T) RET
const ccl_global KernelWorkTile * tile
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
#define unit_float_to_uchar_clamp_v3(v1, v2)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define T
#define G(x, y, z)
void RE_multires_bake_images(MultiresBakeRender &bake)
int face_corner_prev(const IndexRange face, const int corner)
Definition BKE_mesh.hh:306
Array< Array< float4 > > calc_uv_tangents(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, Span< int3 > corner_tris, Span< int > corner_tri_faces, Span< bool > sharp_faces, Span< float3 > vert_normals, Span< float3 > face_normals, Span< float3 > corner_normals, Span< Span< float2 > > uv_maps)
float3 face_center_calc(Span< float3 > vert_positions, Span< int > face_verts)
int face_corner_next(const IndexRange face, const int corner)
Definition BKE_mesh.hh:315
bool foreach_subdiv_geometry(Subdiv *subdiv, const ForeachContext *context, const ToMeshSettings *mesh_settings, const Mesh *coarse_mesh)
int context(const bContext *C, const char *member, bContextDataResult *result)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T min(const T &a, const T &b)
CartesianBasis invert(const CartesianBasis &basis)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T max(const T &a, const T &b)
T abs(const T &a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
#define fabsf
#define ceilf
#define FLT_MAX
Definition stdcycles.h:14
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
ListBase tiles
int corners_num
CustomData corner_data
blender::Set< Image * > images
blender::Vector< Image * > ob_image
MultiresModifierData * multires_modifier
eBakeSpace displacement_space
blender::Array< blender::float3 > normals
blender::bke::subdiv::Subdiv * subdiv
blender::Array< blender::float3 > positions
float x
float y
float x
Definition sky_math.h:136
float w
Definition sky_math.h:225
i
Definition text_draw.cc:230
void RE_generate_texturemargin_adjacentfaces(ImBuf *ibuf, char *mask, const int margin, const Mesh *mesh, blender::StringRef uv_layer, const float uv_offset[2])
int xy[2]
Definition wm_draw.cc:178