Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Windows Input and Composition Samples
https://github.com/microsoft/windowscompositionsamples
Admin
A collection of WinAppSDK/WinUI3 samples and demos demonstrating Microsoft.UI.Composition and
...
Tokens:
18,459
Snippets:
100
Trust Score:
10
Update:
4 months ago
Context
Skills
Chat
Benchmark
71.4
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Windows Input and Composition Samples The Windows Input and Composition Samples project is a comprehensive demonstration gallery built on the Windows App SDK, showcasing the capabilities of the Microsoft.UI.Composition and Microsoft.UI.Input APIs. This project serves as both a reference implementation and learning resource for developers building modern Windows applications with rich visual experiences using WinUI 3. The codebase includes over 60 individual samples organized into a gallery application, along with standalone demo applications and reusable utility libraries. The project emphasizes practical implementations of the Fluent Design System building blocks, including visual composition, animation systems, lighting effects, gesture handling, and XAML interoperability. It provides type-safe expression animation capabilities through the ExpressionBuilder library, common UI patterns through the SamplesCommon utilities, and real-world examples ranging from basic transforms to complex interactive experiences. The samples automatically support downlevel compatibility to Windows 10 version 1809 (build 17763), demonstrating hardware capability detection and graceful degradation patterns for effects and animations. ## APIs and Functions ### ExpressionBuilder - Type-Safe Expression Animations The ExpressionBuilder provides a strongly-typed C# API for creating composition expression animations, eliminating string-based expressions and enabling compile-time checking for animation logic. ```csharp using ExpressionBuilder; using Microsoft.UI.Composition; using Microsoft.UI.Xaml.Hosting; // Get compositor from XAML element Compositor compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; // Create a visual to animate SpriteVisual sprite = compositor.CreateSpriteVisual(); sprite.Size = new Vector2(100, 100); // Get reference to another visual for expression binding var targetVisual = ElementCompositionPreview.GetElementVisual(targetElement); var visualRef = targetVisual.GetReference(); // Create type-safe expression: bind sprite opacity to target's Y position // Expression: clamp(target.Offset.Y / 500, 0, 1) var expression = ExpressionFunctions.Clamp(visualRef.Offset.Y / 500.0f, 0.0f, 1.0f); // Start the expression animation - sprite opacity tracks target position sprite.StartAnimation("Opacity", expression); ``` ### StartAnimation Extension Method Simplified method to start expression animations on composition objects using ExpressionBuilder nodes. ```csharp using ExpressionBuilder; using Microsoft.UI.Composition; using System.Numerics; // Create compositor and visual Compositor compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; SpriteVisual visual = compositor.CreateSpriteVisual(); // Create a PropertySet for animation parameters CompositionPropertySet properties = compositor.CreatePropertySet(); properties.InsertScalar("Progress", 0.0f); properties.InsertVector3("StartPosition", new Vector3(0, 0, 0)); properties.InsertVector3("EndPosition", new Vector3(500, 500, 0)); // Build type-safe expression using property references var propRef = properties.GetReference(); var progressRef = propRef.GetScalarProperty("Progress"); var startRef = propRef.GetVector3Property("StartPosition"); var endRef = propRef.GetVector3Property("EndPosition"); // Expression: lerp between start and end based on progress var offsetExpression = ExpressionFunctions.Lerp(startRef, endRef, progressRef); // Start animation visual.StartAnimation("Offset", offsetExpression); // Animate progress from 0 to 1 to move visual ScalarKeyFrameAnimation progressAnimation = compositor.CreateScalarKeyFrameAnimation(); progressAnimation.InsertKeyFrame(0.0f, 0.0f); progressAnimation.InsertKeyFrame(1.0f, 1.0f); progressAnimation.Duration = TimeSpan.FromSeconds(2); properties.StartAnimation("Progress", progressAnimation); ``` ### GetReference - Create Expression References Extension methods to create strongly-typed references to composition objects for use in expression animations. ```csharp using ExpressionBuilder; using Microsoft.UI.Composition; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Hosting; // Get ScrollViewer manipulation properties for scroll-driven animations ScrollViewer scrollViewer = myListView.GetFirstDescendantOfType<ScrollViewer>(); CompositionPropertySet scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer); // Get specialized reference for manipulation property set var scrollRef = scrollProperties.GetSpecializedReference<ManipulationPropertySetReferenceNode>(); // Create visual to animate Visual headerVisual = ElementCompositionPreview.GetElementVisual(headerElement); // Expression: header moves up at half the scroll rate (parallax effect) var parallaxExpression = scrollRef.Translation.Y * 0.5f; headerVisual.StartAnimation("Offset.Y", parallaxExpression); // Expression: header fades out based on scroll position var scrollDistance = 200.0f; var opacityExpression = ExpressionFunctions.Clamp(1.0f - (scrollRef.Translation.Y / scrollDistance), 0.0f, 1.0f); headerVisual.StartAnimation("Opacity", opacityExpression); ``` ### Parallax List Items Implementation Creates parallax scrolling effects on ListView items where each item moves at a different rate relative to the scroll position. ```csharp using ExpressionBuilder; using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Hosting; using System.Numerics; public sealed partial class ParallaxListView : Page { private ExpressionNode _parallaxExpression; private CompositionPropertySet _scrollProperties; private void Page_Loaded(object sender, RoutedEventArgs e) { Compositor compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; // Get ScrollViewer from ListView ScrollViewer scrollViewer = myListView.GetFirstDescendantOfType<ScrollViewer>(); _scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(scrollViewer); // Create parallax expression with offset parameter for each item var scrollRef = _scrollProperties.GetSpecializedReference<ManipulationPropertySetReferenceNode>(); var startOffset = ExpressionValues.Constant.CreateConstantScalar("startOffset", 0.0f); var parallaxValue = 0.5f; // Expression: (scrollY + itemOffset) * parallaxRate - (scrollY + itemOffset) _parallaxExpression = (scrollRef.Translation.Y + startOffset) * parallaxValue - (scrollRef.Translation.Y + startOffset); } private void ListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args) { // Get image element from item template Image image = args.ItemContainer.ContentTemplateRoot.GetFirstDescendantOfType<Image>(); Visual visual = ElementCompositionPreview.GetElementVisual(image); visual.Size = new Vector2(960f, 960f); // Set unique start offset for this item based on its index _parallaxExpression.SetScalarParameter("startOffset", (float)args.ItemIndex * visual.Size.Y / 4.0f); // Apply parallax animation to item visual.StartAnimation("Offset.Y", _parallaxExpression); } } ``` ### BackDrop - Blur Effect Control Reusable control that creates backdrop blur effects with customizable blur amount and tint color, commonly used for acrylic-style backgrounds. ```csharp using SamplesCommon; using Microsoft.UI; using Microsoft.UI.Composition; using Microsoft.UI.Xaml.Controls; // XAML usage // <SamplesCommon:BackDrop x:Name="myBackdrop" // BlurAmount="9" // TintColor="Transparent" // Width="400" Height="300" /> // Code-behind manipulation public sealed partial class MyPage : Page { private BackDrop _backdrop; public MyPage() { InitializeComponent(); // Create backdrop programmatically _backdrop = new BackDrop { BlurAmount = 15, TintColor = Color.FromArgb(128, 255, 255, 255), Width = 500, Height = 400 }; myPanel.Children.Add(_backdrop); } private void AnimateBlur() { // Access the underlying composition property set for animations CompositionPropertySet properties = _backdrop.VisualProperties; Compositor compositor = _backdrop.Compositor; // Animate blur amount from 0 to 20 ScalarKeyFrameAnimation blurAnimation = compositor.CreateScalarKeyFrameAnimation(); blurAnimation.InsertKeyFrame(0.0f, 0.0f); blurAnimation.InsertKeyFrame(1.0f, 20.0f); blurAnimation.Duration = TimeSpan.FromSeconds(1); properties.StartAnimation("BlurAmount", blurAnimation); } } ``` ### ImageLoader - Singleton Image Management Centralized image loading and surface management with Win2D integration, providing device lost recovery and thread-safe drawing operations. ```csharp using SamplesCommon; using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Hosting; using Windows.Foundation; using Windows.UI; using System; public sealed partial class MyPage : Page { private Compositor _compositor; private void Page_Loaded(object sender, RoutedEventArgs e) { // Initialize ImageLoader singleton with compositor _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; ImageLoader.Initialize(_compositor); // Load image from URI Uri imageUri = new Uri("ms-appx:///Assets/Images/photo.jpg"); ManagedSurface imageSurface = ImageLoader.Instance.LoadFromUri(imageUri); // Create visual with the loaded image SpriteVisual imageVisual = _compositor.CreateSpriteVisual(); imageVisual.Size = new Vector2(300, 300); imageVisual.Brush = imageSurface.Brush; imageVisual.Offset = new Vector3(50, 50, 0); ElementCompositionPreview.SetElementChildVisual(imageContainer, imageVisual); // Load image with specific size Size targetSize = new Size(200, 200); ManagedSurface thumbnailSurface = ImageLoader.Instance.LoadFromUri(imageUri, targetSize); // Load circular mask float radius = 150.0f; ManagedSurface circleSurface = ImageLoader.Instance.LoadCircle(radius, Colors.White); // Create mask brush CompositionSurfaceBrush maskBrush = circleSurface.Brush; CompositionMaskBrush compositeMask = _compositor.CreateMaskBrush(); compositeMask.Source = imageSurface.Brush; compositeMask.Mask = maskBrush; // Apply masked brush to visual SpriteVisual maskedVisual = _compositor.CreateSpriteVisual(); maskedVisual.Brush = compositeMask; maskedVisual.Size = new Vector2(radius * 2, radius * 2); } } ``` ### DropShadow with Mask Creating and manipulating drop shadows with optional mask support for non-rectangular shadows. ```csharp using SamplesCommon; using Microsoft.UI; using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Hosting; using Windows.UI; public sealed partial class ShadowExample : Page { private Compositor _compositor; private SpriteVisual _imageVisual; private CompositionMaskBrush _maskBrush; private DropShadow _dropShadow; private void Page_Loaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; // Load image var imageSurface = ImageLoader.Instance.LoadFromUri( new Uri("ms-appx:///Assets/Images/photo.jpg")); // Create image visual _imageVisual = _compositor.CreateSpriteVisual(); _imageVisual.Size = new Vector2(300, 300); _imageVisual.Brush = imageSurface.Brush; // Create drop shadow _dropShadow = _compositor.CreateDropShadow(); _dropShadow.Color = Colors.Black; _dropShadow.Opacity = 0.7f; _dropShadow.BlurRadius = 20.0f; _dropShadow.Offset = new Vector3(10, 10, 0); // Apply shadow to visual _imageVisual.Shadow = _dropShadow; // Load circular mask for shadow ManagedSurface maskSurface = ImageLoader.Instance.LoadCircle(150, Colors.White); // Create mask brush _maskBrush = _compositor.CreateMaskBrush(); _maskBrush.Source = imageSurface.Brush; _maskBrush.Mask = maskSurface.Brush; ElementCompositionPreview.SetElementChildVisual(container, _imageVisual); } private void ToggleMask_Click(object sender, RoutedEventArgs e) { // Toggle between masked and unmasked appearance if (_imageVisual.Brush == _maskBrush) { // Remove mask _imageVisual.Brush = _maskBrush.Source; _dropShadow.Mask = null; } else { // Apply mask _imageVisual.Brush = _maskBrush; _dropShadow.Mask = _maskBrush.Mask; } } } ``` ### Implicit Animations Automatic animations triggered by property changes, eliminating the need to manually start animations when visual properties are modified. ```csharp using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Hosting; using System; using System.Numerics; public sealed partial class ImplicitAnimationPage : Page { private Compositor _compositor; private ContainerVisual _root; private void Page_Loaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; _root = _compositor.CreateContainerVisual(); ElementCompositionPreview.SetElementChildVisual(this, _root); // Create multiple visuals for (int i = 0; i < 10; i++) { SpriteVisual visual = _compositor.CreateSpriteVisual(); visual.Size = new Vector2(50, 50); visual.Offset = new Vector3(i * 60, 100, 0); visual.CenterPoint = new Vector3(25, 25, 0); visual.Brush = _compositor.CreateColorBrush(Colors.Blue); _root.Children.InsertAtTop(visual); } // Set up implicit animations for all visuals SetupImplicitAnimations(); } private void SetupImplicitAnimations() { // Create offset animation (position changes) Vector3KeyFrameAnimation offsetAnimation = _compositor.CreateVector3KeyFrameAnimation(); offsetAnimation.Target = "Offset"; offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue"); offsetAnimation.Duration = TimeSpan.FromSeconds(1.5); // Create scale animation Vector3KeyFrameAnimation scaleAnimation = _compositor.CreateVector3KeyFrameAnimation(); scaleAnimation.Target = "Scale"; scaleAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue"); scaleAnimation.Duration = TimeSpan.FromSeconds(1.0); // Create rotation animation group ScalarKeyFrameAnimation rotationAnimation = _compositor.CreateScalarKeyFrameAnimation(); rotationAnimation.Target = "RotationAngleInDegrees"; rotationAnimation.InsertExpressionKeyFrame(1.0f, "this.StartingValue + 45"); rotationAnimation.Duration = TimeSpan.FromSeconds(1.0); // Create animation group for scale (combines scale and rotation) CompositionAnimationGroup scaleGroup = _compositor.CreateAnimationGroup(); scaleGroup.Add(scaleAnimation); scaleGroup.Add(rotationAnimation); // Create implicit animation collection ImplicitAnimationCollection implicitAnimations = _compositor.CreateImplicitAnimationCollection(); implicitAnimations["Offset"] = offsetAnimation; implicitAnimations["Scale"] = scaleGroup; // Apply to all visuals foreach (var child in _root.Children) { child.ImplicitAnimations = implicitAnimations; } } private void CircleLayout_Click(object sender, RoutedEventArgs e) { // Simply change offsets - animations trigger automatically double theta = 0; float radius = 200; float centerX = 300; float centerY = 300; foreach (var child in _root.Children) { double thetaRadians = theta * Math.PI / 180; // Offset change automatically triggers implicit animation child.Offset = new Vector3( (float)(radius * Math.Cos(thetaRadians)) + centerX, (float)(radius * Math.Sin(thetaRadians)) + centerY, 0); theta += 36; // 360 / 10 items } } private void ToggleScale_Click(object sender, RoutedEventArgs e) { foreach (var child in _root.Children) { // Scale change automatically triggers implicit animation (with rotation) child.Scale = child.Scale == Vector3.One ? new Vector3(0.5f, 0.5f, 1.0f) : Vector3.One; } } } ``` ### Expression Functions - Mathematical Operations Static helper functions for building complex mathematical expressions in a type-safe manner. ```csharp using ExpressionBuilder; using Microsoft.UI.Composition; using Microsoft.UI.Xaml.Hosting; using System.Numerics; using EF = ExpressionBuilder.ExpressionFunctions; public class AdvancedExpressionExamples { private Compositor _compositor; public void CreateBouncingBallExpression(Visual ballVisual, CompositionPropertySet gravityProps) { var propsRef = gravityProps.GetReference(); var visualRef = ballVisual.GetReference(); // Complex physics expression using multiple functions // Clamp ball position between floor and ceiling var groundLevel = 500.0f; var ceilingLevel = 0.0f; var velocityRef = propsRef.GetScalarProperty("Velocity"); var timeRef = propsRef.GetScalarProperty("Time"); // Position = Max(Min(initialY + velocity * time + 0.5 * gravity * time^2, ground), ceiling) var gravity = -980.0f; var positionExpression = EF.Max( EF.Min( visualRef.Offset.Y + velocityRef * timeRef + 0.5f * gravity * EF.Pow(timeRef, EF.Constant(2.0f)), EF.Constant(groundLevel) ), EF.Constant(ceilingLevel) ); ballVisual.StartAnimation("Offset.Y", positionExpression); } public void CreateColorTransitionExpression(SpriteVisual visual, CompositionPropertySet props) { var propsRef = props.GetReference(); var progressRef = propsRef.GetScalarProperty("Progress"); // Color lerp from blue to red based on progress var startColor = Vector4.Create(0, 0, 1, 1); // Blue var endColor = Vector4.Create(1, 0, 0, 1); // Red // ColorLerp creates smooth color transitions var colorExpression = EF.ColorLerp( EF.ColorRgb(startColor.X * 255, startColor.Y * 255, startColor.Z * 255), EF.ColorRgb(endColor.X * 255, endColor.Y * 255, endColor.Z * 255), progressRef ); // Apply to brush color var brush = (CompositionColorBrush)visual.Brush; brush.StartAnimation("Color", colorExpression); } public void CreateWaveExpression(Visual waveVisual, CompositionPropertySet timeProps) { var timeRef = timeProps.GetReference(); var time = timeRef.GetScalarProperty("ElapsedTime"); var visualRef = waveVisual.GetReference(); // Wave motion using sine function // y = amplitude * sin(frequency * time + phase) var amplitude = 100.0f; var frequency = 2.0f; var centerY = 200.0f; var waveExpression = centerY + amplitude * EF.Sin(frequency * time); waveVisual.StartAnimation("Offset.Y", waveExpression); } public void CreateDistanceBasedOpacity(Visual followVisual, Visual targetVisual) { var followerRef = followVisual.GetReference(); var targetRef = targetVisual.GetReference(); // Calculate distance between visuals var distance = EF.Distance(followerRef.Offset, targetRef.Offset); var maxDistance = 500.0f; // Opacity decreases with distance: opacity = 1 - (distance / maxDistance) var opacityExpression = EF.Max( 0.0f, 1.0f - (distance / maxDistance) ); followVisual.StartAnimation("Opacity", opacityExpression); } } ``` ### InteractionTracker - Gesture-Driven Animations System for creating gesture-driven, inertia-based interactions with customizable motion equations and boundaries. ```csharp using ExpressionBuilder; using Microsoft.UI.Composition; using Microsoft.UI.Composition.Interactions; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Hosting; using Microsoft.UI.Xaml.Input; using System.Numerics; public sealed partial class InteractionTrackerPage : Page { private Compositor _compositor; private InteractionTracker _tracker; private VisualInteractionSource _interactionSource; private SpriteVisual _contentVisual; private void Page_Loaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; // Create content visual _contentVisual = _compositor.CreateSpriteVisual(); _contentVisual.Size = new Vector2(400, 2000); // Tall scrollable content _contentVisual.Brush = _compositor.CreateColorBrush(Colors.LightBlue); ElementCompositionPreview.SetElementChildVisual(scrollContainer, _contentVisual); // Create InteractionTracker _tracker = InteractionTracker.Create(_compositor); _tracker.MinPosition = new Vector3(0, -1500, 0); // Max scroll up _tracker.MaxPosition = new Vector3(0, 0, 0); // Starting position // Bind content visual offset to tracker position var trackerRef = _tracker.GetReference(); _contentVisual.StartAnimation("Offset", trackerRef.Position); // Create interaction source from XAML element _interactionSource = VisualInteractionSource.Create( ElementCompositionPreview.GetElementVisual(scrollContainer)); // Configure manipulation behavior _interactionSource.ManipulationRedirectionMode = VisualInteractionSourceRedirectionMode.CapableTouchpadAndPointerWheel; _interactionSource.PositionYSourceMode = InteractionSourceMode.EnabledWithInertia; // Attach interaction source to tracker _tracker.InteractionSources.Add(_interactionSource); // Add inertia modifiers for bounce effect at boundaries ConfigureInertiaModifiers(); } private void ConfigureInertiaModifiers() { // Create bounce-back modifier at max position (top) InteractionTrackerInertiaRestingValue maxModifier = InteractionTrackerInertiaRestingValue.Create(_compositor); var trackerRef = _tracker.GetReference(); // Condition: activate when at or past max boundary maxModifier.SetCondition(trackerRef.Position.Y >= trackerRef.MaxPosition.Y); // Resting value: snap back to max position maxModifier.SetRestingValue(trackerRef.MaxPosition.Y); // Create bounce-back modifier at min position (bottom) InteractionTrackerInertiaRestingValue minModifier = InteractionTrackerInertiaRestingValue.Create(_compositor); // Condition: activate when at or past min boundary minModifier.SetCondition(trackerRef.Position.Y <= trackerRef.MinPosition.Y); // Resting value: snap back to min position minModifier.SetRestingValue(trackerRef.MinPosition.Y); // Apply modifiers to Y-axis _tracker.ConfigurePositionYInertiaModifiers(new[] { maxModifier, minModifier }); } private void ResetPosition_Click(object sender, RoutedEventArgs e) { // Programmatically animate tracker to position var resetPosition = new Vector3(0, 0, 0); var trackerRef = _tracker.GetReference(); // Create animation to target position var resetExpression = ExpressionFunctions.Vector3(0, 0, 0); _tracker.TryUpdatePositionWithAnimation(resetExpression); } } ``` ### CompositionImage - Managed Image Control High-performance image control using composition surfaces with automatic loading, caching, and fade-in animations. ```csharp using SamplesCommon; using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; // XAML usage with databinding // <SamplesCommon:CompositionImage // x:Name="heroImage" // ImageUrl="{Binding PhotoUrl}" // PlaceholderUrl="ms-appx:///Assets/placeholder.png" // Width="400" Height="400" // Stretch="UniformToFill" /> public sealed partial class ImageGalleryPage : Page { private CompositionImage _imageControl; public ImageGalleryPage() { InitializeComponent(); // Initialize ImageLoader for app Compositor compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; ImageLoader.Initialize(compositor); } private void LoadDynamicImage() { // Programmatic creation _imageControl = new CompositionImage { ImageUrl = "https://example.com/photo.jpg", PlaceholderUrl = "ms-appx:///Assets/placeholder.png", Width = 300, Height = 300, Stretch = CompositionStretch.UniformToFill }; imageContainer.Children.Add(_imageControl); // Image automatically loads with fade-in animation // Placeholder shows until image loads } private void UpdateImage(string newUrl) { // Change image - automatically handles crossfade heroImage.ImageUrl = newUrl; } private void Page_Unloaded(object sender, RoutedEventArgs e) { // Dispose resources when page unloads _imageControl?.Dispose(); } } ``` ### Effect Brushes - Blur and Blend Effects Creating and animating effects using Win2D effect graphs with composition brushes. ```csharp using Microsoft.Graphics.Canvas.Effects; using Microsoft.UI; using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Hosting; using System; using Windows.UI; public sealed partial class EffectsPage : Page { private Compositor _compositor; private SpriteVisual _effectVisual; private CompositionEffectBrush _effectBrush; private void Page_Loaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; // Build effect graph var blurEffect = new GaussianBlurEffect { Name = "Blur", BlurAmount = 0.0f, BorderMode = EffectBorderMode.Hard, Source = new CompositionEffectSourceParameter("BackdropSource") }; var saturationEffect = new SaturationEffect { Name = "Saturation", Saturation = 1.0f, Source = blurEffect }; var tintEffect = new ColorSourceEffect { Name = "Tint", Color = Color.FromArgb(128, 255, 255, 255) }; var blendEffect = new BlendEffect { Background = saturationEffect, Foreground = tintEffect, Mode = BlendEffectMode.SoftLight }; // Create effect factory with animatable properties var effectFactory = _compositor.CreateEffectFactory( blendEffect, new[] { "Blur.BlurAmount", "Saturation.Saturation", "Tint.Color" } ); // Create effect brush _effectBrush = effectFactory.CreateBrush(); _effectBrush.SetSourceParameter("BackdropSource", _compositor.CreateBackdropBrush()); // Apply to visual _effectVisual = _compositor.CreateSpriteVisual(); _effectVisual.Size = new Vector2(400, 400); _effectVisual.Brush = _effectBrush; ElementCompositionPreview.SetElementChildVisual(effectContainer, _effectVisual); } private void AnimateBlur(float targetBlur) { // Animate blur amount ScalarKeyFrameAnimation blurAnimation = _compositor.CreateScalarKeyFrameAnimation(); blurAnimation.InsertKeyFrame(1.0f, targetBlur); blurAnimation.Duration = TimeSpan.FromSeconds(0.5); _effectBrush.Properties.StartAnimation("Blur.BlurAmount", blurAnimation); } private void AnimateSaturation(float targetSaturation) { // Animate saturation ScalarKeyFrameAnimation saturationAnimation = _compositor.CreateScalarKeyFrameAnimation(); saturationAnimation.InsertKeyFrame(1.0f, targetSaturation); saturationAnimation.Duration = TimeSpan.FromSeconds(0.5); _effectBrush.Properties.StartAnimation("Saturation.Saturation", saturationAnimation); } private void AnimateTintColor(Color targetColor) { // Animate tint color ColorKeyFrameAnimation colorAnimation = _compositor.CreateColorKeyFrameAnimation(); colorAnimation.InsertKeyFrame(1.0f, targetColor); colorAnimation.Duration = TimeSpan.FromSeconds(0.5); _effectBrush.Properties.StartAnimation("Tint.Color", colorAnimation); } private void BlurSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e) { if (_effectBrush != null) { AnimateBlur((float)e.NewValue); } } } ``` ### Lighting - Point Lights and Spot Lights Creating dynamic lighting effects with point lights, spot lights, and ambient lights that respond to visual elements. ```csharp using Microsoft.UI; using Microsoft.UI.Composition; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Hosting; using Microsoft.UI.Xaml.Input; using System.Numerics; using Windows.UI; public sealed partial class LightingPage : Page { private Compositor _compositor; private PointLight _pointLight; private SpotLight _spotLight; private AmbientLight _ambientLight; private SpriteVisual _sceneRoot; private void Page_Loaded(object sender, RoutedEventArgs e) { _compositor = ElementCompositionPreview.GetElementVisual(this).Compositor; // Create scene container _sceneRoot = _compositor.CreateSpriteVisual(); _sceneRoot.Size = new Vector2(800, 600); ElementCompositionPreview.SetElementChildVisual(lightingContainer, _sceneRoot); // Create ambient light for base illumination _ambientLight = _compositor.CreateAmbientLight(); _ambientLight.Color = Colors.Gray; _ambientLight.Intensity = 0.3f; _ambientLight.Targets.Add(_sceneRoot); // Create point light (omnidirectional) _pointLight = _compositor.CreatePointLight(); _pointLight.Color = Colors.White; _pointLight.Intensity = 1.0f; _pointLight.Offset = new Vector3(400, 300, 100); // Z determines distance from surface _pointLight.CoordinateSpace = _sceneRoot; _pointLight.Targets.Add(_sceneRoot); // Create spot light (directional cone) _spotLight = _compositor.CreateSpotLight(); _spotLight.Color = Colors.Yellow; _spotLight.Intensity = 2.0f; _spotLight.InnerConeAngleInDegrees = 30; _spotLight.OuterConeAngleInDegrees = 45; _spotLight.Offset = new Vector3(200, 100, 200); _spotLight.Direction = new Vector3(0, 0, -1); // Point down at surface _spotLight.CoordinateSpace = _sceneRoot; _spotLight.Targets.Add(_sceneRoot); // Create objects that receive lighting CreateLitObjects(); } private void CreateLitObjects() { // Create several sphere visuals that will be lit for (int i = 0; i < 5; i++) { SpriteVisual sphere = _compositor.CreateSpriteVisual(); sphere.Size = new Vector2(100, 100); sphere.Offset = new Vector3(i * 150 + 50, 250, 0); // Use color brush to receive lighting sphere.Brush = _compositor.CreateColorBrush(Colors.LightGray); _sceneRoot.Children.InsertAtTop(sphere); } } private void Container_PointerMoved(object sender, PointerRoutedEventArgs e) { // Move point light to follow pointer var point = e.GetCurrentPoint(lightingContainer); _pointLight.Offset = new Vector3( (float)point.Position.X, (float)point.Position.Y, 100 // Keep constant distance from surface ); } private void AnimateLightIntensity() { // Pulse light intensity ScalarKeyFrameAnimation intensityAnimation = _compositor.CreateScalarKeyFrameAnimation(); intensityAnimation.InsertKeyFrame(0.0f, 0.5f); intensityAnimation.InsertKeyFrame(0.5f, 2.0f); intensityAnimation.InsertKeyFrame(1.0f, 0.5f); intensityAnimation.Duration = TimeSpan.FromSeconds(2); intensityAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _pointLight.StartAnimation("Intensity", intensityAnimation); } private void RotateSpotLight() { // Rotate spot light in circle var centerX = 400f; var centerY = 300f; var radius = 200f; // Animate offset in circular path Vector3KeyFrameAnimation offsetAnimation = _compositor.CreateVector3KeyFrameAnimation(); for (float angle = 0; angle <= 360; angle += 30) { float radians = angle * (float)Math.PI / 180f; float x = centerX + radius * (float)Math.Cos(radians); float y = centerY + radius * (float)Math.Sin(radians); offsetAnimation.InsertKeyFrame(angle / 360f, new Vector3(x, y, 200)); } offsetAnimation.Duration = TimeSpan.FromSeconds(5); offsetAnimation.IterationBehavior = AnimationIterationBehavior.Forever; _spotLight.StartAnimation("Offset", offsetAnimation); // Animate direction to always point at center ExpressionAnimation directionExpression = _compositor.CreateExpressionAnimation(); directionExpression.Expression = "Vector3.Normalize(Vector3(400, 300, 0) - spotLight.Offset)"; directionExpression.SetReferenceParameter("spotLight", _spotLight); _spotLight.StartAnimation("Direction", directionExpression); } } ``` ## Summary and Integration The Windows Input and Composition Samples demonstrates production-ready patterns for building modern Windows applications with rich visual experiences. The primary use cases include creating responsive UI with gesture-driven animations (using InteractionTracker), implementing smooth visual transitions and parallax effects (using ExpressionAnimations), building immersive effects like acrylic and depth (using effect brushes and lighting), and creating fluid layout animations (using implicit animations). The project serves as both a learning resource and a component library that can be directly integrated into production applications. Integration follows standard Windows App SDK patterns where developers reference the Microsoft.UI.Composition and Microsoft.UI.Input namespaces, use ElementCompositionPreview as the bridge between XAML and composition layers, and optionally adopt the ExpressionBuilder library for type-safe expression authoring. The SamplesCommon utilities (BackDrop, CompositionImage, ImageLoader) can be included as reusable components in any WinUI 3 project. The samples demonstrate proper lifecycle management including compositor initialization, device lost recovery, animation cleanup, and memory disposal. Developers can extract individual sample implementations as starting templates or use the full gallery structure as a reference for organizing complex composition-based applications with multiple interactive demonstrations.