Win2D Particles

One of the apps I am preparing has a particles adornment, I made the first version ‘solve version’ and now I have implemented the ‘code version’.


The CanvasAnimatedControl

This Win2D Control is like having XNA in UWP apps, you can subscribe the following events:

private void Initialize()
    MainCanvas.CreateResources += MainCanvas_CreateResources;
    MainCanvas.SizeChanged += MainCanvas_SizeChanged;
    MainCanvas.Update += MainCanvas_Update;
    MainCanvas.Draw += MainCanvas_Draw;

Where CreateResources is where you generate and download all the source images you will need in the other events. SizeChanged is just the base event to keep the bounds, Update is when you modify the position and effect of the particles, and finally the Draw event when you paint each particle in the control.

Particles Generator

Basically it has the following structure:

  1. Create the textures (small circles with blur)
  2. Create a List of particles at different positions.
  3. Add displacement with turbulente effect per particle. (turbulence gives more natural effect)
  4. Update Turbulence

And then draw the result each time.

Creating the Textures

In order to use only Win2D, I created 4 bitmaps (CanvasRenderTarget) of different sizes with a chained painting session where:

  1. Paint two circles in a canvas
  2. Apply blur effect to the previous canvas.
using (CanvasDrawingSession targetSession = canvas.CreateDrawingSession())
    targetSession.FillCircle(center, nextRadius, outerColor);
    targetSession.FillCircle(center, nextRadius - 6, innerColor);
var blurEffect = new GaussianBlurEffect() { BlurAmount = 2f };
CanvasRenderTarget blurredcanvas = new CanvasRenderTarget(device, viewportsize, viewportsize, parent.Dpi);
blurEffect.Source = canvas;
using (CanvasDrawingSession targetSession = blurredcanvas.CreateDrawingSession())

Each of these bitmaps will be used as sources of every particle drawing, which has a displacement with turbulence effect, when you apply this effect you must create a big viewport, 100 px in this case, because is drawn the original image and the displacement image, so to avoid this just create this safety viewport.

Decrease ‘float viewportsize = 100;’ if you want to watch the weird result.

Creating the Particles

Now we have the images let’s create the particles, you have to consider the window bounds and the size changes. I added a random orientation for each particle and if you want only falling particles:

public void CreateParticles(bool fall)
    particles = new List<Particle>();

    int i = -1;
    int minpos = minRadius * sizes * 2;
    while (++i < amountparticles)
        var x = generator.Next(minpos, (int)bounds.Width);
        var y = generator.Next(minpos, (int)bounds.Height);
        var s = generator.Next(0, sizes);
        var ox = generator.NextDouble() > 0.5 ? 1 : -1;
        var oy = fall ? 1 : generator.NextDouble() > 0.5 ? 1 : -1;

        var particle = new Particle(x, y,s,ox,oy, particleBitmaps[s], particlefall:fall);

As you see is just creating a list with random values for each property. In the constructor of each particle I add the effects.

Displacement with turbulence

random = generator.Next(2, 50);
factor = 0.7f * random / 10.0f;
var octaves = generator.Next(1, 5);
turbulence = new Transform2DEffect() { Source = new TurbulenceEffect() { Octaves = octaves } };
displacement = new DisplacementMapEffect() { Source = source, Displacement = turbulence };

The idea of the displacement is to displace and deform the particle according to the turbulence effect. If you want to see what is the turbulence, in the drawing session, draw the turbulence effect instead the displacement.

Update the turbulence

Now we have the turbulence created we have to move the particle around it is position using the following turbulence which also deforms the particle:

private void UpdateTurbulence(float elapsedTime)
    TurbulenceMatrix = Matrix3x2.CreateTranslation((float)Math.Cos(elapsedTime + random) * 2 - 2, (float)Math.Sin(elapsedTime) * 2 - 2);
    turbulence.TransformMatrix = TurbulenceMatrix;
    displacement.Amount = (float)Math.Sin(elapsedTime * factor) * random;

It is relative simple to create this environment, I have to recognize that in my 1320 goes slow, but in desktop works really well, I cannot assure is because the displacement effect, might be reducing the update times could be great so I let you go and test it.

I hope you enjoy the article and take the idea about how to create images/textures in Win2D and then apply to a CanvasAnimatedControl like in the XNA old ages so simplifies the code a lot.

And as always you have the code in the Particles2D project of my repo : Github

Follow me to know the latest code about Windows10 @juanpaexpedite


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s