「Qt Widget中文示例指南」如何實現一個簡單的RHI小部件示例(一)

Qt 是目前最先進、最完整的跨平臺C++開發工具。它不僅完全實現了一次編寫,所有平臺無差別運行,更提供了幾乎所有開發過程中需要用到的工具。如今,Qt已被運用於超過70個行業、數千家企業,支持數百萬設備及應用。

本文將爲大家演示如何使用QRhi、Qt的3D API和着色語言抽象層渲染三角形。

「Qt Widget中文示例指南」如何實現一個快捷編輯器

在很多方面,這個示例都是QWidget世界中的RHI窗口示例的對應。這個應用程序中的QRhiWidget子類使用帶有基本頂點和片段着色器的簡單圖形管道渲染單個三角形。與普通的基於QWindow的應用程序不同,本示例不需要擔心較低級別的細節,比如設置窗口和QRhi,或者處理交換鏈和窗口事件,因爲這些都由這裏的QWidget框架負責。QRhiWidget子類的實例被添加到QVBoxLayout中,爲了使示例保持最小和緊湊,沒有引入更多的小部件或3D內容。

一旦將ExampleRhiWidget (QRhiWidget的子類)的實例添加到頂級小部件的子層次結構中,相應的窗口就會自動變成Direct 3D、Vulkan、Metal或opengl渲染窗口。QPainter渲染的小部件內容,即不是QRhiWidget、QOpenGLWidgetQQuickWidget的所有內容,然後上傳到紋理,而提到的特殊小部件每個渲染到紋理,生成的紋理集由頂級小部件的backingstore組合在一起。

結構和main()

main()函數非常簡單,頂級小部件的默認大小爲720p(此大小以邏輯單位表示),實際像素大小可能不同,具體取決於比例因子。窗口可調整大小,QRhiWidget使實現正確處理由於窗口大小或佈局變化而調整小部件大小的子類變得簡單。

int main(int argc, char **argv)
{
QApplication app(argc, argv);

ExampleRhiWidget *rhiWidget = new ExampleRhiWidget;

QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(rhiWidget);

QWidget w;
w.setLayout(layout);
w.resize(1280, 720);
w.show();

return app.exec();
}

QRhiWidget子類重新實現了兩個虛擬對象:initialize()和render(),initialize()在render()之前至少被調用一次,但是在一些重要的變化時也會被調用,比如當小部件的背景紋理由於小部件大小的變化而被重新創建時,當呈現目標參數發生變化時,或者當小部件由於移動到新的頂級窗口而被更改爲新的QRhi時。

注意:與QOpenGLWidget遺留的initializeGL - resizeGL - paintGL模型不同,QRhiWidget中只有兩個虛擬值。這是因爲有更多的特殊事件可能需要照顧,而不僅僅是調整大小。例如,當重新父級到不同的頂層窗口時。(健壯的QOpenGLWidget實現必須通過執行額外的簿記來處理這個問題,例如通過跟蹤相關的QOpenGLContext生命週期,這意味着三個虛擬對象實際上是不夠的)一個更簡單的initialize - render,在重要的更改時重新調用initialize更適合這個。

QRhi實例不屬於小部件,它將在initialize()中從基類中查詢,將其存儲爲成員允許在再次調用initialize()時識別更改。圖形資源,比如頂點和統一緩衝區,或者圖形管道,都在ExampleRhiWidget的控制之下。

#include <QRhiWidget>
#include <rhi/qrhi.h>

class ExampleRhiWidget : public QRhiWidget
{
public:
ExampleRhiWidget(QWidget *parent = nullptr) : QRhiWidget(parent) { }

void initialize(QRhiCommandBuffer *cb) override;
void render(QRhiCommandBuffer *cb) override;

private:
QRhi *m_rhi = nullptr;
std::unique_ptr<QRhiBuffer> m_vbuf;
std::unique_ptr<QRhiBuffer> m_ubuf;
std::unique_ptr<QRhiShaderResourceBindings> m_srb;
std::unique_ptr<QRhiGraphicsPipeline> m_pipeline;
QMatrix4x4 m_viewProjection;
float m_rotation = 0.0f;
};

要使#include <rhi/qrhi.h>語句起作用,應用程序必須鏈接到GuiPrivate(或使用qmake鏈接到gui-private)。

CMakeLists.txt

target_link_libraries(simplerhiwidget PRIVATE
Qt6::Core
Qt6::Gui
Qt6::GuiPrivate
Qt6::Widgets
)

未完待續,下期接着講......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章