Как интегрировать QML в пользовательский рендерер Vulkan без использования отдельного окна [закрыто]C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как интегрировать QML в пользовательский рендерер Vulkan без использования отдельного окна [закрыто]

Сообщение Anonymous »

Я разрабатываю собственный модуль визуализации Vulkan и хочу интегрировать в него пользовательский интерфейс на основе QML.
У меня уже есть работающая настройка Vulkan, а также мне удалось визуализировать QML поверх кадра Vulkan с помощью отдельных QQuickWindow и QQuickRenderControl, но этот подход не идеален — элементы QML находятся в отдельном окне, поэтому у них есть собственный фокус и обработка ввода.
Я пытался использовать QCoreApplication::sendEvent для отправки событий, который работает для Button, но не работает для TextField, потому что для TextField должно быть активировано базовое окно, но, как я уже сказал, в настоящее время мои элементы QML имеют отдельные QQuickWindow, и я не хочу их активировать, поэтому мой QWindow, который я использую для рендеринга Vulkan, не потеряется focus.
Вопрос:
  • Как интегрировать QML в средство визуализации Vulkan, чтобы они использовали один и тот же фокус
    в одном окне?
Есть примеры или рекомендуемая архитектура?
Текущая настройка:
UserInterfaceElement.h
struct UserInterfaceElement
{
std::unique_ptr renderer;
std::unique_ptr cache;
Texture texture;
Model model;
QString qmlPath;
};

UserInterfaceRenderer.h
class UserInterfaceRenderer : public QObject
{
Q_OBJECT
public:
UserInterfaceRenderer(QWindow* parentWindow = nullptr);
~UserInterfaceRenderer();

void loadQml(const QSize& size, const QString& qmlPath);
void render();
void resize(const QSize& size);
void createFbo(const QSize& size);
void deleteFbo();
QImage grabImage(); // taking screenshot
QOpenGLFramebufferObject* getFbo() const { return fbo; }
QQuickWindow* getQuickWindow() const { return quickWindow; }

void forwardEvent(QEvent* event);
QQuickItem* getRootItem() const { return rootItem; }

private:
QQuickRenderControl* renderControl = nullptr;
QQuickWindow* quickWindow = nullptr;
QQmlEngine* engine = nullptr;
QQmlComponent* component = nullptr;
QQuickItem* rootItem = nullptr;

QOpenGLFramebufferObject* fbo = nullptr;
QOpenGLContext* context = nullptr;
QOffscreenSurface* offscreenSurface = nullptr;
QSize surfaceSize;
};

UserInterfaceRenderer.cpp
UserInterfaceRenderer::UserInterfaceRenderer(QWindow* parentWindow) {
renderControl = new QQuickRenderControl(this);
quickWindow = new QQuickWindow(renderControl);
quickWindow->setGraphicsApi(QSGRendererInterface::OpenGL);
quickWindow->setFlags(
Qt::FramelessWindowHint | Qt::Tool |
Qt::WindowStaysOnTopHint | Qt::WindowTransparentForInput
);
quickWindow->setColor(Qt::transparent);

context = new QOpenGLContext(parentWindow);
context->setFormat(parentWindow->format());
context->create();

offscreenSurface = new QOffscreenSurface();
offscreenSurface->setFormat(context->format());
offscreenSurface->create();

context->makeCurrent(offscreenSurface);
quickWindow->setGraphicsDevice(QQuickGraphicsDevice::fromOpenGLContext(context));
renderControl->initialize();
quickWindow->create();

//quickWindow->setTransientParent(parentWindow);
//quickWindow->setParent(parentWindow);

engine = new QQmlEngine(this);
if (!engine->incubationController()) {
engine->setIncubationController(quickWindow->incubationController());
}
}

UserInterfaceRenderer::~UserInterfaceRenderer() {
if (rootItem) {
rootItem->setParentItem(nullptr);
delete rootItem;
}

delete renderControl;
delete quickWindow;
delete engine;
delete component;
deleteFbo();

if (context) {
context->doneCurrent();
delete context;
}

if (offscreenSurface) {
offscreenSurface->destroy();
delete offscreenSurface;
}
}

void UserInterfaceRenderer::forwardEvent(QEvent* event) {
QCoreApplication::sendEvent(quickWindow, event);
}

void UserInterfaceRenderer::loadQml(const QSize& size, const QString& qmlPath) {
component = new QQmlComponent(engine, QUrl::fromLocalFile(qmlPath));

rootItem = qobject_cast(component->create());
if (!rootItem) {
qWarning() contentItem());
rootItem->setSize(size);
quickWindow->resize(size);

surfaceSize = size;

deleteFbo();
createFbo(size);
}

void UserInterfaceRenderer::resize(const QSize& size) {
if (!rootItem) return;

rootItem->setSize(size);
quickWindow->resize(size);
surfaceSize = size;

deleteFbo();
createFbo(size);
}

void UserInterfaceRenderer::createFbo(const QSize& size) {
context->makeCurrent(offscreenSurface);

QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setTextureTarget(GL_TEXTURE_2D);
format.setInternalTextureFormat(GL_RGBA8);
fbo = new QOpenGLFramebufferObject(size, format);

QQuickRenderTarget renderTarget = QQuickRenderTarget::fromOpenGLTexture(
fbo->texture(),
surfaceSize
);
quickWindow->setRenderTarget(renderTarget);
}

void UserInterfaceRenderer::deleteFbo()
{
if (fbo) {
context->makeCurrent(offscreenSurface);
delete fbo;
fbo = nullptr;
}
}

void UserInterfaceRenderer::render() {
if (!rootItem || !quickWindow || !fbo) return;

if (!context->makeCurrent(offscreenSurface)) {
qWarning() functions();
f->glViewport(0, 0, surfaceSize.width(), surfaceSize.height());
f->glClearColor(0, 0, 0, 0); // transparent clear
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

renderControl->beginFrame();
renderControl->polishItems();
renderControl->sync();
renderControl->render();
renderControl->endFrame();

f->glFlush();
}

Model.h
struct Texture {
VkImage image = VK_NULL_HANDLE;
VmaAllocation vmaAllocation = VK_NULL_HANDLE;
VkImageView imageView = VK_NULL_HANDLE;
VkSampler sampler = VK_NULL_HANDLE;
uint32_t mipLevels = 0;
uint32_t width = 0;
uint32_t height = 0;
};

struct Material {
Texture diffuseTexture; // basic color
Texture normalTexture;
Texture specularTexture;
Texture emissiveTexture;
};

struct Mesh
{
std::vector vertices;
std::vector indices;
glm::mat4 transform = glm::mat4(1.0f);

Material material;

VkBuffer vertexBuffer = VK_NULL_HANDLE;
VmaAllocation vertexBufferAllocation = VK_NULL_HANDLE;
VkBuffer indexBuffer = VK_NULL_HANDLE;
VmaAllocation indexBufferAllocation = VK_NULL_HANDLE;

std::vector descriptorSets = std::vector(MAX_FRAMES_IN_FLIGHT, VK_NULL_HANDLE);
};

struct Model {
std::vector meshes;
ModelType type = ModelType::OTHER;

glm::vec3 position;
glm::vec3 scale;
glm::quat rotation;

bool isCollidable = false;
};

вызывается в функции RecordCommandBuffer, которая вызывается каждый кадр для каждого элемента пользовательского интерфейса
void AetherEngine::recordUiElementToCommandBuffer(UserInterfaceElement& uiElement, VkCommandBuffer commandBuffer)
{
renderQmlToTexture(uiElement.renderer.get(), uiElement.texture);
vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines["ui"]);
recordModelToCommandBuffer(uiElement.model, commandBuffer);
}
void AetherEngine::renderQmlToTexture(UserInterfaceRenderer* renderer, Texture& texture)
{
renderer->render();
QImage image = renderer->getFbo()->toImage().convertToFormat(QImage::Format_RGBA8888);

if (texture.width != static_cast(image.width()) ||
texture.height != static_cast(image.height())) {
cleanupTexture(texture);

modelManager.createSolidColorTexture({ 0, 0, 0, 0 }, image.width(), image.height(), texture);
}

modelManager.uploadRawDataToTexture(image.bits(), image.width(), image.height(), texture);
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... arate-wind
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»