Skip to content

Fix dark/faded Metal rendering: use premultiplied alpha blend factors#15

Merged
praeclarum merged 3 commits intomasterfrom
copilot/fix-metal-rendering-issue
Mar 30, 2026
Merged

Fix dark/faded Metal rendering: use premultiplied alpha blend factors#15
praeclarum merged 3 commits intomasterfrom
copilot/fix-metal-rendering-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 30, 2026

The fragment shader outputs premultiplied alpha (rgb * alpha, alpha) but the blend state was using SourceAlpha, causing double-multiplication by alpha and darkened output.

  • Blend factors (MetalGraphics.cs): Changed SourceRgbBlendFactor and SourceAlphaBlendFactor from SourceAlpha to One — standard premultiplied alpha over compositing.
// Before: source.rgb * source.a (double-multiplied since shader already premultiplies)
SourceRgbBlendFactor = MTLBlendFactor.SourceAlpha,
// After: source.rgb * 1 (correct — shader output is already premultiplied)
SourceRgbBlendFactor = MTLBlendFactor.One,
  • Acceptance test format mismatch (AcceptanceTests.cs): Test was creating render targets with RGBA8Unorm while the pipeline expects BGRA8Unorm. Now uses MetalGraphics.DefaultPixelFormat.

Copilot AI linked an issue Mar 30, 2026 that may be closed by this pull request
The fragment shader outputs premultiplied alpha (rgb*alpha, alpha) but
the blend state was using SourceAlpha, causing double-alpha-multiplication.
Changed source blend factors from SourceAlpha to One for correct
premultiplied alpha compositing (Porter-Duff Source Over).

Also fixed acceptance test texture format mismatch: was using RGBA8Unorm
while the pipeline expects BGRA8Unorm (DefaultPixelFormat).

Agent-Logs-Url: https://github.com/praeclarum/CrossGraphics/sessions/7b870bed-9976-46fb-86e2-060fa9acf87a

Co-authored-by: praeclarum <323548+praeclarum@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix dark/faded rendering in MetalGraphics Fix dark/faded Metal rendering: use premultiplied alpha blend factors Mar 30, 2026
Copilot AI requested a review from praeclarum March 30, 2026 16:30
Comment thread atests/AcceptanceTests.cs
{
var renderPassDescriptor = new Metal.MTLRenderPassDescriptor ();
var tdesc = Metal.MTLTextureDescriptor.CreateTexture2DDescriptor (MTLPixelFormat.RGBA8Unorm, (UIntPtr)width,
var tdesc = Metal.MTLTextureDescriptor.CreateTexture2DDescriptor (CrossGraphics.Metal.MetalGraphics.DefaultPixelFormat, (UIntPtr)width,
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since SaveDrawing is blitting the texture to a CGBitmapContext with a fixed pixel format it seems dangerous to just use DefaultPixelFormat? Or am I misunderstanding DefaultPixelFormat? I'm not necessarily asking for a change but I do need a n explanation. DefaultPixelFormat is seeming like a bad idea haha.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — the original PremultipliedLast in SaveDrawing expects RGBA byte order, so blindly using DefaultPixelFormat (BGRA) for the texture would swap R and B during readback.

Fixed in 9c1bbac: SaveDrawing now selects CGBitmapFlags based on DefaultPixelFormat — uses PremultipliedFirst | ByteOrder32Little for BGRA, or PremultipliedLast for RGBA. This keeps the texture format in sync with both the pipeline and the bitmap readback.

The texture format change itself is still needed because Metal requires the render target format to match the pipeline's color attachment format — the original RGBA8Unorm mismatched the pipeline's BGRA8Unorm.

Update CGBitmapContext flags in SaveDrawing to handle BGRA byte order
correctly: use PremultipliedFirst | ByteOrder32Little for BGRA textures,
or PremultipliedLast for RGBA textures.

Agent-Logs-Url: https://github.com/praeclarum/CrossGraphics/sessions/29dd2aa3-9992-4e38-a81d-7015cac6a679

Co-authored-by: praeclarum <323548+praeclarum@users.noreply.github.com>
Copilot AI requested a review from praeclarum March 30, 2026 16:47
@praeclarum praeclarum marked this pull request as ready for review March 30, 2026 17:56
@praeclarum praeclarum merged commit 6afc27f into master Mar 30, 2026
1 check passed
@praeclarum praeclarum deleted the copilot/fix-metal-rendering-issue branch March 30, 2026 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Metal is rendering dark/faded

2 participants