在CPF裡使用OpenGL做跨平臺桌面應用開發

2023-12-05 15:01:47

CPF 是開源的C#跨平臺UI框架,支援使用OpenGL來渲染,可以用來硬體加速播放視訊或者顯示3D模型

實現原理其實就是Skia用OpenGL後端,Skia裡繫結GLView的OpenGL紋理,將紋理作為Skia的影象混合繪製。

在CPF裡使用OpenGL,不能選擇NetCore3.0和Net4,需要選擇Netcore3.1以及之後的版本。

Nuget裡安裝最新版的CPF。另外安裝Silk.NET或者OpenTK來呼叫OpenGL繪製。

Program裡需要開啟GPU,設定 UseGPU = true

    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            Application.Initialize(
                (OperatingSystemType.Windows, new WindowsPlatform(), new SkiaDrawingFactory { UseGPU = true })
                , (OperatingSystemType.OSX, new CPF.Mac.MacPlatform(), new SkiaDrawingFactory { UseGPU = true })//如果需要支援Mac才需要
                , (OperatingSystemType.Linux, new CPF.Linux.LinuxPlatform(), new SkiaDrawingFactory { UseGPU = true })//如果需要支援Linux才需要
            );
            Application.Run(new Window2_1_Colors());
        }
    }

介面上新增 CPF.Skia.GLView 控制元件,GLLoaded為GL載入完成事件,GLRender為GL繪製事件。OpenGL就在這兩個事件裡處理

            Children.Add(new WindowFrame(this, new GLView
            {
                Width = "100%",
                Height = "100%",
                [nameof(GLView.GLLoaded)] = new CommandDescribe((s, e) => GLLoaded((GLView)s, (GLEventArgs)e)),
                [nameof(GLView.GLRender)] = new CommandDescribe((s, e) => GLRender((GLView)s, (GLEventArgs)e)),
                [nameof(GLView.MouseDown)] = new CommandDescribe((s, e) => MouseEvent((GLView)s, (MouseEventArgs)e)),
                [nameof(GLView.MouseUp)] = new CommandDescribe((s, e) => MouseEvent((GLView)s, (MouseEventArgs)e)),
                [nameof(GLView.MouseMove)] = new CommandDescribe((s, e) => MouseEvent((GLView)s, (MouseEventArgs)e)),
            })
            {
                MaximizeBox = true
            });

Silk.Net初始化API

        GL gl;//可以儲存為全域性的欄位
        void GLLoaded(GLView view, GLEventArgs args)
        {
            gl = GL.GetApi(args.Context.GetProcAddress);
        }

OpenTk初始化API

    class Context : OpenTK.IBindingsContext
    {//定義API繫結的上下文
        public IGlContext context;
        public IntPtr GetProcAddress(string procName)
        {
            return context.GetProcAddress(procName);
        }
    }

        void GLLoaded(GLView view, GLEventArgs args)
        {//初始化一次就行
             GL.LoadBindings(new Context { context = args.Context });
        }

在GLRender事件裡繪製。預設情況下GLRender不會一直呼叫,因為繪製方式不是遊戲那種實時重新整理的。需要重新整理的時候要主動呼叫Invalidate(),或者用定時器來實時呼叫Invalidate()。

        void GLRender(GLView view, GLEventArgs args)
        {
            gl.Enable(GLEnum.DepthTest);//開啟深度測試
            gl.DepthMask(true);

            //其他繪製程式碼。。。。


            //開啟深度測試之後要關閉,否則會無法顯示介面,同樣的,如果開啟了其他功能,繪製結束後記得關閉,否則可能影響介面繪製。因為和介面共用OpenGL的上下文。
            gl.Disable(GLEnum.DepthTest);
        }

 

具體OpenGL的繪製教學你可以直接找Silk.NET或者OpenTK的教學就行。

執行效果

 

案例原始碼下載:CPF_OpenGL

CPF開源地址:https://gitee.com/csharpui/CPF