Is it possible to use OpenGL ES code with a WPF application via a D3DImage and ANGLE?
Asked Answered
I

1

9

Summary (TL:DR version)

Ultimately our goal is to be able to utilize OpenGL ES code in a WPF application natively (i.e. not SharpGL, etc.) and without Airspace or driver issues, possible using Google's ANGLE project.

Background:

One of the things I like about OpenGL over DirectX is its cross-platform capability. It has excellent support on both OS X and Linux, and also on Android and iOS via ES. However, on Windows, using it is marred with driver issues, or worse, a lot of cards simply don't implement it properly.

Enter Google's ANGLE project, or Almost-Native-Graphics-Layer-Engine.

ANGLE is an OpenGL ES 2.0 wrapper around a Direct3D implementation, meaning you can write OpenGL ES 2.0 code to be run on Windows without the need for actual OpenGL drivers. It not only passes the ES compatibility tests, but it's actually how Chrome does all of its graphics rendering, including WebGL so it definitely is a proven technology.

The Question:

We know WPF has a D3DImage control which lets you host Direct3D rendering within WPF and it supposedly does away with the airspace issues by properly composting its output to the WPF render thread. My question is since ANGLE is implemented via Direct3D, and D3DImage is a target for Direct3D rendering, is it possible to combine the two, allowing us to write OpenGL ES code and host it in a WPF application on Windows, all without driver or airspace issues?

This would be the 'Holy Grail' for us.

However, I keep hitting a wall around getting ANGLE to target its rendering on the D3D surface created by the D3DImage control since ANGLE wants to use its own. I'm not sure this is even possible. I can't find a single article or reference anywhere of anyone even discussing this, let alone attempting it.

Again to be clear though, the goal is to get our shared, cross-platform OpenGL (or ES) code to work in a WPF application without airspace issues or OpenGL driver requirements. My suggestion of using ANGLE/D3DImage is just that... an attempt. It's the 'means' I've come up with so far, but that's just a potential means to our goal, not the goal itself. Anything else that would get us to the same solution would be more than welcome.

Idoux answered 1/10, 2013 at 4:18 Comment(4)
Do you still need help with this question? If so, do you need to be able to combine WPF and OpenGL rendering on the same region (i.e. blend OpenGL with WPF) or do you just wish to embed OpenGL inside a WPF window? The latter would be trivial with OpenTK.GLControl and a WindowsFormsHost. The former requires some work (but is still possible.)Ephram
Yes, I'd still appreciate assistance here. And while no, we don't need to combine WPF rendering and OpenGL in the same region, if I'm correct, your WinFormsHost approach still falls victim to AirSpace issues. Then again, if our WPF portions within that same window wouldn't overlap with the OpenGL portions, that may be a solution. Not sure without trying it. Can you post a proper andswer with an example of using OpenTK.GLControl? If so, I'll mark yours as accepted.Idoux
One other comment... again, we want to simply reuse our already existing OpenGL ES rendering code. We don't want to translate it to another library, etc. (The general setup code of course can, and usually is somewhat platform-specific so that's fine. I mean the actual drawing calls themselves so it looks identical on WPF, iOS, Android, etc. and runs as close as possible to native speeds.Idoux
I am preparing an example project that shows how to use OpenGL and OpenGL ES / ANGLE using OpenTK.GLControl inside WPF.Ephram
E
4

I have uploaded a github project that demonstrates how to integrate OpenGL rendering into a WPF application via OpenTK.GLControl.

The code is surprisingly simple:

  1. Add a WindowsFormsHost to the WPF application
  2. Construct an OpenTK.GLControl and attach it to the WindowsFormsHost
    • Pass GraphicsContextFlags.Default for a desktop OpenGL context
    • Pass GraphicsContextFlags.Embedded for an OpenGL ES (ANGLE) context
  3. Render using normal OpenGL or OpenGL ES commands

Hint: OpenTK and OpenTK.GLControl are also available as NuGet packages. There is a new release due tomorrow with improved ANGLE support.

Note that the WindowsFormsHost approach is subject to airspace restrictions. If this is an issue, see my answer here for a solution.

// 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();
        }
    }
}
Ephram answered 15/3, 2014 at 0:4 Comment(7)
Two things... one, you didn't provide a link to your GitHub project, and two, again, we want to use our already existing C files, not a compatible toolkit (unless that lets us use our existing code.) Again, the issue is cross-platform code, not OpenGL for OpenGL's sake. Hope that makes sense, and if so, you can address it.Idoux
You are right, I have added the missing link to github. This code demonstrates how to create an OpenGL / OpenGL ES context inside a WPF window. How your render afterwards is up to you - the context does not care if you are using C, C# or something else entirely. For example, you could call into your C renderer via a [DllImport]. Does this answer your question?Ephram
Hmmm... I believe so, but I'll have to look at your sample project and see what it does. Still, I'll give you the answer anyway because of the information that you did provide. Any chance you could provide contact info in your GitHub project in case I have any questions? If we use what you provided, we'll even give you attribution if you want it.Idoux
@TheFiddler You say: "you could call into your C renderer via a [DllImport]". Do you think it's possible in the other way around, like passing a window handle of the WPF (GLControl) to the C++ render. Basically I have the rendering code, I just want a window where to render.Furgeson
OpenGL uses thread-local storage to store its context. Once you call GLControl.MakeCurrent() on a specific thread, you can issue OpenGL commands on that thread from either C# or C++ without any issue. The window handle is not required. Check the GraphicsContext documentation for more information.Ephram
Is this still the best way to integrate an OpenGL window into a WPF project? I require WPF widgets alongside my OpenGL window including - text boxes, buttons, lists etc.Franek
@TheFiddler Hi Fiddler, Thank you very much for your answer, I accidentally ended up here searching for alternative solutions to SkiaSharp for rendering in 2D objects in WPF. Can you please point me in the right direction whether this library can be used for 2D? And if so where should I start! For example how can I create a simple line. I am totally new to OpenGL and OpenTK. Thank you.Rijeka

© 2022 - 2024 — McMap. All rights reserved.