ruffle icon indicating copy to clipboard operation
ruffle copied to clipboard

render: Add BlendMode infrastructure and implement BlendMode.ADD

Open Aaron1011 opened this issue 3 years ago • 2 comments

Each render backend keeps track of a stack of BlenModes, which are pushed and popped by 'core' as we render objects in the displaay tree. For now, I've just implemented BlendMode.ADD, which maps directly onto blend mode supported by each backend.

All other blend modes (besides 'NORMAL') will produce a warning when we try to render using them. This may produce a very large amount of log output, but it's simpler than emitting each warning only once, and will help to point developers in the right direction when they get otherwise inexplicable rendering issues (due to a blend mode not being implemented).

The wgpu implementation is by far the most complicated, as we need to construct a RenderPipeline for each possible (BlendMode, MaskState). I haven't been able to find any documentation about the maximum supported number of (simultaneous) WebGPU render pipelines - if this becomes an issue, we may need to register them on-demand when a particular blend mode is requested.

Aaron1011 avatar Jul 26 '22 03:07 Aaron1011

Sorry if this is a bit off-topic, but: Welp, I wanted to test this on https://z0r.de/2245, as it is obviously rendering incorrectly at the moment, and I thought it was because of the missing blend modes. However, even with this PR, it appears exactly the same as before, and I don't even get any warnings about blend modes.

So, it could be simply the result of the self-overlapping, partially transparent shape being drawn on top of itself due to the tessellation. I suppose this could be solved by rendering the whole shape fully opaquely into a "layer" first, then drawing that with uniform transparency - or, what might be simpler, if possible at all, to ask lyon to remove the overlaps, and "flatten" the shape during tessellation, so it's not drawn on top of itself?

EDIT: Seems like this is a known limitation of lyon: https://nical.github.io/lyon-doc/lyon/tessellation/path_stroke/index.html#overview

torokati44 avatar Jul 26 '22 09:07 torokati44

So, it could be simply the result of the self-overlapping, partially transparent shape being drawn on top of itself due to the tessellation. I suppose this could be solved by rendering the whole shape fully opaquely into a "layer" first, then drawing that with uniform transparency - or, what might be simpler, if possible at all, to ask lyon to remove the overlaps, and "flatten" the shape during tessellation, so it's not drawn on top of itself?

EDIT: Seems like this is a known limitation of lyon: https://nical.github.io/lyon-doc/lyon/tessellation/path_stroke/index.html#overview

Yep, this SWF uses 200 width transparent strokes which lyon doesn't tessellate in a nice way for us. I think we could work around it using stencil or depth to avoid overdraw when rendering these kinds of strokes.

Herschel avatar Jul 26 '22 17:07 Herschel

Hooked this up for SWF PlaceObject tags, AVM1, and AVM2.

One slightly annoying thing is that I'd like to implement FromWStr for BlendMode, but the orphan rules prevent this -- could add an ruffle_wstr dep to swf, or simply add a blend_mode_to_wstr function in core somewhere.

Herschel avatar Aug 18 '22 19:08 Herschel