⚠️ Warning: This website is still being developed. Code examples, videos, and links may be broken while I continue to work on it. -- Scott, May 10, 2020
Resources for visualizing data using C# and the .NET platform

Drawing with SkiaSharp & OpenGL

The drawing with SkiaSharp page described how to use Skia to render graphics on a Bitmap and display them in a Picturebox. In this project we will use the skglControl user control to create an OpenGL-accelerated surface for us to draw on. OpenGL will offer an excellent performance enhancement, especially when creating large or full-screen animations.

Drawing Library 10 lines 1k lines 10k lines 100k lines
System.Drawing 0.614 ms 28.350 ms 278.477 ms 2.834 sec
SkiaSharp 12.777 ms 97.011 ms 352.343 ms 3.493 sec
SkiaSharp + OpenGL 2.973 ms 6.588 ms 40.765 ms 422.217 ms

Code

  • You must target 32-bit or 64-bit, not "any CPU"
  • Install the SkiaSharp.Views.WindowsForms NuGet package
  • Drag a SKGLControl onto the form

Render In the PaintSurface Event

The SKGLControl you created has a PaintSurface event that can be used for rendering. This event is especially useful because the SKSurface is passed in as an argument.

private void skglControl1_PaintSurface(object sender, SkiaSharp.Views.Desktop.SKPaintGLSurfaceEventArgs e)
{
    e.Surface.Canvas.Clear(SKColor.Parse("#003366"));
    for (int i = 0; i < lineCount; i++)
    {
        var paint = new SKPaint
        {
            Color = new SKColor(
                red: (byte)rand.Next(255),
                green: (byte)rand.Next(255),
                blue: (byte)rand.Next(255),
                alpha: (byte)rand.Next(255)),
            StrokeWidth = rand.Next(1, 10),
            IsAntialias = true
        };
        e.Surface.Canvas.DrawLine(
            x0: rand.Next(skglControl1.Width),
            y0: rand.Next(skglControl1.Height),
            x1: rand.Next(skglControl1.Width),
            y1: rand.Next(skglControl1.Height),
            paint: paint);
    }
}

Trigger a Render

Rendering only occurs when our control is re-painted, but painting doesn't happen continuously. To trigger renders we must indicate a new paint is required by calling the control's invalidate method.

skglControl1.Invalidate();

The screen typically updates around 60 frames per second. If your render method creates frames faster than that, you might draw on and clear several frames before the first one is actually displayed. To force a display between multiple renders you can call DoEvents to ensure every render gets drawn to the screen.

for (int i = 0; i < 10; i++)
{
    skglControl1.Invalidate();
    Application.DoEvents();
}

⚠️ Warning: DoEvents() blocks the GUI thread while the application is redrawn. If you call this method too frequently your application will become slow.

Render Continuously

To create animations you can call Invalidate using a Timer set to 1ms:

private void timer1_Tick(object sender, EventArgs e)
{
    skglControl1.Invalidate();
}

Source Code

Source code for this project is on GitHub: /examples/drawing/alternate/SkiaSharpOpenGLBenchmark