Add HUD brush mask selector and fix dilation seam artifacts
- Add mask selector with previews to the brush card (data-driven from painter.brushMasks); persist activeBrushIndex with HUD layout. - Fix alpha/coverage artifacts when overpainting after load or backend switch: derive the dilation source marker from a deterministic UV island mask instead of resetting it to "unpainted" on every seed. - Import the two final brush mask textures (Brushes/). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
d62eddc518
commit
c14525a2c8
15 files changed
+1005
-14
No files matched your search
@@ -68,7 +68,7 @@ public partial class MeshPainter
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>Seeds a GPU map's display RT from canonical data (alpha = 0 = unpainted), then packs MS to final.</summary>
|
||||
/// <summary>Seeds a GPU map's display RT from canonical data (coverage alpha = UV islands), then packs MS to final.</summary>
|
||||
private void SeedGpuMap(int mi, Color32[][] canonical)
|
||||
{
|
||||
var src = (canonical != null && canonical[mi] != null && canonical[mi].Length == textureSize * textureSize)
|
||||
@@ -78,15 +78,15 @@ public partial class MeshPainter
|
||||
if (mi == MAP_MSO)
|
||||
{
|
||||
// Canonical (R=metallic, G=occlusion, A=smoothness) -> work layout
|
||||
// (R=metallic, G=smoothness, B=occlusion); alpha = coverage stays 0 (unpainted).
|
||||
// (R=metallic, G=smoothness, B=occlusion); UploadColorsToRT fills A = island coverage.
|
||||
var work = new Color32[src.Length];
|
||||
for (int i = 0; i < src.Length; i++) work[i] = new Color32(src[i].r, src[i].a, src[i].g, 0);
|
||||
UploadColorsToRT(work, gm.display, paintedAlpha: false, linear: true);
|
||||
UploadColorsToRT(work, gm.display, linear: true);
|
||||
PackMs(gm); // build the final mask RT once so the material shows the seeded values
|
||||
}
|
||||
else
|
||||
{
|
||||
UploadColorsToRT((Color32[])src.Clone(), gm.display, paintedAlpha: false, linear: gm.sRGB == false);
|
||||
UploadColorsToRT((Color32[])src.Clone(), gm.display, linear: gm.sRGB == false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,12 +125,15 @@ public partial class MeshPainter
|
||||
}
|
||||
|
||||
/// <summary>Writes Color32 data into a RenderTexture via a temporary texture.</summary>
|
||||
private void UploadColorsToRT(Color32[] colors, RenderTexture rt, bool paintedAlpha, bool linear)
|
||||
private void UploadColorsToRT(Color32[] colors, RenderTexture rt, bool linear)
|
||||
{
|
||||
var tmp = new Texture2D(textureSize, textureSize, TextureFormat.RGBA32, false, linear);
|
||||
// Alpha marks painted (255) vs unpainted (0) for the dilation pass.
|
||||
byte a = paintedAlpha ? (byte)255 : (byte)0;
|
||||
for (int i = 0; i < colors.Length; i++) colors[i].a = a;
|
||||
// Alpha is the dilation coverage marker: island texels (real content) = 255 so the
|
||||
// dilate pass keeps them; the gutter = 0 so it stays paddable. Driving this from the UV
|
||||
// islands (not a flat "unpainted") protects seeded content from the first stroke's bleed.
|
||||
var island = GetIslandMask();
|
||||
bool useMask = island.Length == colors.Length;
|
||||
for (int i = 0; i < colors.Length; i++) colors[i].a = (useMask && island[i]) ? (byte)255 : (byte)0;
|
||||
tmp.SetPixels32(colors);
|
||||
tmp.Apply(false);
|
||||
|
||||
|
||||
Reference in new issue
Block a user