So I'm currently using Windows composition Apis to create a "fade-in" animation, combining a scale animation and an opacity animation, to my custom control, which worked perfectly fine. However, recently I tried to add some light effect but for some reason the opacity animation doesn't work out anymore.
As you can see, you are able to see the image during the "fade-in" animation without light effect. But once you add the light effect, you are not able to see it until the "fade-in" animation is done. It must be some mechanics of composition animation but I just used them in a wrong way.
You can reproduce the code here
MainPage.xaml(Use your own image):
<Grid x:Name="rootPanel" Background="LightGray" Loaded="rootPanel_Loaded">
<Image x:Name="panel" Source="Assets/aaa.jpg" Loaded="panel_Loaded" />
MainPage.xaml.cs:
public sealed partial class MainPage : Page
{
private Compositor _compositor;
private const float lightDepth = 300f;
private const int animationDelay = 600;
private const int animationDuration = 70;
private CompositionEffectFactory _effectFactory;
private Random _random = new Random();
private PointLight _pointLight;
private Visual _root;
private ImplicitAnimationCollection _implicitAnimations1st;
public MainPage()
{
this.InitializeComponent();
_compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
_implicitAnimations1st = _compositor.CreateImplicitAnimationCollection();
var _firstWaveAnimationGroup = _compositor.CreateAnimationGroup();
var OpacityAnimation1st = _compositor.CreateScalarKeyFrameAnimation();
OpacityAnimationSetting(OpacityAnimation1st, (double)0);
var scaleAnimation1st = _compositor.CreateVector3KeyFrameAnimation();
ScaleAnimationSetting(scaleAnimation1st, (double)0);
_firstWaveAnimationGroup.Add(OpacityAnimation1st);
_firstWaveAnimationGroup.Add(scaleAnimation1st);
_implicitAnimations1st["Offset"] = _firstWaveAnimationGroup;
}
private void ScaleAnimationSetting(Vector3KeyFrameAnimation animation, double delay)
{
animation.InsertKeyFrame(0.0f, new Vector3(0.7f, 0.7f, -.5f));
animation.InsertKeyFrame(1.0f, new Vector3(1, 1, 0), _compositor.CreateLinearEasingFunction());
animation.Duration = TimeSpan.FromMilliseconds(800);
animation.DelayTime = TimeSpan.FromMilliseconds(delay);
animation.DelayBehavior = AnimationDelayBehavior.SetInitialValueAfterDelay;
animation.Target = "Scale";
}
private void OpacityAnimationSetting(ScalarKeyFrameAnimation animation, double delay)
{
animation.InsertKeyFrame(0.0f, 0.0f);
animation.InsertKeyFrame(1.0f, 1.0f, _compositor.CreateLinearEasingFunction());
animation.Duration = TimeSpan.FromMilliseconds(800);
animation.DelayTime = TimeSpan.FromMilliseconds(delay);
animation.DelayBehavior = AnimationDelayBehavior.SetInitialValueAfterDelay;
animation.Target = "Opacity";
}
private void panel_Loaded(object sender, RoutedEventArgs e)
{
var visual = ElementCompositionPreview.GetElementVisual(panel);
visual.Opacity = 0f;
visual.ImplicitAnimations = _implicitAnimations1st;
visual.CenterPoint = new Vector3((float)(panel.DesiredSize.Width / 2), (float)(panel.DesiredSize.Height / 2), 0);
visual.Offset = new Vector3((float)-panel.DesiredSize.Width, (float)-panel.DesiredSize.Height, 0);
}
private void rootPanel_Loaded(object sender, RoutedEventArgs e)
{
_root = ElementCompositionPreview.GetElementVisual(rootPanel);
_pointLight = _compositor.CreatePointLight();
_pointLight.Offset = new Vector3(-2500f, -2500f, 300f);
_pointLight.Intensity = 1.3f;
IGraphicsEffect graphicsEffect = new CompositeEffect()
{
Mode = CanvasComposite.DestinationIn,
Sources =
{
new CompositeEffect()
{
Mode = CanvasComposite.Add,
Sources =
{
new CompositionEffectSourceParameter("ImageSource"),
new SceneLightingEffect()
{
AmbientAmount = 0,
DiffuseAmount = .5f,
SpecularAmount = 0,
NormalMapSource = new CompositionEffectSourceParameter("NormalMap"),
}
}
},
new CompositionEffectSourceParameter("NormalMap"),
}
};
_effectFactory = _compositor.CreateEffectFactory(graphicsEffect);
//Comment Out the rest of the two lines can remove light effect
_pointLight.CoordinateSpace = _root;
_pointLight.Targets.Add(_root);
#region First light animation
Vector3KeyFrameAnimation lightPositionAnimation;
lightPositionAnimation = _compositor.CreateVector3KeyFrameAnimation();
lightPositionAnimation.InsertKeyFrame(.0f, new Vector3(200f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
lightPositionAnimation.InsertKeyFrame(1f, new Vector3(200f, 700f, lightDepth), _compositor.CreateLinearEasingFunction());
lightPositionAnimation.DelayTime = TimeSpan.FromMilliseconds(animationDelay);
lightPositionAnimation.Duration = TimeSpan.FromSeconds(animationDuration);
lightPositionAnimation.IterationBehavior = AnimationIterationBehavior.Forever;
_pointLight.StartAnimation("Offset", lightPositionAnimation);
#endregion
}
}
How do I be able to fix it?
While waiting some days after posting problem as issue on the github repo of Windows UI, one of the Windows UI developers gave a solution to fix such question.
A quote from this developer:
After adding such code in my project, it really fix the problem.