tornavis/source/blender/blenkernel/BKE_image_wrappers.hh

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

91 lines
2.3 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup imbuf
*/
#pragma once
#include "DNA_image_types.h"
#include "BLI_math_color.h"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
2024-01-18 21:50:23 +01:00
#include "IMB_imbuf_types.hh"
Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh Fix seam bleeding of non-manifold sections of the mesh, by copying pixels that are covered by the brush stroke. As manifold parts are already handled, the pixel copying solution can be very straight forward. * Pixels are copied from the same tile. So we don't need a mechanism that copies and merges pixels from other tiles. * Pixels are copied from the closest pixel that is being painted on. We don't need to consider that that pixel can be in different areas of the tile. When we copy a pixel, we find the closest pixel in UV space that is being directly influenced by a paint brush. We also look for the second closest pixel, which is still a neighbor from the closest pixel. We can mix both pixels together and store it in the destination. A mix factor is calculated using the closest non manifold edge as a guidance. The result of this step is a list of copy and mix commands that can be executed to fix the seam bleeding for non-manifold sections of the mesh. | Destination | Source 1 | Source 2 | Mix factor | | ----------- | -------- | -------- | ---------- | | 1780,1811 | 1780,1810| 1779,1810| 0.000000 | | 1781,1811 | 1781,1810| 1782,1811| 0.168627 | | 1828,1811 | 1828,1810| 1827,1811| 0.156863 | | 1829,1811 | 1829,1810| 1828,1810| 0.188235 | | 1830,1811 | 1830,1810| 1829,1810| 0.188235 | | 1831,1811 | 1831,1810| 1830,1810| 0.188235 | | 1832,1811 | 1832,1810| 1831,1810| 0.188235 | | 1833,1811 | 1832,1810| 1832,1810| 0.000000 | In the end we go over this list mix the sources and store the result at the destination. ``` tile_buffer[destination] = mix(tile_buffer[source_1], tile_buffer[source_2], mix_factor); ``` **Encoding** When using a large textures or large seam margins this table can grow large and reduce performance as data retrieval is slower, than the operations it has to perform. To improve the performance we encode the table so less data retrieval needs to be done. * first `DeltaCopyPixelCommand` is delta encoded from `CopyPixelGroup#start_destination` and `start_source_1`. The others are delta encoded from the previous `DeltaCopyPixelCommand`. * For performance reasons PixelCopyGroup#pixels are ordered from destination (left to right) for each row a new group would be created as the delta encoding most likely doesn't fit. When pixels cannot be delta encoded a new group will also be created. **Compression rate** When using Suzanne the compression rate is around 36% when using a seam margin of 4 pixels. The compression rate may vary depending on seam margin and model. For Suzanne the compression rate was around 36% for various resolutions. | Resolution | Margin | Decoded size | Encoded size | Compression | | ---------- | ------ | ------------ | ------------ | ----------- | | 2048x2048 | 4 px | 353.052 | 128.101 | 36% | | 4096x4096 | 4 px | 700.140 | 255.137 | 36% | | 8192x8192 | 4 px | 1.419.320 | 513.802 | 36% | | 2048x2048 | 8 px | 721.084 | 193.629 | 26% | | 4096x4096 | 8 px | 1.444.968 | 388.110 | 26% | Pull Request: https://projects.blender.org/blender/blender/pulls/105336
2023-03-09 16:11:01 +01:00
namespace blender::bke::image {
/** Type to use for UDIM tile numbers (1001). */
using TileNumber = int32_t;
struct ImageTileWrapper {
ImageTile *image_tile;
ImageTileWrapper(ImageTile *image_tile) : image_tile(image_tile) {}
TileNumber get_tile_number() const
{
return image_tile->tile_number;
}
int2 get_tile_offset() const
{
return int2(get_tile_x_offset(), get_tile_y_offset());
}
int get_tile_x_offset() const
{
TileNumber tile_number = get_tile_number();
return (tile_number - 1001) % 10;
}
int get_tile_y_offset() const
{
TileNumber tile_number = get_tile_number();
return (tile_number - 1001) / 10;
}
};
Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh Fix seam bleeding of non-manifold sections of the mesh, by copying pixels that are covered by the brush stroke. As manifold parts are already handled, the pixel copying solution can be very straight forward. * Pixels are copied from the same tile. So we don't need a mechanism that copies and merges pixels from other tiles. * Pixels are copied from the closest pixel that is being painted on. We don't need to consider that that pixel can be in different areas of the tile. When we copy a pixel, we find the closest pixel in UV space that is being directly influenced by a paint brush. We also look for the second closest pixel, which is still a neighbor from the closest pixel. We can mix both pixels together and store it in the destination. A mix factor is calculated using the closest non manifold edge as a guidance. The result of this step is a list of copy and mix commands that can be executed to fix the seam bleeding for non-manifold sections of the mesh. | Destination | Source 1 | Source 2 | Mix factor | | ----------- | -------- | -------- | ---------- | | 1780,1811 | 1780,1810| 1779,1810| 0.000000 | | 1781,1811 | 1781,1810| 1782,1811| 0.168627 | | 1828,1811 | 1828,1810| 1827,1811| 0.156863 | | 1829,1811 | 1829,1810| 1828,1810| 0.188235 | | 1830,1811 | 1830,1810| 1829,1810| 0.188235 | | 1831,1811 | 1831,1810| 1830,1810| 0.188235 | | 1832,1811 | 1832,1810| 1831,1810| 0.188235 | | 1833,1811 | 1832,1810| 1832,1810| 0.000000 | In the end we go over this list mix the sources and store the result at the destination. ``` tile_buffer[destination] = mix(tile_buffer[source_1], tile_buffer[source_2], mix_factor); ``` **Encoding** When using a large textures or large seam margins this table can grow large and reduce performance as data retrieval is slower, than the operations it has to perform. To improve the performance we encode the table so less data retrieval needs to be done. * first `DeltaCopyPixelCommand` is delta encoded from `CopyPixelGroup#start_destination` and `start_source_1`. The others are delta encoded from the previous `DeltaCopyPixelCommand`. * For performance reasons PixelCopyGroup#pixels are ordered from destination (left to right) for each row a new group would be created as the delta encoding most likely doesn't fit. When pixels cannot be delta encoded a new group will also be created. **Compression rate** When using Suzanne the compression rate is around 36% when using a seam margin of 4 pixels. The compression rate may vary depending on seam margin and model. For Suzanne the compression rate was around 36% for various resolutions. | Resolution | Margin | Decoded size | Encoded size | Compression | | ---------- | ------ | ------------ | ------------ | ----------- | | 2048x2048 | 4 px | 353.052 | 128.101 | 36% | | 4096x4096 | 4 px | 700.140 | 255.137 | 36% | | 8192x8192 | 4 px | 1.419.320 | 513.802 | 36% | | 2048x2048 | 8 px | 721.084 | 193.629 | 26% | | 4096x4096 | 8 px | 1.444.968 | 388.110 | 26% | Pull Request: https://projects.blender.org/blender/blender/pulls/105336
2023-03-09 16:11:01 +01:00
template<typename T, int Channels = 4> struct ImageBufferAccessor {
static_assert(std::is_same_v<T, int> || std::is_same_v<T, float4>);
ImBuf &image_buffer;
ImageBufferAccessor(ImBuf &image_buffer) : image_buffer(image_buffer) {}
Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh Fix seam bleeding of non-manifold sections of the mesh, by copying pixels that are covered by the brush stroke. As manifold parts are already handled, the pixel copying solution can be very straight forward. * Pixels are copied from the same tile. So we don't need a mechanism that copies and merges pixels from other tiles. * Pixels are copied from the closest pixel that is being painted on. We don't need to consider that that pixel can be in different areas of the tile. When we copy a pixel, we find the closest pixel in UV space that is being directly influenced by a paint brush. We also look for the second closest pixel, which is still a neighbor from the closest pixel. We can mix both pixels together and store it in the destination. A mix factor is calculated using the closest non manifold edge as a guidance. The result of this step is a list of copy and mix commands that can be executed to fix the seam bleeding for non-manifold sections of the mesh. | Destination | Source 1 | Source 2 | Mix factor | | ----------- | -------- | -------- | ---------- | | 1780,1811 | 1780,1810| 1779,1810| 0.000000 | | 1781,1811 | 1781,1810| 1782,1811| 0.168627 | | 1828,1811 | 1828,1810| 1827,1811| 0.156863 | | 1829,1811 | 1829,1810| 1828,1810| 0.188235 | | 1830,1811 | 1830,1810| 1829,1810| 0.188235 | | 1831,1811 | 1831,1810| 1830,1810| 0.188235 | | 1832,1811 | 1832,1810| 1831,1810| 0.188235 | | 1833,1811 | 1832,1810| 1832,1810| 0.000000 | In the end we go over this list mix the sources and store the result at the destination. ``` tile_buffer[destination] = mix(tile_buffer[source_1], tile_buffer[source_2], mix_factor); ``` **Encoding** When using a large textures or large seam margins this table can grow large and reduce performance as data retrieval is slower, than the operations it has to perform. To improve the performance we encode the table so less data retrieval needs to be done. * first `DeltaCopyPixelCommand` is delta encoded from `CopyPixelGroup#start_destination` and `start_source_1`. The others are delta encoded from the previous `DeltaCopyPixelCommand`. * For performance reasons PixelCopyGroup#pixels are ordered from destination (left to right) for each row a new group would be created as the delta encoding most likely doesn't fit. When pixels cannot be delta encoded a new group will also be created. **Compression rate** When using Suzanne the compression rate is around 36% when using a seam margin of 4 pixels. The compression rate may vary depending on seam margin and model. For Suzanne the compression rate was around 36% for various resolutions. | Resolution | Margin | Decoded size | Encoded size | Compression | | ---------- | ------ | ------------ | ------------ | ----------- | | 2048x2048 | 4 px | 353.052 | 128.101 | 36% | | 4096x4096 | 4 px | 700.140 | 255.137 | 36% | | 8192x8192 | 4 px | 1.419.320 | 513.802 | 36% | | 2048x2048 | 8 px | 721.084 | 193.629 | 26% | | 4096x4096 | 8 px | 1.444.968 | 388.110 | 26% | Pull Request: https://projects.blender.org/blender/blender/pulls/105336
2023-03-09 16:11:01 +01:00
float4 read_pixel(const int2 coordinate)
{
if constexpr ((std::is_same_v<T, float4>)) {
int offset = (coordinate.y * image_buffer.x + coordinate.x) * Channels;
return float4(&image_buffer.float_buffer.data[offset]);
Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh Fix seam bleeding of non-manifold sections of the mesh, by copying pixels that are covered by the brush stroke. As manifold parts are already handled, the pixel copying solution can be very straight forward. * Pixels are copied from the same tile. So we don't need a mechanism that copies and merges pixels from other tiles. * Pixels are copied from the closest pixel that is being painted on. We don't need to consider that that pixel can be in different areas of the tile. When we copy a pixel, we find the closest pixel in UV space that is being directly influenced by a paint brush. We also look for the second closest pixel, which is still a neighbor from the closest pixel. We can mix both pixels together and store it in the destination. A mix factor is calculated using the closest non manifold edge as a guidance. The result of this step is a list of copy and mix commands that can be executed to fix the seam bleeding for non-manifold sections of the mesh. | Destination | Source 1 | Source 2 | Mix factor | | ----------- | -------- | -------- | ---------- | | 1780,1811 | 1780,1810| 1779,1810| 0.000000 | | 1781,1811 | 1781,1810| 1782,1811| 0.168627 | | 1828,1811 | 1828,1810| 1827,1811| 0.156863 | | 1829,1811 | 1829,1810| 1828,1810| 0.188235 | | 1830,1811 | 1830,1810| 1829,1810| 0.188235 | | 1831,1811 | 1831,1810| 1830,1810| 0.188235 | | 1832,1811 | 1832,1810| 1831,1810| 0.188235 | | 1833,1811 | 1832,1810| 1832,1810| 0.000000 | In the end we go over this list mix the sources and store the result at the destination. ``` tile_buffer[destination] = mix(tile_buffer[source_1], tile_buffer[source_2], mix_factor); ``` **Encoding** When using a large textures or large seam margins this table can grow large and reduce performance as data retrieval is slower, than the operations it has to perform. To improve the performance we encode the table so less data retrieval needs to be done. * first `DeltaCopyPixelCommand` is delta encoded from `CopyPixelGroup#start_destination` and `start_source_1`. The others are delta encoded from the previous `DeltaCopyPixelCommand`. * For performance reasons PixelCopyGroup#pixels are ordered from destination (left to right) for each row a new group would be created as the delta encoding most likely doesn't fit. When pixels cannot be delta encoded a new group will also be created. **Compression rate** When using Suzanne the compression rate is around 36% when using a seam margin of 4 pixels. The compression rate may vary depending on seam margin and model. For Suzanne the compression rate was around 36% for various resolutions. | Resolution | Margin | Decoded size | Encoded size | Compression | | ---------- | ------ | ------------ | ------------ | ----------- | | 2048x2048 | 4 px | 353.052 | 128.101 | 36% | | 4096x4096 | 4 px | 700.140 | 255.137 | 36% | | 8192x8192 | 4 px | 1.419.320 | 513.802 | 36% | | 2048x2048 | 8 px | 721.084 | 193.629 | 26% | | 4096x4096 | 8 px | 1.444.968 | 388.110 | 26% | Pull Request: https://projects.blender.org/blender/blender/pulls/105336
2023-03-09 16:11:01 +01:00
}
if constexpr ((std::is_same_v<T, int>)) {
int offset = (coordinate.y * image_buffer.x + coordinate.x);
float4 result;
rgba_uchar_to_float(
result,
static_cast<uchar *>(static_cast<void *>(&image_buffer.byte_buffer.data[offset])));
Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh Fix seam bleeding of non-manifold sections of the mesh, by copying pixels that are covered by the brush stroke. As manifold parts are already handled, the pixel copying solution can be very straight forward. * Pixels are copied from the same tile. So we don't need a mechanism that copies and merges pixels from other tiles. * Pixels are copied from the closest pixel that is being painted on. We don't need to consider that that pixel can be in different areas of the tile. When we copy a pixel, we find the closest pixel in UV space that is being directly influenced by a paint brush. We also look for the second closest pixel, which is still a neighbor from the closest pixel. We can mix both pixels together and store it in the destination. A mix factor is calculated using the closest non manifold edge as a guidance. The result of this step is a list of copy and mix commands that can be executed to fix the seam bleeding for non-manifold sections of the mesh. | Destination | Source 1 | Source 2 | Mix factor | | ----------- | -------- | -------- | ---------- | | 1780,1811 | 1780,1810| 1779,1810| 0.000000 | | 1781,1811 | 1781,1810| 1782,1811| 0.168627 | | 1828,1811 | 1828,1810| 1827,1811| 0.156863 | | 1829,1811 | 1829,1810| 1828,1810| 0.188235 | | 1830,1811 | 1830,1810| 1829,1810| 0.188235 | | 1831,1811 | 1831,1810| 1830,1810| 0.188235 | | 1832,1811 | 1832,1810| 1831,1810| 0.188235 | | 1833,1811 | 1832,1810| 1832,1810| 0.000000 | In the end we go over this list mix the sources and store the result at the destination. ``` tile_buffer[destination] = mix(tile_buffer[source_1], tile_buffer[source_2], mix_factor); ``` **Encoding** When using a large textures or large seam margins this table can grow large and reduce performance as data retrieval is slower, than the operations it has to perform. To improve the performance we encode the table so less data retrieval needs to be done. * first `DeltaCopyPixelCommand` is delta encoded from `CopyPixelGroup#start_destination` and `start_source_1`. The others are delta encoded from the previous `DeltaCopyPixelCommand`. * For performance reasons PixelCopyGroup#pixels are ordered from destination (left to right) for each row a new group would be created as the delta encoding most likely doesn't fit. When pixels cannot be delta encoded a new group will also be created. **Compression rate** When using Suzanne the compression rate is around 36% when using a seam margin of 4 pixels. The compression rate may vary depending on seam margin and model. For Suzanne the compression rate was around 36% for various resolutions. | Resolution | Margin | Decoded size | Encoded size | Compression | | ---------- | ------ | ------------ | ------------ | ----------- | | 2048x2048 | 4 px | 353.052 | 128.101 | 36% | | 4096x4096 | 4 px | 700.140 | 255.137 | 36% | | 8192x8192 | 4 px | 1.419.320 | 513.802 | 36% | | 2048x2048 | 8 px | 721.084 | 193.629 | 26% | | 4096x4096 | 8 px | 1.444.968 | 388.110 | 26% | Pull Request: https://projects.blender.org/blender/blender/pulls/105336
2023-03-09 16:11:01 +01:00
return result;
}
return float4();
}
void write_pixel(const int2 coordinate, float4 new_value)
{
if constexpr ((std::is_same_v<T, float>)) {
int offset = (coordinate.y * image_buffer.x + coordinate.x) * Channels;
copy_v4_v4(&image_buffer.float_buffer.data[offset], new_value);
Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh Fix seam bleeding of non-manifold sections of the mesh, by copying pixels that are covered by the brush stroke. As manifold parts are already handled, the pixel copying solution can be very straight forward. * Pixels are copied from the same tile. So we don't need a mechanism that copies and merges pixels from other tiles. * Pixels are copied from the closest pixel that is being painted on. We don't need to consider that that pixel can be in different areas of the tile. When we copy a pixel, we find the closest pixel in UV space that is being directly influenced by a paint brush. We also look for the second closest pixel, which is still a neighbor from the closest pixel. We can mix both pixels together and store it in the destination. A mix factor is calculated using the closest non manifold edge as a guidance. The result of this step is a list of copy and mix commands that can be executed to fix the seam bleeding for non-manifold sections of the mesh. | Destination | Source 1 | Source 2 | Mix factor | | ----------- | -------- | -------- | ---------- | | 1780,1811 | 1780,1810| 1779,1810| 0.000000 | | 1781,1811 | 1781,1810| 1782,1811| 0.168627 | | 1828,1811 | 1828,1810| 1827,1811| 0.156863 | | 1829,1811 | 1829,1810| 1828,1810| 0.188235 | | 1830,1811 | 1830,1810| 1829,1810| 0.188235 | | 1831,1811 | 1831,1810| 1830,1810| 0.188235 | | 1832,1811 | 1832,1810| 1831,1810| 0.188235 | | 1833,1811 | 1832,1810| 1832,1810| 0.000000 | In the end we go over this list mix the sources and store the result at the destination. ``` tile_buffer[destination] = mix(tile_buffer[source_1], tile_buffer[source_2], mix_factor); ``` **Encoding** When using a large textures or large seam margins this table can grow large and reduce performance as data retrieval is slower, than the operations it has to perform. To improve the performance we encode the table so less data retrieval needs to be done. * first `DeltaCopyPixelCommand` is delta encoded from `CopyPixelGroup#start_destination` and `start_source_1`. The others are delta encoded from the previous `DeltaCopyPixelCommand`. * For performance reasons PixelCopyGroup#pixels are ordered from destination (left to right) for each row a new group would be created as the delta encoding most likely doesn't fit. When pixels cannot be delta encoded a new group will also be created. **Compression rate** When using Suzanne the compression rate is around 36% when using a seam margin of 4 pixels. The compression rate may vary depending on seam margin and model. For Suzanne the compression rate was around 36% for various resolutions. | Resolution | Margin | Decoded size | Encoded size | Compression | | ---------- | ------ | ------------ | ------------ | ----------- | | 2048x2048 | 4 px | 353.052 | 128.101 | 36% | | 4096x4096 | 4 px | 700.140 | 255.137 | 36% | | 8192x8192 | 4 px | 1.419.320 | 513.802 | 36% | | 2048x2048 | 8 px | 721.084 | 193.629 | 26% | | 4096x4096 | 8 px | 1.444.968 | 388.110 | 26% | Pull Request: https://projects.blender.org/blender/blender/pulls/105336
2023-03-09 16:11:01 +01:00
}
if constexpr ((std::is_same_v<T, int>)) {
int offset = (coordinate.y * image_buffer.x + coordinate.x);
rgba_float_to_uchar(
static_cast<uchar *>(static_cast<void *>(&image_buffer.byte_buffer.data[offset])),
new_value);
Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh Fix seam bleeding of non-manifold sections of the mesh, by copying pixels that are covered by the brush stroke. As manifold parts are already handled, the pixel copying solution can be very straight forward. * Pixels are copied from the same tile. So we don't need a mechanism that copies and merges pixels from other tiles. * Pixels are copied from the closest pixel that is being painted on. We don't need to consider that that pixel can be in different areas of the tile. When we copy a pixel, we find the closest pixel in UV space that is being directly influenced by a paint brush. We also look for the second closest pixel, which is still a neighbor from the closest pixel. We can mix both pixels together and store it in the destination. A mix factor is calculated using the closest non manifold edge as a guidance. The result of this step is a list of copy and mix commands that can be executed to fix the seam bleeding for non-manifold sections of the mesh. | Destination | Source 1 | Source 2 | Mix factor | | ----------- | -------- | -------- | ---------- | | 1780,1811 | 1780,1810| 1779,1810| 0.000000 | | 1781,1811 | 1781,1810| 1782,1811| 0.168627 | | 1828,1811 | 1828,1810| 1827,1811| 0.156863 | | 1829,1811 | 1829,1810| 1828,1810| 0.188235 | | 1830,1811 | 1830,1810| 1829,1810| 0.188235 | | 1831,1811 | 1831,1810| 1830,1810| 0.188235 | | 1832,1811 | 1832,1810| 1831,1810| 0.188235 | | 1833,1811 | 1832,1810| 1832,1810| 0.000000 | In the end we go over this list mix the sources and store the result at the destination. ``` tile_buffer[destination] = mix(tile_buffer[source_1], tile_buffer[source_2], mix_factor); ``` **Encoding** When using a large textures or large seam margins this table can grow large and reduce performance as data retrieval is slower, than the operations it has to perform. To improve the performance we encode the table so less data retrieval needs to be done. * first `DeltaCopyPixelCommand` is delta encoded from `CopyPixelGroup#start_destination` and `start_source_1`. The others are delta encoded from the previous `DeltaCopyPixelCommand`. * For performance reasons PixelCopyGroup#pixels are ordered from destination (left to right) for each row a new group would be created as the delta encoding most likely doesn't fit. When pixels cannot be delta encoded a new group will also be created. **Compression rate** When using Suzanne the compression rate is around 36% when using a seam margin of 4 pixels. The compression rate may vary depending on seam margin and model. For Suzanne the compression rate was around 36% for various resolutions. | Resolution | Margin | Decoded size | Encoded size | Compression | | ---------- | ------ | ------------ | ------------ | ----------- | | 2048x2048 | 4 px | 353.052 | 128.101 | 36% | | 4096x4096 | 4 px | 700.140 | 255.137 | 36% | | 8192x8192 | 4 px | 1.419.320 | 513.802 | 36% | | 2048x2048 | 8 px | 721.084 | 193.629 | 26% | | 4096x4096 | 8 px | 1.444.968 | 388.110 | 26% | Pull Request: https://projects.blender.org/blender/blender/pulls/105336
2023-03-09 16:11:01 +01:00
}
}
};
} // namespace blender::bke::image