-
Notifications
You must be signed in to change notification settings - Fork 692
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
Proposal: Bring back vector-based tiled brushes #536
Comments
@verelpode would Win2D work for your scenarios? You can see an example of how it's used to create a repeated checkerboard in the "drawimage enumerations" example in the Win2D Gallery sample app by tiling the result of CreateFromColors() using CanvasEdgeBehavior.Wrap. For more complex usages there's also TileEffect. |
@jesbis Thanks for the idea. Correct me if I'm wrong, but that Win2D object cannot be converted to
Win2D seems like a case of switching to a completely different graphics engine whereas I was thinking that vector tiled brushes would be a part of |
Thanks for clarifying! Xaml, Composition and Win2D are mostly built on the same graphics engine and just provide different levels of abstraction, but I can see the value of having it supported as part of the Xaml API. Right now you have a couple options for Brushes: Win2D has a CanvasImageSource which can be used as the source for a Xaml brush. Another option might be to create your own Xaml brush that subclasses XamlCompositionBrushBase and uses the Windows.UI.Composition APIs to tile. It could use the same approach as in Win2D (e.g. CanvasEdgeBehavior.Wrap). |
Aha. Although I've not yet used the new Composition API, it looks like the idea of subclassing If I understand correctly, it would be implemented like the following ?
If I understand correctly, the checkerboard or gridline pattern or whatever pattern would be defined in the Visual object that is assigned to |
I would recommend using a CompositionEffectBrush. You can create an effect graph using Win2D. One of the effects in there is BorderEffect which lets you tile its source. You might be able to glean some info from the AcrylicBrush that we have implemented in this repo (https://github.com/Microsoft/microsoft-ui-xaml/blob/master/dev/Materials/Acrylic/AcrylicBrush.cpp#L845). In that scenario we tile an image wrapped in CompositionSurfaceBrush, which can be given to the BorderEffect. If you wanted it to be an SVG-based tile then I think you could use Win2D to render the base tile and feed that through the effect brush. |
You shouldn't need to use anything to do with Visuals for a brush. For reference here's a basic C# example of a tiling brush based on XamlCompositionBrushBase: Disclaimer: just an example, and not 100% tested or guaranteed. |
hmm, if it doesn't use a Visual object to represent the checkerboard or other vector-based pattern to tile, then what other object should be used to represent the pattern? The link to ImageTileBrush.cs is helpful except one thing needs to be replaced: Instead of using a raster image (the |
All content is eventually rasterized, so it's just a matter of what stage you do it at. Using pre-generated image files can often yield better performance if it works for your scenario. If you do want to generate the content at runtime then instead of this line in the gist above: var surface = LoadedImageSurface.StartLoadFromUri(ImageSourceUri); you could draw your own content, e.g.: var graphicsDevice = CanvasComposition.CreateCompositionGraphicsDevice(Window.Current.Compositor, CanvasDevice.GetSharedDevice());
var surface = graphicsDevice.CreateDrawingSurface(new Size(10,10), DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);
using (var session = CanvasComposition.CreateDrawingSession(surface))
{
session.FillRectangle(new Rect(0, 0, 5, 5), Colors.Blue);
session.FillRectangle(new Rect(5, 5, 10, 10), Colors.Yellow);
} (note this is just an example for testing: for a real implementation you'd likely want to additionally cache the CompositionGraphiceDevice, handle the RenderingDeviceReplaced event appropriately, and dispose the device in OnDisconnected). |
Correct me if I'm wrong: If the content is loaded from a raster image file OR drawn at runtime using CreateDrawingSession, either way, this pre-rasterized solution would be incompatible with ScrollViewer.ZoomFactor and Viewbox etc? Actually the tiled brush would still appear on-screen but it would suffer raster scaling artifacts/distortions, unlike WPF's DrawingBrush and VisualBrush which are fully scalable / resolution-independent. Another disadvantage is that if this tiled brush implementation is publicly added to UWP/Windows.UI.Xaml is supposed to be better than its predecessor WPF, but for this pre-rasterized tiled brush implementation, it seems like we're falling back to an inferior solution in comparison to WPF. Loss of a preexisting capability isn't a happy feeling. How difficult would it be to create a UWP/Xaml version of System.Windows.Media.VisualBrush ? Note VisualBrush also supports tiling. Obviously the UWP Although WPF has |
If you need to support dynamic scaling at runtime then you do need something Visual-based after all 😊 In the latest insider SDKs you can use Windows.UI.Composition.CompositionVisualSurface, which is similar to the WPF VisualBrush but a) faster and b) more flexible. It will definitely be more expensive than pre-rasterized content though. Here's an example that uses high-performance composition shapes and supports scaling (with ViewBox, ScrollViewer, etc.): You could also refactor it to accept arbitrary sets of shapes or Visuals if needed. |
Looks good, thank you! That example could also be used as the basis for creating Alternatively, if desired, the relevant parts of the code inside A related issue that could be considered is the adding of the tiled brush capability to the Composition API. As I understand it, currently the Composition API -- if used alone -- is incapable of making a tiled Therefore would it make sense to create a class named Alternatively, a "TileMode" property could be added to CompositionSurfaceBrush, similar to System.Windows.Media.TileBrush.TileMode, with the default value being I think that a graphics API is generally expected to have a tiling capability, so I think it would make good sense if the Composition API supports a CompositionBrush that tiles a Composition Surface. When this capability is added to the Composition API, then of course it could also be used to create Xaml tiled brush that is internally implemented as a wrapper of the same capability within the Composition API. |
Little late to the thread, we do have a Tile Control in the Toolkit, but it's a bit limited and a wrapper. I agree this should just be a brush based thing which can be applied as a background anywhere. |
In issue #719, @bschoepke requested that WPF's
The In a previous message here, @jesbis mentioned Windows.UI.Composition.CompositionVisualSurface and a link to an example, but I misunderstood half of the message because I thought CompositionVisualSurface and the example were the same topic, but actually the example demonstrated something else: XamlCompositionBrushBase. So it's worthwhile to again mention In any event, |
I was looking for a similar brush too, i vote for bringing this to winui |
Not sure if this is a perfect workaround for what @verelpode is trying to do, but we have at least partial support for such a feature in the various brushes and effects in the Windows Community Toolkit, specifically in the In particular, there's the I'm thinking you might be able to achieve a tiled vectorized image brush by creating a pipeline like so (general idea):
You should then be able to just use this brush in your XAML controls as usual, and it'll render an infinitely-repeating tiles surface with your original geometry drawn to that surface. If you try this out, let us know how it goes! 😄 Also for completeness, even though it's not exactly the same, you can also use the |
Proposal: Bring back vector-based tiled brushes
Summary
Could you please consider bringing back the ability and documentation for how to make vector-based tiled brushes such as checkerboard and gridline brushes? This already existed previously but disappeared in UWP. Prior to UWP, TileBrush had a derived class called DrawingBrush and you can see examples of gridline brushes and checkerboard brushes in the second image in "Painting with Images, Drawings, and Visuals", under the heading "Paint an Area with a Drawing". But how can this be done in UWP? Please note these were vector-based brushes not bitmaps. How can we make such vector-based tiled brushes in UWP?
Rationale
Currently UWP has TileBrush with subclass ImageBrush but this only supports raster/bitmap tiled brushes, but in today's GUI world, everyone expects display resolution independence and support for very high resolution displays etc, thus the need for vector tiled brushes.
A tiled brush that displays gridlines is an example of something that looks terrible when implemented using ImageBrush. A bitmap image of gridlines does not scale well. In addition, it is inefficient to implement it as an ImageBrush. As a vector tile brush, it looks better and renders faster.
Important Notes
The following example XAML demonstrates how to make a checkerboard brush in WPF, but this stopped working in UWP because UWP doesn't have DrawingBrush. How can we do the equivalent in UWP?
Open Questions
The text was updated successfully, but these errors were encountered: