You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SkiaSharp的Silk.NET窗口出现闪烁问题求助

Silk.NET + SkiaSharp 窗口闪烁问题

我想在Silk.NET窗口里用SkiaSharp做一个能改变矩形圆角的程序,但运行时窗口一直闪烁。

我的代码:

using Silk.NET.Windowing;
using Silk.NET.OpenGL;
using SkiaSharp;

class Program
{
    private static IWindow window;
    private static GL gl;
    private static GRGlInterface grgInterface;
    private static GRContext grContext;
    private static SKSurface surface;
    private static SKCanvas canvas;
    private static GRBackendRenderTarget renderTarget;
    private static SKPaint TestBrush;

    static void Main(string[] args)
    {
        var options = WindowOptions.Default;
        options.Size = new Silk.NET.Maths.Vector2D<int>(800, 600);
        options.Title = "Silk.NET with SkiaSharp Triangle";

        window = Window.Create(options);

        window.Load += OnLoad;
        window.Render += OnRender;

        window.Run();
    }

    private static void OnLoad()
    {
        grgInterface = GRGlInterface.Create();
        grContext = GRContext.CreateGl(grgInterface);
        renderTarget = new GRBackendRenderTarget(window.Size.X, window.Size.Y, 0, 8, new GRGlFramebufferInfo(0, (uint)SizedInternalFormat.Rgba8));
        surface = SKSurface.Create(grContext, renderTarget, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888);
        canvas = surface.Canvas;

        TestBrush = new SKPaint
        {
            Color = SKColors.White,
            IsAntialias = true,
            Style = SKPaintStyle.Fill,
            TextAlign = SKTextAlign.Center,
            TextSize = 24
        };
    }

    private static void OnRender(double delta)
    {
        canvas.Clear(SKColors.CornflowerBlue);

        TestBrush.Color = SKColors.White;
        canvas.DrawRoundRect(new SKRoundRect(new SKRect(0, 0, 256, 256), (float)Math.Max(Math.Sin(-delta) * 128.0f, 0)), TestBrush);

        TestBrush.Color = SKColors.Black;
        canvas.DrawText("Hello, World!", 128, 300, TestBrush);

        canvas.Flush();
        window.SwapBuffers();
    }
}

环境说明:使用最新版Silk.NET 2.21和SkiaSharp 2.28.8,代码改编自一个OpenTK的示例(该示例运行正常)。


问题原因及解决办法

闪烁的核心原因是SkiaSharp与Silk.NET的GL上下文未同步,且缺少帧缓冲清除、垂直同步等关键步骤,导致前后帧残留或帧交换时机错位。

解决步骤:

  1. 绑定Silk.NET的GL上下文给SkiaSharp
    必须让Skia使用Silk.NET创建的GL实例,避免上下文不一致。
  2. 开启垂直同步
    让帧交换与显示器刷新同步,消除大部分闪烁。
  3. 渲染前清除GL缓冲
    确保每一帧起始状态干净,避免残留上一帧内容。
  4. 强制Skia提交所有渲染命令
    确保Skia的绘制命令完全提交到GL后再交换缓冲。

修复后的完整代码

using Silk.NET.Windowing;
using Silk.NET.OpenGL;
using SkiaSharp;

class Program
{
    private static IWindow window;
    private static GL gl;
    private static GRGlInterface grgInterface;
    private static GRContext grContext;
    private static SKSurface surface;
    private static SKCanvas canvas;
    private static GRBackendRenderTarget renderTarget;
    private static SKPaint TestBrush;

    static void Main(string[] args)
    {
        var options = WindowOptions.Default;
        options.Size = new Silk.NET.Maths.Vector2D<int>(800, 600);
        options.Title = "Silk.NET with SkiaSharp Triangle";
        options.IsVsync = true; // 开启垂直同步

        window = Window.Create(options);

        window.Load += OnLoad;
        window.Render += OnRender;

        window.Run();
    }

    private static void OnLoad()
    {
        // 获取Silk.NET的GL实例并设置初始清除颜色
        gl = window.CreateOpenGL();
        gl.ClearColor(SKColors.CornflowerBlue.Red / 255f, SKColors.CornflowerBlue.Green / 255f, SKColors.CornflowerBlue.Blue / 255f, 1f);

        // 传入Silk.NET的GL句柄创建Skia的GL接口
        grgInterface = GRGlInterface.Create(gl.Handle);
        grContext = GRContext.CreateGl(grgInterface);
        renderTarget = new GRBackendRenderTarget(window.Size.X, window.Size.Y, 0, 8, new GRGlFramebufferInfo(0, (uint)SizedInternalFormat.Rgba8));
        surface = SKSurface.Create(grContext, renderTarget, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888);
        canvas = surface.Canvas;

        TestBrush = new SKPaint
        {
            Color = SKColors.White,
            IsAntialias = true,
            Style = SKPaintStyle.Fill,
            TextAlign = SKTextAlign.Center,
            TextSize = 24
        };
    }

    private static void OnRender(double delta)
    {
        // 先清除GL颜色缓冲
        gl.Clear(ClearBufferMask.ColorBufferBit);

        canvas.Clear(SKColors.CornflowerBlue);

        TestBrush.Color = SKColors.White;
        canvas.DrawRoundRect(new SKRoundRect(new SKRect(0, 0, 256, 256), (float)Math.Max(Math.Sin(-delta) * 128.0f, 0)), TestBrush);

        TestBrush.Color = SKColors.Black;
        canvas.DrawText("Hello, World!", 128, 300, TestBrush);

        // 强制Skia提交所有渲染命令到GL
        canvas.Flush();
        grContext.Flush();

        window.SwapBuffers();
    }
}

内容的提问来源于stack exchange,提问作者AlexeyBobrovich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:47:27