• Silk.Net Opengl 创建基于WPF或者Winform 的显示控件


    背景:

    Silk.GL, 基于Net6.0 跨平台,微软封装的一套三维框架, 总的来说, 参考OpenTK, SharpGL,Vulkan ,DX 等等.

    因为基于WPF写的一些demo,每次额外弹出一个黑色窗口来显示内容,不是很爽,那么是否可以将其封装成一个控件,这样就挺方便的吧.

    成果展示:

    WPF中,在xaml中,引入该控件,

    2.显示,完美契合

     思路以及用到的知识点:

    需要掌握Windows窗口相关的知识,以及窗体变化之后,要捕捉的窗体事件. 因为每次这些窗体变换之后, 需要及时的更新SilkGL的窗口. 

    关键代码:

    1.将链接宿主和GL窗口的信息,抽象封装为一个接口

    1. public interface IHostWindow
    2. {
    3. IntPtr IParentHandle { get; set; } //宿主窗口句柄
    4. IntPtr ICurrentWHandle { get; set; }//当前的窗口句柄
    5. string IWindowTitle { get; set; } //通过Title来获取窗口,进行宿主
    6. void SetRecTangle(int x,int y,int w,int h);
    7. ///
    8. /// 初始化加载资源
    9. ///
    10. void InitSource();
    11. ///
    12. /// 展示窗口.
    13. ///
    14. void Show();
    15. ///
    16. /// 关闭的时候,释放一些资源
    17. ///
    18. void DisposeSource();
    19. Action FinishInitHandle { get; set; }
    20. }

     2.基于该接口,实现一个基类 HostBaseUIElement

    1. public class HostBaseUIElement : IHostWindow
    2. {
    3. public HostBaseUIElement()
    4. {
    5. WCount++;
    6. IWindowTitle += $"{WCount}";
    7. }
    8. public IntPtr IParentHandle { get; set; } = IntPtr.Zero;
    9. public IntPtr ICurrentWHandle { get; set; } = IntPtr.Zero;
    10. public string IWindowTitle { get; set; } = "";
    11. public Rectangle BounderBox = new Rectangle(0,0,10,10);
    12. ///
    13. /// 这里要做的就是,设置Title,ICurrentWHandle,IParentHandle默认不设置
    14. ///
    15. public static int WCount { get; set; } = 0;
    16. public Action FinishInitHandle { get; set; }
    17. public virtual void SetRecTangle(int x, int y, int w, int h)
    18. {
    19. BounderBox.X = x;
    20. BounderBox.Y = y;
    21. BounderBox.Width = w;
    22. BounderBox.Height = h;
    23. }
    24. public virtual void InitSource()
    25. {
    26. }
    27. public virtual void DisposeSource()
    28. {
    29. }
    30. public virtual void Show()
    31. {
    32. }
    33. }

    3.继承并实现自己的 SilkGL 控件,这里呢,我们引入GL控制类

    1. public class SilkGL: HostBaseUIElement
    2. {
    3. public SilkGL() : base() //调用Base来设置初始化.
    4. {
    5. IWindowTitle = $"Silk GL {WCount}";
    6. }
    7. ///
    8. /// GL窗口
    9. ///
    10. public IWindow window;
    11. ///
    12. /// GL对象
    13. ///
    14. public GL? gl
    15. {
    16. get
    17. {
    18. if (window == null) return null;
    19. return GL.GetApi(window);
    20. }
    21. }
    22. public override void InitSource()
    23. {
    24. var box = BounderBox;
    25. if (box.Width > 0 && box.Height > 0)
    26. {
    27. var options = WindowOptions.Default;
    28. options.Size = new Vector2D<int>(box.Width, box.Height);
    29. options.Title = IWindowTitle;
    30. window = Window.Create(options); //现在想办法,将Window的内容,渲染到UserControl上面去.
    31. window.Title = IWindowTitle;
    32. }
    33. }
    34. public override void Show()
    35. {
    36. window?.Run();
    37. }
    38. public override void DisposeSource()
    39. {
    40. window?.Close();
    41. }
    42. }

    4:这里可以进一步封装,,主要完成GL的,本身的一些事件的关联. 然后剩下的就是GL本身的绘制内容了.

     

    5.这里介绍一下使用方式:

    5.1,注意我画红线的部分

    5.2.后台代码,主要是通过这个SilkwpfName,拿到里面的gl对象,和对应的关键信息

     6.0,运行跑起来,就可以很好的做为一个WPF控件来使用了.

     一点扩展性和可以做的工作内容

    上面控件的设计方式,不单单是可以进行封装SilkGL,还可以封装OSG,VTK,Qt,PLC等等第三方的Windows窗口,只需要继承一下那个HostBaseUIElement 这个基础控件类即可,后续我思考把OSG的也弄一个进来,毕竟OSG的Earth还是蛮有意思的.

  • 相关阅读:
    【JS】JavaScript入门笔记第五弹之预解析、对象~
    SpringCould微服务保护01——Sentinel组件下载并使用
    CAD如何绘制六连环图案?CAD使用圆,椭圆,直线综合练习
    在Linux服务器中查找mysql的配置文件并修改其内容并保存,清空mysql8.0以上默认开启SSL的配置,防止odbc无法连接的问题
    基于springboot+vue的戒毒所人员管理系统毕业设计源码251514
    input_delay
    现代对称密码
    mojo语言 入门体验 环境安装
    灰色预测GM(1,1)
    Unity实现设计模式——命令模式
  • 原文地址:https://blog.csdn.net/sinat_36564005/article/details/126822076