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只是......一次尝试.到目前为止,这是我提出的"手段",但这只是我们目标的潜在手段,而不是目标本身.任何能让我们得到同样解决方案的东西都会受到欢迎.
我上传了一个github 项目,该项目演示了如何通过OpenTK.GLControl将 OpenGL 渲染集成到 WPF 应用程序中。
代码出奇的简单:
WindowsFormsHost到WPF应用程序OpenTK.GLControl并将其附加到WindowsFormsHost
GraphicsContextFlags.Default桌面 OpenGL 上下文GraphicsContextFlags.EmbeddedOpenGL ES (ANGLE) 上下文提示: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)