Skip to content
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

experimental acrylic brush implementation. #4043

Merged
merged 64 commits into from Jul 6, 2020

Conversation

danwalmsley
Copy link
Member

What does the pull request do?

What is the current behavior?

What is the updated/expected behavior with this PR?

How was the solution implemented (if it's not obvious)?

Checklist

Breaking changes

Fixed issues

Copy link
Member

@kekekeks kekekeks left a comment

Choose a reason for hiding this comment

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

Also need to implement a solid color fallback for Direct2D

@@ -653,6 +671,36 @@ private void ConfigureVisualBrush(ref PaintWrapper paintWrapper, IVisualBrush vi
}
}

static SKColor SimpleColorBurn(SKColor bg, SKColor fg)
Copy link
Member

Choose a reason for hiding this comment

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

We need to calculate that color properly, that code was here only for example purposes

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed, as we cant, you need a blending function that can work with the background bitmap. we dont have access to this.

Maybe for in - app acrylic in future.

Comment on lines 714 to 726
var noiseOpcity = 0.06 * brush.Opacity;

var tintColor = acrylicBrush.TintColor;
var excl = new SKColor(255, 255, 255, (byte)(255 * 0.1));
var tint = new SKColor(tintColor.R, tintColor.G, tintColor.B, (byte)(255 * ((tintColor.A / 255.0) * acrylicBrush.Opacity)));

tint = SimpleColorBurn(excl, tint);

using (var tintShader = SKShader.CreateColor(tint))
using (var noiseShader =
SKShader.CreatePerlinNoiseTurbulence(15.876f, 15.876f, 2, 0.76829314f)
.WithColorFilter(CreateAlphaColorFilter(noiseOpcity)))
using (var compose = SKShader.CreateCompose(tintShader, noiseShader))
Copy link
Member

Choose a reason for hiding this comment

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

@danwalmsley I have tried with noise texture and noise looks good now. I don't really think, if it's great idea to ship png file with every application as WinUI does (or ship embedded instead?), but I am not sure, if it is easy to generate consistently good noise in runtime.
I have compared this brush with "Acrylic" application from MS Store and WinUI's Xaml Controls Gallery. Also I have set AccentPolicy.GradientColor value to 0x01000000 for windows (in other way acrylic background with transparent brush looks too "white"). But I haven't tested it with luminosity, because Acrylic app and WinUI XAML app doesn't have options for this. I can create simple one tomorrow evening.

With better noise and app background it already looks great for me (except gradient on top from undocumented api). But if we want acrylic with same effect as in UWP (I don't think if this is necessary), I have found also two small issues:

  1. With UWP Acrylic I can set any TintOpacity, and with 100% value it will looks like solid color without any effects. But with Avalonia TintOpacity=100% still is partially transparent (it seems like GetTintOpacityModifier should work only in pair with GetEffectiveLuminosityColor, and returns 1.0d on older OS, where luminosity is not available).
  2. In UWP Brush with TintOpacity=100% doesn't have 10% of white - it still has clear solid color (FF0000 for Red tint). So it seems like "excl" (10% of white) should also depend on TintOpacity, or also needs luminosity?
Suggested change
var noiseOpcity = 0.06 * brush.Opacity;
var tintColor = acrylicBrush.TintColor;
var excl = new SKColor(255, 255, 255, (byte)(255 * 0.1));
var tint = new SKColor(tintColor.R, tintColor.G, tintColor.B, (byte)(255 * ((tintColor.A / 255.0) * acrylicBrush.Opacity)));
tint = SimpleColorBurn(excl, tint);
using (var tintShader = SKShader.CreateColor(tint))
using (var noiseShader =
SKShader.CreatePerlinNoiseTurbulence(15.876f, 15.876f, 2, 0.76829314f)
.WithColorFilter(CreateAlphaColorFilter(noiseOpcity)))
using (var compose = SKShader.CreateCompose(tintShader, noiseShader))
var noiseOpcity = 0.02 * brush.Opacity;
var tintColor = acrylicBrush.TintColor;
var excl = new SKColor(255, 255, 255, (byte)(255 * 0.1));
var tint = new SKColor(tintColor.R, tintColor.G, tintColor.B, (byte)(255 * ((tintColor.A / 255.0) * acrylicBrush.Opacity)));
tint = SimpleColorBurn(excl, tint);
using (var tintShader = SKShader.CreateColor(tint))
using (var bitmap = SKBitmap.Decode("noise.png"))
using (var noiseShader = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat)
.WithColorFilter(CreateAlphaColorFilter(noiseOpcity)))
using (var compose = SKShader.CreateCompose(tintShader, noiseShader))

Copy link
Member

Choose a reason for hiding this comment

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

Different TintOpacity values, but almost same acrylic. And in Avalonia 10% of white is more noticeable.
image

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed the way acrylic works significantly... we will not be able to achieve identical results to UWP unfortunately. (At least for BackDrop acrylic, inapp acrylic will be possible in future and identical results to uwp is reasonable)

We can also make the result fairly consistent across platforms and blur radius (which is platform dependent) will need some adjustment factor depending on what the platform provides in the window.

So we have:

<HostBackDrop> - not accessible
<HostProvidedBlur> - not controlable
<TracingPaperLayer> - #xx7f7f7f makes the backdrop more opaque on platforms that cant do this for us.
<TintLayer> - Adds the tint colour, blended with the tracing paper layer.
<NoiseLayer> - Adds the texture blended with the TintLayer.

Dan Walmsley and others added 21 commits June 13, 2020 14:33
…l-acrylic-brush

# Conflicts:
#	src/Avalonia.Visuals/Rendering/SceneGraph/DeferredDrawingContextImpl.cs
# Conflicts:
#	samples/ControlCatalog/MainWindow.xaml
@danwalmsley danwalmsley marked this pull request as ready for review July 5, 2020 16:55
@danwalmsley danwalmsley merged commit 5a890b9 into master Jul 6, 2020
@danwalmsley danwalmsley deleted the feature/experimental-acrylic-brush branch July 6, 2020 18:11
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.

None yet

4 participants