9

摘要(TL:DR版本)

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

背景:

我喜欢 OpenGL over 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 想要使用它自己的,所以我一直在让 ANGLE 将其渲染定位在由 D3DImage 控件创建的 D3D 表面上。我不确定这是否可能。我什至在任何地方都找不到任何人讨论这个问题的文章或参考资料,更不用说尝试了。

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

4

1 回答 1

4

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

代码非常简单:

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

提示:OpenTKOpenTK.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();
        }
    }
}
于 2014-03-15T00:04:22.800 回答