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

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

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

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

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

前言

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

QOpenGLFunctions

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

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

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

Windows 下加載(wglGetProcAddress)

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

包含必要的頭文件

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

定義函數(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ū)動(dòng)不支持該函數(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 ,對(duì)應(yīng)的代碼是:

包含必要的頭文件

#include <GL/gl.h>
#include <GL/glx.h>  // X11 的 OpenGL 擴(kuò)展
#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 提供的一個(gè) widget 類,用于在 Qt 應(yīng)用程序中嵌入 OpenGL 渲染內(nèi)容。它繼承自 QWidget,內(nèi)部管理了一個(gè) OpenGL 上下文(例如 windows 下調(diào)用 wglMakeCurrent / wglDoneCurrent)和幀緩沖區(qū),并提供了與 Qt 窗口系統(tǒng)無縫集成的能力。詳細(xì)內(nèi)容可看:QOpenGLWidget Class

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

initializeGL

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

paintGL

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

resizeGL

調(diào)整 OpenGL Viewport 的大小或者投影等,在窗口需要調(diào)整大小時(shí)調(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[] = {
    // 頂點(diǎn)坐標(biāo),存儲(chǔ)3個(gè)xyz坐標(biāo)
    // 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");
}

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

相關(guān)文章

最新評(píng)論

资阳市| 黑水县| 栾城县| 商南县| 广昌县| 黄冈市| 佛坪县| 德惠市| 龙门县| 和政县| 柳河县| 盐池县| 福清市| 保康县| 南江县| 民县| 拉孜县| 巴彦淖尔市| 宜阳县| 丽水市| 昌邑市| 文登市| 安陆市| 全南县| 同仁县| 山阳县| 余庆县| 建德市| 南郑县| 诸暨市| 衡水市| 环江| 汾西县| 昌图县| 眉山市| 五峰| 陆良县| 咸丰县| 西吉县| 霍山县| 东源县|