最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在Qt中使用OpenGL繪制三角形指南

 更新時間:2025年04月07日 08:48:39   作者:師從名劍山  
在高性能渲染場景中,CPU資源常被過度消耗,導致界面卡頓,而OpenGL作為業(yè)界標準的圖形API,能通過GPU硬件加速顯著降低CPU負載,本文將以繪制三角形為例,教你如何通過Qt的QOpenGLWidget和QOpenGLFunctions實現(xiàn)跨平臺GPU渲染,感興趣的朋友一起看看吧

本文只介紹基本的 QOpenGLWidget 和 QOpenGLFunctions 的使用,想要學習 OpenGL 的朋友,建議訪問經(jīng)典 OpenGL 學習網(wǎng)站:LearnOpenGL CN

本篇文章,我們將以繪制一個經(jīng)典的三角形為例,講一講,怎么在 Qt 中使用 OpenGL 來進行 GPU 繪制。

前言

在高性能渲染場景中,CPU資源常被過度消耗,導致界面卡頓。而OpenGL作為業(yè)界標準的圖形API,能通過GPU硬件加速顯著降低CPU負載。本文將以繪制三角形為例,教你如何通過Qt的QOpenGLWidget和QOpenGLFunctions實現(xiàn)跨平臺GPU渲染。

QOpenGLFunctions

OpenGL函數(shù)在不同平臺(Windows/Linux/Mac)的實現(xiàn)存在差異。例如:

平臺函數(shù)加載方式
WindowswglGetProcAddress
LinuxglXGetProcAddress

Qt通過QOpenGLFunctions封裝了這些底層差異,開發(fā)者只需繼承此類,即可用glClear() 等統(tǒng)一接口調(diào)用OpenGL函數(shù),無需編寫平臺特定代碼。通過這樣,我們就可以用一套代碼,在不同平臺下使用 OpenGL 相。要使用這個類也很簡單,讓我們的類直接繼承 QOpenGLFuntions 就好了。同時也可以配合 QOpenGLWidget 來使用,在 initializeGL 函數(shù)里,調(diào)用 initializeOpenGLFunctions 后,就可以直接使用 OpenGL 的函數(shù)

Windows 下加載(wglGetProcAddress)

例如在 Windows 下,我們使用 wglGetProcAddress來動態(tài)加載這些函數(shù)(例如 glClear),下面是加載代碼:

包含必要的頭文件

#include <windows.h>
#include <GL/gl.h>
#include <GL/glext.h>  // 提供 OpenGL 擴展聲明

定義函數(shù)指針類型

// 示例:定義 glClear 的函數(shù)指針類型
typedef void (APIENTRY *PFNGLCLEARPROC)(GLbitfield);
PFNGLCLEARPROC glClear;

加載 OpenGL 函數(shù)

// 初始化 OpenGL 函數(shù)
void initOpenGLFunctions() {
    // 1. 加載 OpenGL 1.1 函數(shù)(由 opengl32.dll 提供)
    glClear = (PFNGLCLEARPROC)wglGetProcAddress("glClear");
    // 2. 檢查是否加載成功
    if (!glClear) {
        // 如果失敗,可能是驅(qū)動不支持該函數(shù)
        MessageBoxA(NULL, "Failed to load glClear", "Error", MB_OK);
        exit(1);
    }
    // 3. 類似方式加載其他函數(shù)...
    // glDrawArrays = (PFNGLDRAWARRAYSPROC)wglGetProcAddress("glDrawArrays");
    // ...
}

使用加載的函數(shù)

glClear(GL_COLOR_BUFFER_BIT);  // 現(xiàn)在可以正常調(diào)用

Linux 下加載(glXGetProcAddress )

而在 linux 下,加載的函數(shù)變成了:glXGetProcAddress ,對應的代碼是:

包含必要的頭文件

#include <GL/gl.h>
#include <GL/glx.h>  // X11 的 OpenGL 擴展
#include <GL/glext.h>

定義函數(shù)指針類型

// 示例:定義 glClear 的函數(shù)指針類型
typedef void (*PFNGLCLEARPROC)(GLbitfield);
PFNGLCLEARPROC glClear;

加載 OpenGL 函數(shù)

void initOpenGLFunctions() {
    // 1. 加載 glClear
    glClear = (PFNGLCLEARPROC)glXGetProcAddress((const GLubyte*)"glClear");
    // 2. 檢查是否加載成功
    if (!glClear) {
        fprintf(stderr, "Failed to load glClear\n");
        exit(1);
    }
    // 3. 類似方式加載其他函數(shù)...
    // glDrawArrays = (PFNGLDRAWARRAYSPROC)glXGetProcAddress((const GLubyte*)"glDrawArrays");
    // ...
}

使用加載的函數(shù)

glClear(GL_COLOR_BUFFER_BIT);  // 現(xiàn)在可以正常調(diào)用

QOpenGLWidget

QOpenGLWidget 是 Qt 提供的一個 widget 類,用于在 Qt 應用程序中嵌入 OpenGL 渲染內(nèi)容。它繼承自 QWidget,內(nèi)部管理了一個 OpenGL 上下文(例如 windows 下調(diào)用 wglMakeCurrent / wglDoneCurrent)和幀緩沖區(qū),并提供了與 Qt 窗口系統(tǒng)無縫集成的能力。詳細內(nèi)容可看:QOpenGLWidget Class

我們可以創(chuàng)建自己的窗口,并繼承 QOpenGLWidget,然后重寫下面三個函數(shù),來處理一些 OpenGL 相關的工作。

initializeGL

初始化一些 OpenGL 相關的資源或者狀態(tài)。這個函數(shù)在在第一次調(diào)用 resizeGL或者 paintGL之前被調(diào)用。

paintGL

渲染 OpenGL 的場景,類似于我們平常使用的 QWidget::paintEvent,在窗口需要更新時調(diào)用。

resizeGL

調(diào)整 OpenGL Viewport 的大小或者投影等,在窗口需要調(diào)整大小時調(diào)用。

完整代碼

#pragma once
#include <QOpenGLBuffer>
#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include "FrameObserver.h"
class COpenGLRenderWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit COpenGLRenderWidget(QWidget *parent = nullptr);
    ~COpenGLRenderWidget() override;
private:
    void InitShaders();
private:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int w, int h) override;
private:
    QOpenGLShaderProgram m_shaderProgram;
    QOpenGLBuffer m_vbo;
};
#include "OpenGLRenderWidget.h"
static const GLfloat coordinateBasic[] = {
    // 頂點坐標,存儲3個xyz坐標
    // x     y     z
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f,
};
constexpr auto VERTEX_SHADER_BASIC = R"(
attribute vec3 vertexIn; 
varying vec2 textureOut; 
void main(void)
{
    gl_Position = vec4(vertexIn, 1.0);
}
)";
constexpr auto FRAGMENT_SHADER_BASIC = R"(
varying vec2 textureOut;
void main(void) 
{ 
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 
}
)";
COpenGLRenderWidget::COpenGLRenderWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{}
COpenGLRenderWidget::~COpenGLRenderWidget()
{}
void COpenGLRenderWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glDisable(GL_DEPTH_TEST);
    m_vbo.create();
    m_vbo.bind();
    m_vbo.allocate(coordinateBasic, sizeof(coordinateBasic));
    InitShaders();
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}
void COpenGLRenderWidget::paintGL()
{
    m_shaderProgram.bind();
    glDrawArrays(GL_TRIANGLES, 0, 3);
    m_shaderProgram.release();
}
void COpenGLRenderWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    update();
}
void COpenGLRenderWidget::InitShaders()
{
    QOpenGLShader vertexShader(QOpenGLShader::Vertex);
    if (!vertexShader.compileSourceCode(VERTEX_SHADER_BASIC))
    {
        qDebug() << "Vertex shader compilation failed. Error: " << vertexShader.log();
        return;
    }
    QOpenGLShader fragmentShader(QOpenGLShader::Fragment);
    if (!fragmentShader.compileSourceCode(FRAGMENT_SHADER_BASIC))
    {
        qDebug() << "Fragment shader compilation failed. Error: " << fragmentShader.log();
        return;
    }
    m_shaderProgram.addShader(&vertexShader);
    m_shaderProgram.addShader(&fragmentShader);
    m_shaderProgram.link();
    m_shaderProgram.bind();
    m_shaderProgram.setAttributeBuffer("vertexIn", GL_FLOAT, 0, 3, 3 * sizeof(float));
    m_shaderProgram.enableAttributeArray("vertexIn");
}

到此這篇關于在Qt中使用OpenGL繪制指南的文章就介紹到這了,更多相關Qt使用OpenGL繪制指南內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

德惠市| 霍林郭勒市| 宜阳县| 林芝县| 故城县| 隆回县| 宜兴市| 剑川县| 闽侯县| 中江县| 河津市| 高密市| 开远市| 迁安市| 崇义县| 班戈县| 尼勒克县| 济南市| 巴中市| 元谋县| 澄江县| 霍城县| 密山市| 闸北区| 合肥市| 奉化市| 全南县| 峨边| 新营市| 门头沟区| 泊头市| 左云县| 盘锦市| 永吉县| 察隅县| 界首市| 仁寿县| 岳阳市| 杂多县| 永川市| 尉氏县|