Skip to content

fix(core): correct opacity in interleaved mode #9642

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

felixpalmer
Copy link
Collaborator

Background

When using PostProcessEffect with interleaved: true, due to clearing of the canvas the result is the basemap is completely cleared with a solid grey color:

Screenshot 2025-05-22 at 09 40 00

With this change, the clearing is applied only when needed, and the blending in ScreenPass is fixed to give correct results. Here is a layer, drawn with opacity with a ink postprocess applied, in interleaved mode.

Screen.Recording.2025-05-22.at.09.44.57.mov

In order to test, the layer browser has been enhanced to include a toggle for interleaved rendering

Change List

  • Do not clear canvas in deck-renderer when clearCanvas is explicitly set to false
  • Correct blending in ScreenPass (only used in PostProcessEffect)
  • Tidy up RasterLayer
  • Enhance layer browser to support interleaved

layers={layers.map(l => l.clone({beforeId: 'watername_ocean'}))}
initialViewState={INITIAL_VIEW_STATES}
layerFilter={this._layerFilter}
{...(!interleaved && {views})}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

interleaved and the view prop do not play nicely together with postprocessing as the MapboxOverlay does a double render, thus applying the postprocess twice to the mapbox canvas.

Details: hasNonMapboxViews ends up being true due to the custom views: https://github.com/visgl/deck.gl/blob/master/modules/mapbox/src/deck-utils.ts#L340-L357

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you have a sense of how we might support multi-view + interleave + post-processing?

Could this look like configuring something on each view, or configuring post-processing to apply only to specific views? Something else?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think the most flexible approach would be to have postprocessing be something that is done on a per-layer basis. For:

  • A) effects that require multiple layers, they can be combined using CompositeLayer (this is basically how the PostProcessUtils do it
  • B) effects that should only apply to a specific view can use the same approach in conjunction with layerFilter to only render the postprocessed layer(s) in the given view

Applying postprocessing to a specific view feels more restrictive as it means all the layers in that view would then be affected.

The only downside I can think of is layers which get shown in multiple views, where one would like to apply postprocess only in one view. In this case the layer would have to be duplicated, but I don't think this is bad - it at least makes clear what is going on

Copy link
Collaborator

@chrisgervang chrisgervang Jun 11, 2025

Choose a reason for hiding this comment

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

Yeah great point, per-layer effects are the most flexible of the options.

And I can't think of too many scenarios where I want to only apply an entire effect to a view.

I agree that we can optimize for per-layer and entire canvas effects.

Sounds like the APIs are fine and we just have rendering issues for interleaved + multi-view that can be solved internally. Does that sound right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well, except we don't have an official way to do per-Layer effects - it would be best to include that in the core of deck.gl

@felixpalmer
Copy link
Collaborator Author

felixpalmer commented Jun 4, 2025

Some more background, as this is quite tricky to get right. There are two cases to consider:

  • Alpha added via Layer rendering (e.g. opacity prop set to 0.5)
  • Alpha added via postprocess (e.g. a zoom blur will add translucent pixels)

Here are some example renders:

Postprocessing with a shader that just writes out the input color

Current behavior (master)

pp-opacity-main.mov

The blending setup is incorrectly darkening the output, when it should not

New behavior (this PR)

pp-opacity-fix.mov

Color is now correct, only the opacity is modified

Postprocessing with zoom blur

Current behavior (master)

zoomblur-master.mov

Translucent pixels from postprocess are correct, but layer is darkened

New behavior (this PR)

zoomblur-fix-old.mov

Layer no longer darkened, but the blending of the postprocess is wrong

New behavior including fix in luma

The issue is that two effects in luma.gl are using per-multiplied alpha in the shader, which is incorrect. The blending should be handled by the blend modes, not in the shader

zoomblur-fix-fixshader.mov

With the luma fix, we finally get the correct result 🥵 !

@felixpalmer
Copy link
Collaborator Author

felixpalmer commented Jun 4, 2025

The failing render test is due to the issue in luma. Running with the luma fix this result is fixed:

Screenshot 2025-06-03 at 15 19 52

Current (incorrect) golden image:

post-process-effects

@chrisgervang
Copy link
Collaborator

Thank you very much for this write up and examples! The new results look wayyyyyy better.

We never mentioned issues with PostProcessing in our limitations, but I'd believe if they've silently been problematic this whole time.

I'd been aware of an undocumented limitation we had about not being able to achieve basic blending effects like "additive" via deck prop parameters in v8 and below, but I consider that technique a hack since it interfered with the interleaved renderer. I'd prefer officially supporting an "additive" effect via PostProcessing.

Great work. I think it's worth mentioning formal support for interleaved PostProcessing effects in the 9.2 release.

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.

2 participants