Skip to content

Commit

Permalink
feat(composition): Implement DistantDiffuseEffect + Sample
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmed605 committed Mar 2, 2024
1 parent 2f4b39d commit 6a153b5
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@
<Grid x:Name="sepiaGrid" Width="200" Height="200" VerticalAlignment="Top" HorizontalAlignment="Left" ToolTipService.ToolTip="SepiaEffect"/>
<Grid x:Name="tempTintGrid" Width="200" Height="200" VerticalAlignment="Top" HorizontalAlignment="Left" ToolTipService.ToolTip="TemperatureAndTintEffect"/>
<Grid x:Name="matrixGrid" Width="200" Height="200" VerticalAlignment="Top" HorizontalAlignment="Left" ToolTipService.ToolTip="ColorMatrixEffect"/>
<Grid x:Name="ddGrid" Width="200" Height="200" VerticalAlignment="Top" HorizontalAlignment="Left" ToolTipService.ToolTip="DistantDiffuseEffect"/>
</GridView>
</UserControl>
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public EffectBrushTests()
private void EffectBrushTests_Loaded(object sender, RoutedEventArgs e)
{
#if !WINDOWS_UWP
var compositor = Window.Current.Compositor;
var compositor = Windows.UI.Xaml.Window.Current.Compositor;

var effect = new SimpleBlurEffect() { Source = new CompositionEffectSourceParameter("sourceBrush"), BlurAmount = 5.0f };
var factory = compositor.CreateEffectFactory(effect);
Expand Down Expand Up @@ -199,6 +199,23 @@ private void EffectBrushTests_Loaded(object sender, RoutedEventArgs e)
var effectBrush21 = factory21.CreateBrush();

matrixGrid.Background = new EffectTesterBrush(effectBrush21);

var surface3 = LoadedImageSurface.StartLoadFromUri(new Uri("https://user-images.githubusercontent.com/34550324/268126129-1bb2c5e7-24a4-41dc-bcdf-59f533c0d173.png"));
surface3.LoadCompleted += (s, o) =>
{
if (o.Status == LoadedImageSourceLoadStatus.Success)
{
var brush = compositor.CreateSurfaceBrush(surface3);
var effect22 = new SimpleDistantDiffuseEffect() { Source = new SimpleLuminanceToAlphaEffect() { Source = new CompositionEffectSourceParameter("sourceBrush") }, DiffuseAmount = 5.0f, Azimuth = (float)MathEx.ToRadians(180.0f) };
var factory22 = compositor.CreateEffectFactory(effect22);
var effectBrush22 = factory22.CreateBrush();
effectBrush22.SetSourceParameter("sourceBrush", brush);
ddGrid.Background = new XamlCompositionBrush(effectBrush22);
}
};
#endif
}

Expand All @@ -215,7 +232,7 @@ public EffectTesterBrush(CompositionEffectBrush effectBrush, int imgSize = 200)

protected override void OnConnected()
{
var compositor = Window.Current.Compositor;
var compositor = Windows.UI.Xaml.Window.Current.Compositor;
var surface = LoadedImageSurface.StartLoadFromUri(new Uri($"https://avatars.githubusercontent.com/u/52228309?s={_imgSize}&v=4"));
surface.LoadCompleted += (s, o) =>
{
Expand Down Expand Up @@ -243,7 +260,7 @@ public EffectTesterBrushWithSecondaryBrush(CompositionEffectBrush effectBrush, C

protected override void OnConnected()
{
var compositor = Window.Current.Compositor;
var compositor = Windows.UI.Xaml.Window.Current.Compositor;
var surface = LoadedImageSurface.StartLoadFromUri(new Uri("https://avatars.githubusercontent.com/u/52228309?s=200&v=4"));
surface.LoadCompleted += (s, o) =>
{
Expand All @@ -259,6 +276,18 @@ protected override void OnConnected()
}
}

private class XamlCompositionBrush : XamlCompositionBrushBase
{
CompositionBrush _brush;

public XamlCompositionBrush(CompositionBrush brush) => _brush = brush;

protected override void OnConnected()
{
CompositionBrush = _brush;
}
}

#if !WINDOWS_UWP
[Guid("1FEB6D69-2FE6-4AC9-8C58-1D7F93E7A6A5")]
private class SimpleBlurEffect : IGraphicsEffect, IGraphicsEffectSource, IGraphicsEffectD2D1Interop
Expand Down Expand Up @@ -1613,6 +1642,89 @@ public object GetProperty(uint index)
public IGraphicsEffectSource GetSource(uint index) => Source;
public uint GetSourceCount() => 1;
}

[Guid("3E7EFD62-A32D-46D4-A83C-5278889AC954")]
private class SimpleDistantDiffuseEffect : IGraphicsEffect, IGraphicsEffectSource, IGraphicsEffectD2D1Interop
{
private string _name = "SimpleDistantDiffuseEffect";
private Guid _id = new Guid("3E7EFD62-A32D-46D4-A83C-5278889AC954");

public string Name
{
get => _name;
set => _name = value;
}

public float Azimuth { get; set; } = 0.0f;

public float Elevation { get; set; } = 0.0f;

public float DiffuseAmount { get; set; } = 1.0f;

public Color LightColor { get; set; } = Colors.White;

public IGraphicsEffectSource Source { get; set; }

public Guid GetEffectId() => _id;

public void GetNamedPropertyMapping(string name, out uint index, out GraphicsEffectPropertyMapping mapping)
{
switch (name)
{
case "Azimuth":
{
index = 0;
mapping = GraphicsEffectPropertyMapping.RadiansToDegrees;
break;
}
case "Elevation":
{
index = 1;
mapping = GraphicsEffectPropertyMapping.RadiansToDegrees;
break;
}
case "DiffuseAmount":
{
index = 2;
mapping = GraphicsEffectPropertyMapping.Direct;
break;
}
case "LightColor":
{
index = 3;
mapping = GraphicsEffectPropertyMapping.Direct;
break;
}
default:
{
index = 0xFF;
mapping = (GraphicsEffectPropertyMapping)0xFF;
break;
}
}
}

public object GetProperty(uint index)
{
switch (index)
{
case 0:
return Azimuth;
case 1:
return Elevation;
case 2:
return DiffuseAmount;
case 3:
return LightColor;
default:
return null;
}
}

public uint GetPropertyCount() => 4;
public IGraphicsEffectSource GetSource(uint index) => Source;
public uint GetSourceCount() => 1;
}
#endif
}
}
31 changes: 31 additions & 0 deletions src/Uno.UI.Composition/Composition/CompositionEffectBrush.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,37 @@ half4 main()
sourceFilter, new(bounds));
}

return null;
}
case EffectType.DistantDiffuseEffect:
{
if (effectInterop.GetSourceCount() == 1 && effectInterop.GetPropertyCount() == 4 && effectInterop.GetSource(0) is IGraphicsEffectSource source)
{
SKImageFilter sourceFilter = GenerateEffectFilter(source, bounds);
if (sourceFilter is null)
return null;

effectInterop.GetNamedPropertyMapping("Azimuth", out uint azimuthProp, out GraphicsEffectPropertyMapping azimuthMapping);
effectInterop.GetNamedPropertyMapping("Elevation", out uint elevationProp, out GraphicsEffectPropertyMapping elevationMapping);
effectInterop.GetNamedPropertyMapping("DiffuseAmount", out uint amountProp, out _);
effectInterop.GetNamedPropertyMapping("LightColor", out uint colorProp, out _);

float azimuth = (float)effectInterop.GetProperty(azimuthProp);
float elevation = (float)effectInterop.GetProperty(elevationProp);
float amount = (float)effectInterop.GetProperty(amountProp);
Color color = (Color)effectInterop.GetProperty(colorProp);

if (azimuthMapping == GraphicsEffectPropertyMapping.RadiansToDegrees)
azimuth *= 180.0f / MathF.PI;

if (elevationMapping == GraphicsEffectPropertyMapping.RadiansToDegrees)
elevation *= 180.0f / MathF.PI;

Vector3 lightVector = EffectHelpers.GetLightVector(azimuth, elevation);

return SKImageFilter.CreateDistantLitDiffuse(new SKPoint3(lightVector.X, lightVector.Y, lightVector.Z), color.ToSKColor(), 1.0f, amount, sourceFilter, new(bounds));
}

return null;
}
case EffectType.Unsupported:
Expand Down
52 changes: 52 additions & 0 deletions src/Uno.UWP/Graphics/Effects/Interop/EffectHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Windows.Foundation;
using Windows.Graphics.Effects;
using System.Runtime.InteropServices;
using System.Numerics;

namespace Windows.Graphics.Effects.Interop
{
Expand Down Expand Up @@ -111,5 +112,56 @@ public static EffectType GetEffectType(Guid effectId)
else
return EffectType.Unsupported;
}

internal static Vector3 GetLightVector(float azimuthInDegrees, float elevationInDegrees)
{
// MathEx.ToRadians isn't used here to precisely match the original function
float azimuthInRadians = azimuthInDegrees * 0.0174532925199433f;
float elevationInRadians = 0.0174532925199433f * elevationInDegrees;
float cosElevation = MathF.Cos(elevationInRadians);

Vector3 lightVector = new();
lightVector.X = cosElevation * MathF.Cos(azimuthInRadians);
lightVector.Y = cosElevation * MathF.Sin(azimuthInRadians);
lightVector.Z = MathF.Sin(elevationInRadians);

Normalize3DVector(ref lightVector);
return lightVector;
}

private static void Normalize3DVector(ref Vector3 vector)
{
float fa = 0.0f;
float flSqSum = 0.0f;
float flSqSuma = 0.0f;
Vector3 rgflSq = vector * vector;

flSqSum = rgflSq[0] + rgflSq[1] + rgflSq[2];
if (flSqSum <= 0.0000099999997f)
{
vector.X = 0.0f;
vector.Y = 0.0f;
vector.Z = 0.0f;
}
else
{
for (int i = 0; i < 3; ++i)
{
if (rgflSq[i] == 0)
{
vector[i] = 0.0f;
}
else
{
flSqSuma += rgflSq[i];
}
}

fa = MathF.Sqrt(flSqSuma);
vector.X = vector.X / fa;
vector.Y = vector.Y / fa;
vector.Z = vector.Z / fa;
}
}
}
}
7 changes: 6 additions & 1 deletion src/Uno.UWP/Graphics/Effects/Interop/EffectHelpers.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,11 @@ public static SKBlendMode ToSkia(this D2D1CompositeMode compositeMode)
case D2D1CompositeMode.Add:
return SKBlendMode.Plus;

case D2D1CompositeMode.Copy:
return SKBlendMode.Src;

// Unsupported modes

case D2D1CompositeMode.Copy:
case D2D1CompositeMode.MaskInvert:
default:
return (SKBlendMode)0xFF;
Expand All @@ -123,10 +125,13 @@ public static SKShaderTileMode ToSkia(this D2D1BorderEdgeMode mode)
{
case D2D1BorderEdgeMode.Clamp:
return SKShaderTileMode.Clamp;

case D2D1BorderEdgeMode.Wrap:
return SKShaderTileMode.Repeat;

case D2D1BorderEdgeMode.Mirror:
return SKShaderTileMode.Mirror;

default:
return SKShaderTileMode.Clamp;
}
Expand Down

0 comments on commit 6a153b5

Please sign in to comment.