2023-08-15 16:20:26 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2022 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2022-01-28 08:37:12 +01:00
|
|
|
|
|
|
|
/** \file
|
2022-04-04 14:00:33 +02:00
|
|
|
* \ingroup imbuf
|
2022-01-28 08:37:12 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "DNA_image_types.h"
|
|
|
|
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 10:39:20 +02:00
|
|
|
#include "BLI_math_color.h"
|
|
|
|
#include "BLI_math_vector.h"
|
2023-01-04 00:14:55 +01:00
|
|
|
#include "BLI_math_vector_types.hh"
|
2022-04-04 14:00:33 +02:00
|
|
|
|
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
|
|
|
|
2022-04-04 14:00:33 +02:00
|
|
|
namespace blender::bke::image {
|
|
|
|
|
2022-12-21 08:42:19 +01:00
|
|
|
/** Type to use for UDIM tile numbers (1001). */
|
|
|
|
using TileNumber = int32_t;
|
|
|
|
|
2022-01-28 08:37:12 +01:00
|
|
|
struct ImageTileWrapper {
|
|
|
|
ImageTile *image_tile;
|
2023-03-29 16:50:54 +02:00
|
|
|
ImageTileWrapper(ImageTile *image_tile) : image_tile(image_tile) {}
|
2022-01-28 08:37:12 +01:00
|
|
|
|
2022-12-21 08:42:19 +01:00
|
|
|
TileNumber get_tile_number() const
|
2022-01-28 08:37:12 +01:00
|
|
|
{
|
|
|
|
return image_tile->tile_number;
|
|
|
|
}
|
|
|
|
|
2022-04-04 14:00:33 +02:00
|
|
|
int2 get_tile_offset() const
|
|
|
|
{
|
|
|
|
return int2(get_tile_x_offset(), get_tile_y_offset());
|
|
|
|
}
|
|
|
|
|
2022-01-28 08:37:12 +01:00
|
|
|
int get_tile_x_offset() const
|
|
|
|
{
|
2022-12-21 08:42:19 +01:00
|
|
|
TileNumber tile_number = get_tile_number();
|
2022-01-28 08:37:12 +01:00
|
|
|
return (tile_number - 1001) % 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_tile_y_offset() const
|
|
|
|
{
|
2022-12-21 08:42:19 +01:00
|
|
|
TileNumber tile_number = get_tile_number();
|
2022-01-28 08:37:12 +01:00
|
|
|
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;
|
|
|
|
|
2023-03-29 16:50:54 +02:00
|
|
|
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;
|
2023-05-18 10:19:01 +02:00
|
|
|
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;
|
2023-05-18 10:19:01 +02:00
|
|
|
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;
|
2023-05-18 10:19:01 +02:00
|
|
|
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);
|
2023-05-18 10:19:01 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-04-04 14:00:33 +02:00
|
|
|
} // namespace blender::bke::image
|