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

Mar*_*eIV 9 opengl wpf direct3d opengl-es d3dimage

摘要(TL:DR版)

最终,我们的目标是能够在WPF应用程序中本地使用OpenGL ES代码(即不是SharpGL等),并且无需空域或驱动程序问题,可以使用Google的ANGLE项目.

背景:

我喜欢OpenGL而不是DirectX的一个原因是它的跨平台功能.它在OS X和Linux以及通过ES的Android和iOS上都提供了出色的支持.但是,在Windows上,使用它会受到驱动程序问题的影响,或者更糟糕的是,许多卡只是没有正确实现它.

输入Google的ANGLE项目或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希望使用自己的D3Dmage控件创建的D3D表面上的ANGLE目标,因此我一直在围绕墙壁进行攻击.我不确定这是否可能.我甚至无法在任何人的任何地方找到一篇文章或参考文献,更不用说尝试它了.

尽管如此,我们的目标是让我们的共享,跨平台OpenGL(或ES)代码在WPF应用程序中工作,而不会出现空域问题或OpenGL驱动程序要求.我建议使用ANGLE/D3DImage只是......一次尝试.到目前为止,这是我提出的"手段",但这只是我们目标的潜在手段,而不是目标本身.任何能让我们得到同样解决方案的东西都会受到欢迎.

The*_*ler 4

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

代码出奇的简单:

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

提示:OpenTK和OpenTK.GLControl也可以作为 NuGet 包提供。明天将发布新版本,改进 ANGLE 支持。

请注意,WindowsFormsHost 方法受空域限制。如果这是一个问题,请参阅我的回答以获取解决方案。

// 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)