-
Notifications
You must be signed in to change notification settings - Fork 330
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
Advanced rendering effects - filters, masks, box-shadows, gradients, and shaders #594
Conversation
…er' properties Filters are implemented partially like decorators.
… local stacking context
…ntaining block for absolutely positioned elements
…dd to effect sample
…rea with border radius support
…rack of the render state - The clip mask can be rendered to using normal geometry, then during other render commands the clip mask should hide any contents outside its area. - Improved element clipping behavior: Handles more complicated cases, including nested transforms with hidden overflow, and clips to the curved edge of elements with border-radius. - Text culling now also considers the viewport and properly handles transforms. Previously, text was not rendered in some situations, or unnecessarily rendered outside the window. - Clip mask implemented in GL3 renderer using stencil buffer. - Added and modified visual tests for clipping behavior.
- Allow textures to be saved from the current layer through render interface. - Implement GL3 support for saving textures. - Extend bounding box to include ink overflow from box shadows.
… with 'horizontal-gradient(...)' and 'vertical-gradient(...)' [deprecation]
- Allow splitting by comma - No escaping inside parenthesis - Enable quote mode inside parenthesis - Add unit tests
Add warning message when decorators generate invalid data handles
Good catch! Thanks for reporting. I made some changes, I believe this one should fix this issue: 011b3c1 |
I see, I'll look into that. Can you post a full document example? |
|
There are also some problems with applying
For Chrome, this is correct only if the |
@0suddenly0 I finally got around to looking into these ones. For the first issue with a child and filter parent, this is a bit tricky for us. It has to do with how absolutely positioned elements are considered in terms of overflow. Specifically, a known difference from CSS is that we don't show scroll bars or clip such elements when placed outside their offset parent's visible region. There is some previous discussion on this topic, but in short, we want absolute positioning to be independent of layout, so that we don't have to compute an expensive layout step every time we move something around the screen. This behavior extends to filtering, such that absolutely positioned elements are not considered a part the current element's visible region. I am considering a way to make this work without inducing a full re-layout step. In particular, we could keep track of any such absolutely positioned overflowing elements, and say that:
This could solve some existing cases where one would need to use I've pushed a commit for the second case. There was indeed a limitation to combining backdrop-filter with filter and mask-image, so thank you for reporting this. I made some changes, including a new test case for several different combinations of these properties: I also identified some cases where the edges of backdrop-filter with blur would be dark, as seen above. There might still be some cases left to consider for these combinations. The resulting code is a bit clunky in my opinion, so I am consider making some render interface API changes around layers. Also, please note that our |
@mikke89 can you add a such sample to official samples please? Or how to call a such sample? It might be useful for testing render backends since we would have many of them... |
@wh1t3lord All of these examples are added to our visual tests. You can find them by launching the The jellyfish in the screenshot above was replaced with an existing image in the repository for the test though. I have a jsfiddle here for the browser equivalent for anyone interested. |
… to the same element
…of being a part of layer pop The purpose of each function should now be more clear. With this change, we can now composite two arbitrary layers which simplifies some use cases of compositing. This commit also uses the changed interface to fix some artifacts when rendering back-drop filter blur combined with plain filter blur.
This one has been a long time in the making, first mentioned in #307, now the time has come for one of the biggest additions to the library. I hope you like the changes!
I am posting this as a pull request to gather more feedback. There's a lot here, feel free to give any feedback, whether a small comment or a fully detailed review. It would be great to see the effect sample especially tested on more machines, as I'm sure there will be issues popping up. I've tried to keep the commit history clean, which should be helpful for reviewing.
There has been some feedback regarding the new render interface in particular, please let me know what you think here, before we lock-in the changes. Some thoughts here: #307 (comment)
This PR closes #249, #253, #307, and even addresses #1.
New features
New properties:
filter
: Apply a rendering effect to the current element (including its children).blur
,drop-shadow
,hue-rotate
,brightness
,contrast
,grayscale
,invert
,opacity
,sepia
. In other words, all supported functions from CSS.backdrop-filter
: Apply a filter to anything that is rendered below the current element.mask-image
: Can be combined with any decorator, including images and gradients, to mask out any part of the current element (and its children) by multiplying their alpha channels.box-shadow
: With full support for offset, blur, spread, and insets.New decorators:
shader
: A generic decorator to pass a string to your renderer.linear-gradient
,repeating-linear-gradient
radial-gradient
,repeating-radial-gradient
conic-gradient
,repeating-conic-gradient
The new rendering interface include support for shaders, which enable the above decorators. Parsing is done in the library, but the backend renderer is the one implementing the actual shader code.
All of the filters and gradient decorators have full support for interpolation, that is, they can be animated. This is not yet implemented for box-shadow.
Decorators can now take an extra keyword
<paint-area>
which is one ofborder-box | padding-box | content-box
, which indicates which area of the element the decorator should apply to. All built-in decorators are modifed to support this property.Custom filters can be created by users by deriving from
Filter
andFilterInstancer
, very much like how custom decorators are created.Improved element clipping behavior. Handles more complicated cases, including nested transforms with hidden overflow, and clips to the curved edge of elements with border-radius. This requires clip mask support in the renderer.
New
effect
sample showcasing a lot of the new features.Major overhaul of the render interface
The render interface has been simplified to ease implementation of basic rendering functionality, while extended to enable the new advanced rendering effects. The new effects are fully opt-in, and can be enabled iteratively to support the features that are most desired for your project.
Highlighted changes:
Backward compatible render interface adapter
The render interface changes will require updates for all users writing their own render interface implementation. To smooth the transition, there is a fully backward-compatible adapter for old render interfaces, see
RenderInterfaceCompatibility
.Rml::RenderInterfaceCompatibility
instead ofRml::RenderInterface
.Rml::SetRenderInterface(my_render_interface.GetAdaptedInterface());
It can also be useful to take a closer look at the adapter before migrating your own renderer to the new interface, to see which changes are necessary. Naturally, this adapter won't support any of the new rendering features.
Render manager and resources
A new RenderManager is introduced to manage resources and other rendering state. Users don't normally have to interact with this, but for contributors, and for more advanced usages, such as custom decorators, this implies several changes.
The RenderManager and can be considered a wrapper around the render interface. All internal calls to the render interface should now go through this class.
Resources from the render interface are now wrapped as unique render resources, which are move-only types that automatically cleans up after themselves when they go out of scope. This considerably helps resource management. This also implies changes to many central rendering types.
CallbackTexture
on the other hand is a unique render resource, automatically released when out of scope.See the following commit message for more details: a452f26.
Other changes
Utilities:
General improvements:
Fixes:
Visual tests:
Limitations
Filters will only render based on geometry that is visible on-screen. Thus, some filters may be cut-off. As an example, an element that is partly clipped with a drop-shadow may have its drop-shadow also clipped, even if it is fully visible. On the other hand, box shadows should always be rendered properly, as they are rendered off-screen and stored in a texture.
Breaking changes
RenderInterfaceCompatibility
notes above for an adapter from the old render interface.gradient
decorator has been deprecated, instead one can now usehorizontal-gradient
andvertical-gradient
, thereby replacing the keyword to indicate direction.Not yet implemented
Some features to be implemented, or being considered:
background
property. This way, we can use e.g.background: linear-gradient(...)
like in CSS.I consider none of these blocker, instead we can do them as follow-ups.
Screenshots
I'll close off with some eye candy:
effects.sample.-.2024-02-05.webm