是否可以通过 D3DImage 和 ANGLE 将 OpenGL ES 代码与 WPF 应用程序一起使用?

Posted

技术标签:

【中文标题】是否可以通过 D3DImage 和 ANGLE 将 OpenGL ES 代码与 WPF 应用程序一起使用?【英文标题】:Is it possible to use OpenGL ES code with a WPF application via a D3DImage and ANGLE? 【发布时间】:2013-10-07 02:57:27 【问题描述】:

摘要(TL:DR 版本)

最终,我们的目标是能够在 WPF 应用程序中本地使用 OpenGL ES 代码(即不是 SharpGL 等)并且没有 Airspace 或驱动程序问题,这可能使用 Google 的 ANGLE 项目。

背景:

我喜欢 OpenGL over DirectX 的一个原因是它的跨平台能力。它对 OS X 和 Linux 以及通过 ES 在 androidios 上都有出色的支持。然而,在 Windows 上,使用它会受到驱动程序问题的影响,或者更糟糕的是,很多卡根本没有正确实现它。

输入谷歌的ANGLE project,或Almost-Native-Graphics-Layer-Engine。

ANGLE 是围绕 Direct3D 实现的 OpenGL ES 2.0 包装器,这意味着您可以编写 OpenGL ES 2.0 代码以在 Windows 上运行,而无需实际的 OpenGL 驱动程序。它不仅通过了 ES 兼容性测试,而且实际上是 Chrome 进行所有图形渲染的方式,包括 WebGL,因此它绝对是一项经过验证的技术。

问题:

我们知道 WPF 有一个 D3DImage 控件,它允许您在 WPF 中托管 Direct3D 渲染,并且它应该通过将其输出正确地堆肥到 WPF 渲染线程来消除空域问题。我的问题是,由于 ANGLE 是通过 Direct3D 实现的,而 D3DImage 是 Direct3D 渲染的目标,是否可以将两者结合起来,允许我们编写 OpenGL ES 代码并将其托管在 Windows 上的 WPF 应用程序中,所有这些都没有驱动程序或空域问题?

这将是我们的“圣杯”。

但是,由于 ANGLE 想要使用它自己的控件,因此我一直在让 ANGLE 将其渲染定位在由 D3DImage 控件创建的 D3D 表面上。我不确定这是否可能。我什至找不到任何人讨论这个问题的任何文章或参考资料,更不用说尝试了。

再次明确一点,我们的目标是让我们共享的跨平台 OpenGL(或 ES)代码在 WPF 应用程序中工作,而不会出现空域问题或 OpenGL 驱动程序要求。我对使用 ANGLE/D3DImage 的建议就是……尝试。到目前为止,这是我想出的“手段”,但这只是实现我们目标的潜在手段,而不是目标本身。任何其他能让我们获得相同解决方案的东西都将受到欢迎。

【问题讨论】:

您在这个问题上还需要帮助吗?如果是这样,您是否需要能够在同一区域上结合 WPF 和 OpenGL 渲染(即,将 OpenGL 与 WPF 混合)或者您只是希望将 OpenGL 嵌入 WPF 窗口中?后者对于OpenTK.GLControl 和WindowsFormsHost 来说是微不足道的。前者需要一些工作(但仍然可能。) 是的,我仍然希望在这里得到帮助。虽然不,我们不需要在同一区域结合 WPF 渲染和 OpenGL,如果我是正确的,您的 WinFormsHost 方法仍然会成为 AirSpace 问题的受害者。再说一次,如果我们在同一个窗口中的 WPF 部分不会与 OpenGL 部分重叠,那可能是一个解决方案。不尝试就不确定。你能用一个使用 OpenTK.GLControl 的例子来发布一个正确的答案吗?如果是这样,我会将您的标记为已接受。 另一条评论...再次,我们想简单地重用我们已经存在的 OpenGL ES 渲染代码。我们不想将它翻译到另一个库等。(一般的设置代码当然可以,而且通常是特定于平台的,所以这很好。我的意思是实际的绘图调用自己,所以它在 WPF、iOS 上看起来相同, Android 等,并尽可能接近原生速度。 我正在准备一个示例项目,展示如何在 WPF 中使用 OpenTK.GLControl 使用 OpenGL OpenGL ES / ANGLE。 【参考方案1】:

我上传了一个github project,它演示了如何通过OpenTK.GLControl 将OpenGL 渲染集成到WPF 应用程序中。

代码非常简单:

    WindowsFormsHost 添加到 WPF 应用程序 构造一个OpenTK.GLControl 并将其附加到WindowsFormsHost 为桌面 OpenGL 上下文传递 GraphicsContextFlags.Default 为 OpenGL ES (ANGLE) 上下文传递 GraphicsContextFlags.Embedded 使用普通 OpenGL 或 OpenGL ES 命令进行渲染

提示:OpenTK 和 OpenTK.GLControl 也可用作 NuGet 包。明天将发布一个新版本,改进了 ANGLE 支持。

请注意,WindowsFormsHost 方法受空域限制。如果这是一个问题,请参阅my answer here 以获得解决方案。

// This code is public domain
#define USE_ANGLE

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using OpenTK;
using OpenTK.Graphics;

#if USE_ANGLE
using OpenTK.Graphics.ES20;
#else
using OpenTK.Graphics.OpenGL;
#endif

namespace WPF.Angle

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    
        GLControl glControl;

        public MainWindow()
        
            InitializeComponent();
        

        private void WindowsFormsHost_Initialized(object sender, EventArgs e)
        
            var flags = GraphicsContextFlags.Default;
#if USE_ANGLE
            flags = GraphicsContextFlags.Embedded;
#endif
            glControl = new GLControl(new GraphicsMode(32, 24), 2, 0, flags);
            glControl.MakeCurrent();
            glControl.Paint += GLControl_Paint;
            glControl.Dock = DockStyle.Fill;
            (sender as WindowsFormsHost).Child = glControl;
        

        private void GLControl_Paint(object sender, PaintEventArgs e)
        
            GL.ClearColor(
                (float)Red.Value,
                (float)Green.Value,
                (float)Blue.Value,
                1);
            GL.Clear(
                ClearBufferMask.ColorBufferBit |
                ClearBufferMask.DepthBufferBit |
                ClearBufferMask.StencilBufferBit);

            glControl.SwapBuffers();
        

        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        
            glControl.Invalidate();
        
    

【讨论】:

两件事...一,您没有提供指向您的 GitHub 项目的链接,二,再次,我们想使用我们已经存在的 C 文件,而不是兼容的工具包(除非允许我们使用我们现有的代码。)同样,问题在于跨平台代码,而不是为了 OpenGL 而使用 OpenGL。希望这是有道理的,如果是这样,你可以解决它。 你是对的,我已经添加了missing link to github。此代码演示如何在 WPF 窗口中创建 OpenGL / OpenGL ES 上下文。之后的渲染方式取决于您 - 上下文并不关心您是否完全使用 C、C# 或其他东西。例如,您可以通过 [DllImport] 调用您的 C 渲染器。这能回答你的问题吗? 嗯...我相信是这样,但我必须看看你的示例项目,看看它做了什么。尽管如此,由于您提供的信息,我还是会给您答案。如果我有任何问题,你有没有机会在你的 GitHub 项目中提供联系信息?如果我们使用您提供的内容,我们甚至会根据您的需要为您提供归属。 @TheFiddler 你说:“你可以通过 [DllImport] 调用你的 C 渲染器”。您是否认为可以反过来,例如将 WPF (GLControl) 的窗口句柄传递给 C++ 渲染。基本上我有渲染代码,我只想要一个可以渲染的窗口。 OpenGL 使用线程本地存储来存储其上下文。在特定线程上调用 GLControl.MakeCurrent() 后,您可以从 C# 或 C++ 在该线程上发出 OpenGL 命令,而不会出现任何问题。不需要窗口句柄。更多信息请查看GraphicsContext documentation。

以上是关于是否可以通过 D3DImage 和 ANGLE 将 OpenGL ES 代码与 WPF 应用程序一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

dotnet 读 WPF 源代码笔记 为什么加上 BooleanBoxes 类

判断线段与圆是否相交

MediaCodec 低延时解码

Qt 是不是使用 opengl=angle 修复支持不支持 opengl 2.0 的 Windows 客户端?

matlab中图像旋转

Canvas 入门8 物理效果