feat(rendering)!: blend each attachment of a multi-target draw on its own terms - #755
Conversation
… in each browser lane
…fore the draw is queued
Bundle ReportChanges will increase total bundle size by 35.1kB (0.11%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: exo-iife-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-full-iife-min-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-full-iife-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-esm-esmAssets Changed:
Files in
view changes for bundle: exo-iife-min-Exo-iifeAssets Changed:
Files in
view changes for bundle: exo-esm-modules-esmAssets Changed:
Files in
Files in
Files in
Files in
Files in
Files in
Files in
|
One blend mode per colour attachment of a multi-target draw. Until now a single blend setting applied to the whole draw; a G-buffer wants alpha blending on albedo and none on a normal or id slot, where a blended vector or id is meaningless.
MeshMaterialtakesblendModes, one entry per attachment index in fragment-output order; entries past the target's attachment count are ignored, attachments past the end of the list keep the draw's own mode, and a list entry wins over a per-mesh blend override on the attachments it covers. The list is part of the pipeline key. On WebGPU eachtargets[i].blendis set from it, one code path for single- and multi-attachment targets. On WebGL2 it needsOES_draw_buffers_indexed: when the effective modes agree the whole-draw call is issued and no extension is needed; when they differ the indexed calls are issued per attachment and restored afterwards by re-issuing the non-indexed state, which resets every draw buffer. Differing modes on a device without the extension throw aRenderErrorbefore the draw is queued, from the same entry point that already refuses a material that does not write every attachment, so nothing is pooled and no transform slot is consumed. The capability isRenderBackend.supportsPerAttachmentBlend, re-probed after context loss. An instanced batch refuses a multi-attachment target on both backends the same way, because the batch pipeline is built for one target.Tests: unit coverage of plumbing, pipeline-key identity, the indexed GL calls and their restore (including the cached-mode trap where the restore would otherwise be suppressed), the refusal through
renderTowith a clean following frame; browser readback in both lanes with a two-attachment target and[Normal, Additive], identical numbers on WebGL2 and WebGPU. Marked breaking becauseRenderBackendgains a member a third-party backend has to implement.