Page MenuHome

Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh.
Needs ReviewPublic

Authored by Jeroen Bakker (jbakker) on Jan 10 2023, 2:21 PM.

Details

Summary

Fix seam bleeding of non-manifold sections of the mesh, by copy-ing pixels that are covered by the brush stroke.

As manifold parts are already handled, the pixel copy-ing 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.

DestinationSource 1Source 2Mix factor
1780,18111780,18101779,18100.000000
1781,18111781,18101782,18110.168627
1828,18111828,18101827,18110.156863
1829,18111829,18101828,18100.188235
1830,18111830,18101829,18100.188235
1831,18111831,18101830,18100.188235
1832,18111832,18101831,18100.188235
1833,18111832,18101832,18100.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 365 for various resolutions.

Texture resolutionSeam marginDecoded size (bytes)Encoded size (bytes)Compression rate
2048x20484 px353.052128.10136%
4096x40964 px700.140255.13736%
8192x81924 px1.419.320513.80236%
2048x20488 px721.084193.62926%
4096x40968 px1.444.968388.11026%

TODO

  • UDIM tiles aren't supported yet. This needs to be added before this patch lands.
  • Threading isn't added, but should before this patch lands.
  • TODO's have to be resolved including some performance improvements by reducing the search radius.

Diff Detail

Repository
rB Blender
Branch
temp-T101739-fix-seam-bleeding-non-manifold
Build Status
Buildable 25299
Build 25299: arc lint + arc unit

Event Timeline

  • Merge branch 'master' into temp-T101739-fix-seam-bleeding-non-manifold
  • Applied D16981 to continue development.
  • Tweaks to naming and code structure.
  • Use actual distance, not squared to find pixels.
  • Merge branch 'master' into temp-T101739-fix-seam-bleeding-non-manifold
Jeroen Bakker (jbakker) retitled this revision from Texture Painting: Fix Seam Bleeding for Non-Manifold Sections of Mesh. to Texture Painting: Fix Seam Bleeding of Non-Manifold Sections of Mesh..Fri, Jan 13, 11:15 AM
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)
  • Fix incorrect bound selection.
  • Merge branch 'master' into temp-T101739-fix-seam-bleeding-non-manifold
  • Renames structs to be more readable.
  • Use struct of arrays per tile.
  • Print compression rate per tile.
  • Improve mix factor calculation.
  • Codestyle change.
Jeroen Bakker (jbakker) requested review of this revision.Fri, Jan 13, 11:38 AM
Jeroen Bakker (jbakker) added inline comments.
source/blender/editors/sculpt_paint/sculpt_paint_image.cc
546

Perhaps only when there are a certain amount of commands.

  • Add initial UDIM support.
  • Only fix seam bleeding on tiles that are painted on.
  • Fix out of bounds access.
Jeroen Bakker (jbakker) edited the summary of this revision. (Show Details)Fri, Jan 13, 2:14 PM

I tested it for a bit and the bleeding seems to have a strange effect when it has to go in a direction that isn't strictly vertical or horizontal.

On a perfectly horizontal UV boudnary the bleeding is perfect.

But once the direction changes and there is a pixel offset, the bleeding becomes less acruate.

  • Add support for byte textures.
  • Merge branch 'master' into temp-T101739-fix-seam-bleeding-non-manifold
  • Fix out of bounds read due to naming confusion. Clamp vs isect.
  • Added post check to test if encoding and decoding gets similar results.
  • Fix incorrect search bounds when looking for second source.
  • Remove obsolete comment.
  • Enable threading during pixel copy-ing.
  • Added timeit macros, but need to use hotspot to find out what actually is happening.
  • Added easy threading.
  • Merge branch 'master' into temp-T101739-fix-seam-bleeding-non-manifold
  • Improved performance by allocating a single array and use RowViews.
  • Some minor tweaks in performance.
  • Added static + tweaks in memory access.
  • Improved performance.
  • Removed some debugging code.

@Jeroen Bakker (jbakker) I still get a crash on the same file I provided for testing.

Other things I noticed:

The non-manifold bleeding doesn't work when there's another UV island close which bleeding margin overlaps.

There are cases where the bleeding fails on an intersection between manifold and non-manifold seams.

Currently manifold parts have priority over non-manifold parts. Reason is that manifold parts can act as a source for the non-manifold parts. Your suggestion of giving them evenly space requires some more research to see how we could solve this as pixels that are used for a solution might be removed by this mechanism.

  • reuse the coverage mask that is generated during the manifold detection? Perhaps we already have the data, but we might want to store it in a more generic way so both manifold and non-manifold detection uses the same mask.

The second problem might be a short-coming of the manifold solution, at first glance I would think it is an issue there resulting in no solution. If that is the case, it should be handled as a separate issue.

  • Fix some todos.
  • Merge branch 'master' into temp-T101739-fix-seam-bleeding-non-manifold