OpenGL (УГОЛ) + XAML (UWP)

Я пытаюсь запустить код OpenGL в приложении UWP XAML. Я нашел некоторую информацию об этом, но, похоже, нет ничего лучше полного прохождения. Я новичок в UPW, XAML и EGL, поэтому мне удалось создать следующий код из различных руководств:

#include <Windows.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <angle_windowsstore.h>

using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Platform;
using Windows::ApplicationModel::SuspendingEventArgs;
using Windows::ApplicationModel::Activation::LaunchActivatedEventArgs;
using Windows::Foundation::Collections::PropertySet;
using Windows::Foundation::EventHandler;

static EGLint const openGlAttributes[] = {
    EGL_RED_SIZE, 1,
    EGL_GREEN_SIZE, 1,
    EGL_BLUE_SIZE, 1,
    EGL_NONE
};

ref class MyApp sealed : Application {
private:
    SwapChainPanel^ swapChainPanel;
    CoreWindow^ coreWindow;
    EGLDisplay display;
    EGLSurface surface;
    bool stopped;

public:
    MyApp() {
        stopped = false;
    }

    virtual void OnLaunched(LaunchActivatedEventArgs^ e) override {
        auto canvas = ref new Canvas();

        auto swapChainPanel = ref new SwapChainPanel();
        swapChainPanel->Width = 800;
        swapChainPanel->Width = 600;
        canvas->Children->Append(swapChainPanel);
        canvas->SetLeft(swapChainPanel, 0);
        canvas->SetTop(swapChainPanel, 0);


        Window::Current->Content = canvas;
        Window::Current->Activate();

        coreWindow = Window::Current->CoreWindow;
        InitGL(Window::Current);

        WeakReference selfRef(this);
        Suspending += ref new SuspendingEventHandler([selfRef](Object^ sender, SuspendingEventArgs^ args) {
            auto self = selfRef.Resolve<MyApp>();
            self->stopped = true;
        });
        Resuming += ref new EventHandler<Object^>([selfRef](Object^ sender, Object^ args) {
            auto self = selfRef.Resolve<MyApp>();
            self->stopped = false;
        });

        ScheduleRendering();
    }

private:

    void InitGL(Window^ window) {
        display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        eglInitialize(display, NULL, NULL);

        EGLConfig config;
        EGLint numConfig;
        eglChooseConfig(display, openGlAttributes, &config, 1, &numConfig);

        auto surfaceCreationProperties = ref new PropertySet();
        surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), swapChainPanel);

        auto context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
        surface = eglCreateWindowSurface(display, config, reinterpret_cast<EGLNativeWindowType>(surfaceCreationProperties), NULL);
        eglMakeCurrent(display, surface, surface, context);
    }

    void RenderScene() {
        glClearColor(1.0, 0, 0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
        glFlush();

        eglSwapBuffers(display, surface);

        ScheduleRendering();
    }

    void ScheduleRendering() {
        if (stopped) {
            return;
        }
        WeakReference selfRef(this);
        coreWindow->Dispatcher->RunIdleAsync(ref new IdleDispatchedHandler([selfRef](IdleDispatchedHandlerArgs^ args) {
            auto self = selfRef.Resolve<MyApp>();
            self->RenderScene();
        }));
    }
};

int main(Array<String^>^ args) {
    Application::Start(ref new ApplicationInitializationCallback([](ApplicationInitializationCallbackParams^ p) {
        ref new MyApp();
    }));
    return 0;
}

Однако это просто не работает. По крайней мере, этот код не дает сбоев. Затем я проверил InitGL в отладчике, и все вызовы EGL завершились нормально.

Есть несколько вещей, в которых я не уверен:

  1. Должен ли я инициализировать SwapChainPanel в соответствии с это руководство, или ANGLE сделает это за меня?
  2. Должен ли я выполнять рендеринг в режиме ожидания или есть что-то вроде события Paint?

person Alexey Andreev    schedule 24.06.2019    source источник
comment
Я создал пустое приложение на C++ в VS2019 и установил ANGLE.WindowsStore из NuGet, но по-прежнему не смог включить ‹GLES/gl.h›. Можете ли вы показать мне, какие шаги вы предприняли, чтобы помочь мне воспроизвести его?   -  person Faywang - MSFT    schedule 26.06.2019
comment
Я не создавал проект из VS. Вместо этого я написал CMakeLists.txt и сгенерировал из него файл sln. Я включил зависимость ANGLE от vcpkg.   -  person Alexey Andreev    schedule 27.06.2019


Ответы (1)


Похоже, я ошибся, когда написал, что все инициализируется правильно. Этот вызов вернул EGL_NO_SOURCE:

eglMakeCurrent(display, surface, surface, context);

Я полагаю, это из-за того, что мы должны ждать, когда SwapChainPanel будет инициализирован, поэтому, когда я вызвал eglMakeCurrent из Load события swapChainPanel, все начало работать. Кроме того, есть несколько неочевидных вещей, например, swapChainPanel может неожиданно потерять контекст GL, и поэтому вам придется создавать его заново, когда что-то пойдет не так. Я нашел этот шаблон в ответвлении Microsoft ANGLE и использовал его как источник вдохновения.

person Alexey Andreev    schedule 27.06.2019