109namespace subdiv = bke::subdiv;
116template<
class T>
T interp_barycentric_triangle(
const T data[3],
const float2 &uv)
122T interp_bilinear_quad(
123 const float u,
const float v,
const T &p0,
const T &p1,
const T &p2,
const T &p3)
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;
130 return p0 * w0 + p1 * w1 + p2 * w2 + p3 * w3;
146template<
class T>
class Grid {
150 T get_element(
const int x,
const int y)
const
157 Grid(
const Span<T>
data,
const int side_size) : data_(
data), side_size_(side_size)
164 const float2 xy = uv * (side_size_ - 1);
166 const int x0 = int(
xy.x);
167 const int x1 = x0 >= (side_size_ - 1) ? (side_size_ - 1) : (x0 + 1);
169 const int y0 = int(
xy.y);
170 const int y1 = y0 >= (side_size_ - 1) ? (side_size_ - 1) : (y0 + 1);
172 const float u =
xy.x - x0;
173 const float v =
xy.y - y0;
175 return interp_bilinear_quad(
176 u,
v, get_element(x0, y0), get_element(x1, y0), get_element(x1, y1), get_element(x0, y1));
181Grid<T> get_subdiv_ccg_grid(
const SubdivCCG &subdiv_ccg,
const int grid_index,
const Span<T>
data)
187float3 sample_position_on_subdiv_ccg(
const SubdivCCG &subdiv_ccg,
188 const int grid_index,
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);
196float3 sample_normal_on_subdiv_ccg(
const SubdivCCG &subdiv_ccg,
197 const int grid_index,
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);
214 Span<float3> vert_positions;
215 Span<float3> vert_normals;
217 Span<int> corner_verts;
218 Span<int3> corner_tris;
219 Span<float3> corner_normals;
223 OffsetIndices<int> faces;
224 Span<float3> face_normals;
225 VArraySpan<bool> sharp_faces;
227 VArraySpan<float2> uv_map;
229 VArraySpan<int> material_indices;
231 MeshArrays() =
default;
233 explicit MeshArrays(
const Mesh &mesh)
235 bke::AttributeAccessor attributes = mesh.
attributes();
239 vert_positions = mesh.vert_positions();
240 vert_normals = mesh.vert_normals();
242 corner_verts = mesh.corner_verts();
243 corner_tris = mesh.corner_tris();
244 corner_normals = mesh.corner_normals();
246 tri_faces = mesh.corner_tri_faces();
248 faces = mesh.faces();
249 face_normals = mesh.face_normals();
254 material_indices = *attributes.lookup_or_default<
int>(
260static float2 face_center_tex_uv_calc(
const MeshArrays &mesh_arrays,
const int face_index)
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];
267 return tex_uv_acc / face.size();
273static float3 face_center_smooth_normal_calc(
const MeshArrays &mesh_arrays,
const int face_index)
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]];
284 return normal_acc / face.size();
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});
301 return tangent_data[0];
305static float4 face_center_uv_tangent_calc(
const MeshArrays &mesh_arrays,
306 const Span<float4> uv_tangents,
307 const int face_index)
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];
314 return tex_uv_acc / face.size();
324 Array<float> displacement_buffer;
325 Array<char> mask_buffer;
328struct RasterizeTile {
329 ImBuf *ibuf =
nullptr;
330 ExtraBuffers *extra_buffers =
nullptr;
334struct RasterizeTriangle {
352 bool has_uv_tangents;
357 return interp_barycentric_triangle(positions, uv);
369struct RasterizeQuad {
387 bool has_uv_tangents;
391struct RasterizeResult {
399 ExtraBuffers extra_buffers;
403struct MultiresBakeResult {
404 Vector<BakedImBuf> baked_ibufs;
410 const Mesh *highres_bake_mesh =
nullptr;
419 virtual ~MultiresBaker() =
default;
421 virtual float3 bake_pixel(
const RasterizeTriangle &triangle,
424 RasterizeResult &
result)
const = 0;
426 virtual void write_pixel(
const RasterizeTile &
tile,
428 const float3 &value)
const = 0;
431 void write_pixel_to_image_buffer(ImBuf &ibuf,
const int2 &coord,
const float3 &value)
const
456static bool multiresbake_test_break(
const MultiresBakeRender &bake)
464 return *bake.
stop ||
G.is_break;
474static bool need_tangent(
const MultiresBakeRender &bake)
482static float3x3 get_from_tangent_matrix_tbn(
const RasterizeTriangle &triangle,
485 if (!triangle.has_uv_tangents) {
489 const float u = bary_uv.
x;
490 const float v = bary_uv.
y;
491 const float w = 1 - u -
v;
493 const float3 &no0 = triangle.normals[0];
494 const float3 &no1 = triangle.normals[1];
495 const float3 &no2 = triangle.normals[2];
497 const float4 &tang0 = triangle.uv_tangents[0];
498 const float4 &tang1 = triangle.uv_tangents[1];
499 const float4 &tang2 = triangle.uv_tangents[2];
503 const float sign = (tang0.
w * u + tang1.
w *
v + tang2.
w *
w) < 0 ? (-1.0f) : 1.0f;
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;
518static float3x3 get_to_tangent_matrix_tbn(
const RasterizeTriangle &triangle,
const float2 &bary_uv)
520 const float3x3 from_tangent = get_from_tangent_matrix_tbn(triangle, bary_uv);
526static float3x3 get_to_tangent_matrix_tnb(
const RasterizeTriangle &triangle,
const float2 &bary_uv)
528 float3x3 from_tangent = get_from_tangent_matrix_tbn(triangle, bary_uv);
529 std::swap(from_tangent.y, from_tangent.z);
539static void flush_pixel(
const MultiresBaker &baker,
540 const RasterizeTile &
tile,
541 const RasterizeTriangle &triangle,
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);
552 const float3 baked_pixel = baker.bake_pixel(triangle, bary_uv, grid_uv,
result);
553 baker.write_pixel(
tile,
int2(
x,
y), baked_pixel);
556static void set_rast_triangle(
const MultiresBaker &baker,
557 const RasterizeTile &
tile,
558 const RasterizeTriangle &triangle,
563 const int w =
tile.ibuf->
x;
564 const int h =
tile.ibuf->
y;
575static void rasterize_half(
const MultiresBaker &baker,
576 const RasterizeTile &
tile,
577 const RasterizeTriangle &triangle,
584 const bool is_mid_right,
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;
592 if (y1_in <= 0 || y0_in >= h) {
596 const int y0 = y0_in < 0 ? 0 : y0_in;
597 const int y1 = y1_in >= h ? h : y1_in;
599 for (
int y = y0;
y < y1;
y++) {
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;
607 int iXl = int(
ceilf(x_l));
608 int iXr = int(
ceilf(x_r));
610 if (iXr > 0 && iXl <
w) {
611 iXl = iXl < 0 ? 0 : iXl;
612 iXr = iXr >=
w ?
w : iXr;
614 for (
int x = iXl;
x < iXr;
x++) {
621static void rasterize_triangle(
const MultiresBaker &baker,
622 const RasterizeTile &
tile,
623 const RasterizeTriangle &triangle,
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];
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;
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))
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);
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);
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);
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));
665 baker,
tile, triangle, p_low, p_mid, p_low, p_high, ylo, yhi_beg, is_mid_right,
result);
667 baker,
tile, triangle, p_mid, p_high, p_low, p_high, yhi_beg, yhi, is_mid_right,
result);
670static void rasterize_quad(
const MultiresBaker &baker,
671 const RasterizeTile &
tile,
672 const RasterizeQuad &
quad,
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;
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];
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];
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];
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];
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];
704 rasterize_triangle(baker,
tile, triangle,
result);
714class MultiresDisplacementBaker :
public MultiresBaker {
715 const SubdivCCG &high_subdiv_ccg_;
718 MultiresDisplacementBaker(
const SubdivCCG &subdiv_ccg,
720 ExtraBuffers &extra_buffers)
721 : high_subdiv_ccg_(subdiv_ccg)
724 extra_buffers.displacement_buffer.fill(0);
727 float3 bake_pixel(
const RasterizeTriangle &triangle,
730 RasterizeResult &
result)
const override
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);
737 const float length =
math::dot(bake_level_normal, (high_level_position - bake_level_position));
745 void write_pixel(
const RasterizeTile &
tile,
747 const float3 &value)
const override
749 const ImBuf &ibuf = *
tile.ibuf;
752 tile.extra_buffers->displacement_buffer[pixel] = value.
x;
754 write_pixel_to_image_buffer(*
tile.ibuf, coord, value);
758class MultiresVectorDisplacementBaker :
public MultiresBaker {
759 const SubdivCCG &high_subdiv_ccg_;
763 MultiresVectorDisplacementBaker(
const SubdivCCG &subdiv_ccg,
const eBakeSpace space)
764 : high_subdiv_ccg_(subdiv_ccg), space_(space)
768 float3 bake_pixel(
const RasterizeTriangle &triangle,
771 RasterizeResult & )
const override
773 const float3 bake_level_position = triangle.get_position(bary_uv);
775 const float3 high_level_position = sample_position_on_subdiv_ccg(
776 high_subdiv_ccg_, triangle.grid_index, grid_uv);
778 const float3 displacement = high_level_position - bake_level_position;
781 const float3x3 to_tangent = get_to_tangent_matrix_tnb(triangle, bary_uv);
782 return to_tangent * displacement;
788 void write_pixel(
const RasterizeTile &
tile,
790 const float3 &value)
const override
792 write_pixel_to_image_buffer(*
tile.ibuf, coord, value);
802class MultiresNormalsBaker :
public MultiresBaker {
803 const SubdivCCG &subdiv_ccg_;
806 explicit MultiresNormalsBaker(
const SubdivCCG &subdiv_ccg) : subdiv_ccg_(subdiv_ccg) {}
808 float3 bake_pixel(
const RasterizeTriangle &triangle,
811 RasterizeResult & )
const override
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);
818 void write_pixel(
const RasterizeTile &
tile,
820 const float3 &value)
const override
822 write_pixel_to_image_buffer(*
tile.ibuf, coord, value);
832static void initialize_images(MultiresBakeRender &bake)
849static std::unique_ptr<MultiresBaker> create_baker(
const MultiresBakeRender &bake,
850 const SubdivCCG &subdiv_ccg,
852 ExtraBuffers &extra_buffers)
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,
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,
877 const IndexRange &face = mesh_arrays.faces[face_index];
878 const Span<int> face_verts = mesh_arrays.corner_verts.slice(face);
892 quad.tex_uvs[0] = face_center_tex_uv_calc(mesh_arrays, face_index) -
tile.uv_offset;
897 quad.is_flat = mesh_arrays.sharp_faces[face_index];
899 quad.normals[0] = mesh_arrays.face_normals[face_index];
902 quad.normals[0] = face_center_smooth_normal_calc(mesh_arrays, face_index);
906 if (
quad.has_uv_tangents) {
907 quad.uv_tangents[0] = face_center_uv_tangent_calc(mesh_arrays, uv_tangents, face_index);
910 for (
const int corner : face) {
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]];
920 quad.grid_index = corner;
922 quad.tex_uvs[1] = (mesh_arrays.uv_map[corner] + mesh_arrays.uv_map[next_corner]) * 0.5f -
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 -
928 quad.positions[1] = (position + next_position) * 0.5f;
929 quad.positions[2] = position;
930 quad.positions[3] = (prev_position + position) * 0.5f;
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]];
946 quad.normals[1] = (normal + next_normal) * 0.5f;
947 quad.normals[2] = normal;
948 quad.normals[3] = (prev_normal + normal) * 0.5f;
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];
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;
965static void bake_single_image_to_base_mesh(MultiresBakeRender &bake,
966 const Mesh &bake_level_mesh,
967 const SubdivCCG &subdiv_ccg,
971 ExtraBuffers &extra_buffers,
972 MultiresBakeResult &
result)
974 std::unique_ptr<MultiresBaker> baker = create_baker(bake, subdiv_ccg, ibuf, extra_buffers);
979 MeshArrays mesh_arrays(bake_level_mesh);
980 Array<float4> uv_tangents;
981 if (need_tangent(bake)) {
987 tile.extra_buffers = &extra_buffers;
988 tile.uv_offset = get_tile_uv(image, image_tile);
992 std::atomic<int> num_baked_faces = 0;
994 for (const int64_t face_index : range) {
995 if (multiresbake_test_break(bake)) {
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) {
1006 RasterizeResult rasterize_result;
1007 rasterize_base_face(*baker, tile, mesh_arrays, uv_tangents, face_index, rasterize_result);
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;
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;
1021 BLI_spin_unlock(&spin_lock);
1038static Array<GridCoord> get_subdivided_corner_grid_coords(subdiv::Subdiv &subdiv,
1039 const Mesh &coarse_mesh,
1042 struct SubdividedCornerGridCoordData {
1043 MeshArrays coarse_mesh_arrays;
1044 Array<GridCoord> corner_grid_coords;
1047 subdiv::ToMeshSettings mesh_settings;
1048 mesh_settings.resolution = (1 << level) + 1;
1050 SubdividedCornerGridCoordData
data;
1051 data.coarse_mesh_arrays = MeshArrays(coarse_mesh);
1053 subdiv::ForeachContext foreach_context;
1054 foreach_context.user_data = &
data;
1056 foreach_context.topology_info = [](
const subdiv::ForeachContext *
context,
1059 const int num_corners,
1061 const int * ) ->
bool {
1062 SubdividedCornerGridCoordData *
data =
static_cast<SubdividedCornerGridCoordData *
>(
1064 data->corner_grid_coords.reinitialize(num_corners);
1068 foreach_context.loop = [](
const subdiv::ForeachContext *
context,
1074 const int coarse_face_index,
1075 const int coarse_corner,
1076 const int subdiv_corner_index,
1079 SubdividedCornerGridCoordData *
data =
static_cast<SubdividedCornerGridCoordData *
>(
1083 const IndexRange coarse_face =
data->coarse_mesh_arrays.faces[coarse_face_index];
1085 GridCoord &corner_grid_coord =
data->corner_grid_coords[subdiv_corner_index];
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));
1093 corner_grid_coord.uv = subdiv::ptex_face_uv_to_grid_uv(ptex_uv);
1099 return data.corner_grid_coords;
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,
1110 const IndexRange &face = mesh_arrays.faces[face_index];
1120 quad.is_flat = mesh_arrays.sharp_faces[face_index];
1122 quad.grid_index = corner_grid_coords[face.
start()].grid_index;
1124 for (
int i = 0;
i < 4; ++
i) {
1125 const int corner = face[
i];
1126 const int vertex = mesh_arrays.corner_verts[corner];
1128 BLI_assert(corner_grid_coords[corner].grid_index ==
quad.grid_index);
1129 quad.grid_uvs[
i] = corner_grid_coords[corner].uv;
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];
1137 if (
quad.has_uv_tangents) {
1138 quad.uv_tangents[
i] = uv_tangents[corner];
1143 quad.normals[0] = mesh_arrays.face_normals[face_index];
1152static void bake_single_image_to_subdivided_mesh(MultiresBakeRender &bake,
1153 const Mesh &bake_level_mesh,
1154 const SubdivCCG &subdiv_ccg,
1158 ExtraBuffers &extra_buffers,
1159 MultiresBakeResult &
result)
1161 std::unique_ptr<MultiresBaker> baker = create_baker(bake, subdiv_ccg, ibuf, extra_buffers);
1166 MeshArrays mesh_arrays(bake_level_mesh);
1167 Array<float4> uv_tangents;
1168 if (need_tangent(bake)) {
1174 tile.extra_buffers = &extra_buffers;
1175 tile.uv_offset = get_tile_uv(image, image_tile);
1177 const Array<GridCoord> corner_grid_coords = get_subdivided_corner_grid_coords(
1182 std::atomic<int> num_baked_faces = 0;
1184 for (const int64_t face_index : range) {
1185 if (multiresbake_test_break(bake)) {
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) {
1196 RasterizeResult rasterize_result;
1197 rasterize_subdivided_face(*baker,
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;
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;
1217 BLI_spin_unlock(&spin_lock);
1233static const Mesh *create_highres_mesh(
const Mesh &bake_level_mesh,
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;
1243 subdiv::Settings subdiv_settings;
1245 subdiv::Subdiv *subdiv = subdiv::update_from_mesh(
nullptr, &subdiv_settings, &bake_level_mesh);
1247 subdiv::ToMeshSettings mesh_settings;
1248 mesh_settings.resolution = (1 << subdivide_level) + 1;
1250 Mesh *
result = subdiv::subdiv_to_mesh(subdiv, &mesh_settings, &bake_level_mesh);
1252 subdiv::free(subdiv);
1259 subdiv::Subdiv &subdiv,
1261 const Mesh &base_mesh,
1262 const Mesh &bake_level_mesh,
1263 const Mesh &highres_bake_mesh)
1267 if (multires_modifier.
lvl == 0) {
1269 return get_subdivided_corner_grid_coords(
1270 subdiv, bake_level_mesh, multires_modifier.
totlvl - multires_modifier.
lvl);
1290 struct HighresCornerGridCoordData {
1291 MeshArrays bake_level_mesh_arrays;
1292 Array<GridCoord> bake_level_corner_grid_coords;
1294 Array<GridCoord> corner_grid_coords;
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;
1301 subdiv::ToMeshSettings mesh_settings;
1302 mesh_settings.resolution = (1 << subdivide_level) + 1;
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);
1309 subdiv::ForeachContext foreach_context;
1310 foreach_context.user_data = &
data;
1312 foreach_context.topology_info = [](
const subdiv::ForeachContext *
context,
1315 const int num_corners,
1317 const int * ) ->
bool {
1318 HighresCornerGridCoordData *
data =
static_cast<HighresCornerGridCoordData *
>(
1320 data->corner_grid_coords.reinitialize(num_corners);
1324 foreach_context.loop = [](
const subdiv::ForeachContext *
context,
1330 const int bake_level_face_index,
1332 const int highres_corner_index,
1335 HighresCornerGridCoordData *
data =
static_cast<HighresCornerGridCoordData *
>(
1338 const Span<GridCoord> bake_level_corner_grid_coords =
data->bake_level_corner_grid_coords;
1340 const IndexRange bake_level_face =
data->bake_level_mesh_arrays.faces[bake_level_face_index];
1343 const int bake_level_face_start = bake_level_face.
start();
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(
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);
1357 bake_level_corner_grid_coords[bake_level_face_start + 1].grid_index);
1359 bake_level_corner_grid_coords[bake_level_face_start + 2].grid_index);
1361 bake_level_corner_grid_coords[bake_level_face_start + 3].grid_index);
1367 return data.corner_grid_coords;
1371 const Mesh &bake_level_mesh,
1376 ExtraBuffers &extra_buffers,
1377 MultiresBakeResult &
result)
1379 std::unique_ptr<MultiresBaker> baker = create_baker(
bake, subdiv_ccg, ibuf, extra_buffers);
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;
1390 const Array<GridCoord> corner_grid_coords = get_highres_mesh_loop_grid_coords(
1392 *
bake.multires_modifier,
1395 *highres_bake_mesh);
1397 MeshArrays mesh_arrays(*highres_bake_mesh);
1399 if (need_tangent(
bake)) {
1405 tile.extra_buffers = &extra_buffers;
1406 tile.uv_offset = get_tile_uv(image, image_tile);
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)) {
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) {
1424 RasterizeResult rasterize_result;
1425 rasterize_subdivided_face(*baker,
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;
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;
1445 BLI_spin_unlock(&spin_lock);
1458 const Mesh &bake_level_mesh,
1463 ExtraBuffers &extra_buffers,
1464 MultiresBakeResult &
result)
1467 !
bake.use_low_resolution_mesh &&
1468 bake.multires_modifier->lvl !=
bake.multires_modifier->totlvl)
1470 bake_single_image_displacement(
1471 bake, bake_level_mesh, subdiv_ccg, image, image_tile, ibuf, extra_buffers,
result);
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);
1481 bake_single_image_to_subdivided_mesh(
1482 bake, bake_level_mesh, subdiv_ccg, image, image_tile, ibuf, extra_buffers,
result);
1486 const Mesh &bake_level_mesh,
1488 MultiresBakeResult &
result)
1497 if (ibuf && ibuf->
x > 0 && ibuf->
y > 0) {
1498 result.baked_ibufs.append({});
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);
1505 ExtraBuffers &extra_buffers = baked_ibuf.extra_buffers;
1506 extra_buffers.mask_buffer.reinitialize(
int64_t(ibuf->
y) * ibuf->
x);
1510 bake, bake_level_mesh, subdiv_ccg, *image, *image_tile, *ibuf, extra_buffers,
result);
1522static void bake_ibuf_normalize_displacement(
ImBuf &ibuf,
1525 const float displacement_min,
1526 const float displacement_max)
1528 const float *current_displacement = displacement.
data();
1529 const char *current_mask =
mask.data();
1532 if (max_distance <= 1e-5f) {
1533 const float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
1540 for (
size_t i = 0;
i < ibuf_pixel_count;
i++) {
1542 const float normalized_displacement = (*current_displacement + max_distance) /
1549 fp[0] = fp[1] = fp[2] = normalized_displacement;
1560 current_displacement++;
1565static void bake_ibuf_filter(
ImBuf &ibuf,
1567 const Mesh &bake_level_mesh,
1576 switch (margin_type) {
1581 &ibuf,
mask.data(), margin, &bake_level_mesh, active_uv_map, uv_offset);
1605 const Mesh &bake_level_mesh,
1606 MultiresBakeResult &
result)
1610 for (BakedImBuf &baked_ibuf :
result.baked_ibufs) {
1611 Image *image = baked_ibuf.image;
1612 ImBuf *ibuf = baked_ibuf.ibuf;
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,
1622 bake_ibuf_filter(*ibuf,
1623 baked_ibuf.extra_buffers.mask_buffer,
1626 bake.bake_margin_type,
1627 baked_ibuf.uv_offset);
1647static subdiv::Subdiv *create_subdiv(
const Mesh &mesh,
1650 subdiv::Settings subdiv_settings;
1652 subdiv::Subdiv *subdiv = subdiv::update_from_mesh(
nullptr, &subdiv_settings, &mesh);
1653 subdiv::displacement_attach_from_multires(subdiv, &mesh, &multires_modifier);
1656 if (!subdiv::eval_begin_from_mesh(subdiv, &mesh, subdiv::SUBDIV_EVALUATOR_TYPE_CPU)) {
1657 subdiv::free(subdiv);
1660 subdiv::eval_init_displacement(subdiv);
1665static std::unique_ptr<SubdivCCG> create_subdiv_ccg(
const Mesh &mesh,
1668 subdiv::Subdiv *subdiv = create_subdiv(mesh, multires_modifier);
1681static Mesh *create_bake_level_mesh(
const Mesh &base_mesh,
1684 subdiv::Subdiv *subdiv = create_subdiv(base_mesh, multires_modifier);
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);
1706 std::unique_ptr<SubdivCCG> subdiv_ccg = create_subdiv_ccg(*
bake.base_mesh,
1707 *
bake.multires_modifier);
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);
1714 MultiresBakeResult
result;
1715 initialize_images(
bake);
1716 bake_images(
bake, *bake_level_mesh, *subdiv_ccg,
result);
1718 const Mesh *filter_mesh =
result.highres_bake_mesh ?
result.highres_bake_mesh : bake_level_mesh;
1721 if (
result.highres_bake_mesh &&
result.highres_bake_mesh != bake_level_mesh) {
1724 if (bake_level_mesh !=
bake.base_mesh) {
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()
#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])
pthread_spinlock_t SpinLock
void BLI_spin_init(SpinLock *spin)
void BLI_spin_end(SpinLock *spin)
#define UNUSED_VARS_NDEBUG(...)
void DEG_id_tag_update(ID *id, unsigned int flags)
struct ImageTile ImageTile
@ R_BAKE_VECTOR_DISPLACEMENT
void IMB_rectfill_alpha(ImBuf *ibuf, float value)
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])
void IMB_filter_extend(ImBuf *ibuf, char *mask, int filter)
@ IB_DISPLAY_BUFFER_INVALID
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
constexpr int64_t size() const
constexpr int64_t start() const
constexpr T * data() const
constexpr bool is_empty() const
blender::gpu::Batch * quad
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)
void RE_multires_bake_images(MultiresBakeRender &bake)
int face_corner_prev(const IndexRange face, const int corner)
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)
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)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
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
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
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
static MatBase identity()
void RE_generate_texturemargin_adjacentfaces(ImBuf *ibuf, char *mask, const int margin, const Mesh *mesh, blender::StringRef uv_layer, const float uv_offset[2])