{"id":1293,"date":"2024-08-21T13:37:22","date_gmt":"2024-08-21T13:37:22","guid":{"rendered":"https:\/\/www.gislxz.com\/?p=1293"},"modified":"2024-09-12T08:05:18","modified_gmt":"2024-09-12T08:05:18","slug":"qtopengl%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0","status":"publish","type":"post","link":"https:\/\/www.gislxz.com\/index.php\/2024\/08\/21\/qtopengl%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0\/","title":{"rendered":"QT+OpenGL\u5b66\u4e60\u7b14\u8bb0\uff081\uff09"},"content":{"rendered":"\n<p>\u9996\u5148\u521b\u5efa\u4e00\u4e2a\u9ed8\u8ba4qt widget\u9879\u76ee\uff0c\u7136\u540e\u7528git\u505a\u4e00\u4e0b\u7248\u672c\u63a7\u5236\uff0c\u5947\u602a\u7684\u662f\u6211github\u4e0a\u7684\u9879\u76ee\u4ec0\u4e48\u6587\u4ef6\u90fd\u6ca1\u6709\uff0cpush\u65f6\u5374\u63d0\u9192\u6211\u4e0e\u6700\u65b0\u7248\u672c\u4e0d\u4e00\u81f4\uff0cpull\u4e0b\u6765\u65f6\u62a5\u9519\uff0cgpt\u7684\u56de\u7b54\u662f\uff1a<\/p>\n\n\n\n<p>\u51fa\u73b0\u8fd9\u4e2a\u9519\u8bef\u4fe1\u606f <code>fatal: refusing to merge unrelated histories<\/code> \u662f\u56e0\u4e3a\u4f60\u5c1d\u8bd5\u5c06\u4e24\u4e2a\u6ca1\u6709\u5171\u540c\u5386\u53f2\u7684\u5206\u652f\u8fdb\u884c\u5408\u5e76\u3002\u8fd9\u901a\u5e38\u53d1\u751f\u5728\u4ed3\u5e93\u7684\u5386\u53f2\u5728\u67d0\u5904\u88ab\u91cd\u5199\u6216\u8005\u4f60\u514b\u9686\u4e86\u4e00\u4e2a\u5168\u65b0\u7684\u4ed3\u5e93\u5e76\u5c1d\u8bd5\u4e0e\u73b0\u6709\u7684\u4ed3\u5e93\u5408\u5e76\u65f6\u3002<\/p>\n\n\n\n<p>\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 <code>--allow-unrelated-histories<\/code> \u9009\u9879\u6765\u5f3a\u5236\u5408\u5e76\u8fd9\u4e24\u4e2a\u5386\u53f2\u8bb0\u5f55\u4e0d\u76f8\u5173\u7684\u5206\u652f\u3002<\/p>\n\n\n\n<p>\u5f3a\u884cpull\u4e0b\u6765\u5408\u5e76\uff0c\u518dpush\u5c31\u597d\u4e86<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/GISlxz\/QT_learn_demo\" target=\"_blank\"  rel=\"nofollow\" >GISlxz\/QT_learn_demo (github.com)<\/a><\/p>\n\n\n\n<p>\u53e6\u9644github\u57fa\u672c\u6559\u7a0b<\/p>\n\n\n\n<p><a href=\"https:\/\/zhuanlan.zhihu.com\/p\/664195515\" target=\"_blank\"  rel=\"nofollow\" >\u3010\u5c0f\u767d\u5411\u3011\u6700\u65b0\u6700\u8be6\u7ec6\u7684GitHub\u5168\u7ad9\u4f7f\u7528\u6307\u5357 - \u77e5\u4e4e (zhihu.com)<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/zhuanlan.zhihu.com\/p\/90168946\" target=\"_blank\"  rel=\"nofollow\" >\u672c\u5730\u9879\u76ee\u63a8\u9001\u5230\u8fdc\u7a0b\u4ed3\u5e93gitHub\u4e0a\uff08\u8d85\u8be6\u7ec6\uff09 - \u77e5\u4e4e (zhihu.com)<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/learnopengl-cn.github.io\/\" target=\"_blank\"  rel=\"nofollow\" >\u4e3b\u9875 - LearnOpenGL CN (learnopengl-cn.github.io)<\/a><\/p>\n\n\n\n<p>VS2022\u914d\u7f6eOpenGL<a href=\"https:\/\/blog.csdn.net\/J__M__C\/article\/details\/126857129\" target=\"_blank\"  rel=\"nofollow\" >VS2022 + OpenGL GLFW Windows\u73af\u5883\u914d\u7f6e_windows glfw-CSDN\u535a\u5ba2<\/a><\/p>\n\n\n\n<p>glad.c\u76f4\u63a5\u653e\u8fdb\u5de5\u7a0b\u6587\u4ef6\u91cc<\/p>\n\n\n\n<p>\u5148\u91cd\u5b66\u4e00\u8fb9qt\uff0c\u5fd8\u5dee\u4e0d\u591a\u4e86<\/p>\n\n\n\n<p><a href=\"https:\/\/www.bilibili.com\/video\/BV1km4y1k7CW\/?spm_id_from=333.788.recommend_more_video.1&amp;vd_source=e203e20b728f2194924c7f8b9d5478c9\" target=\"_blank\"  rel=\"nofollow\" >\u300aQt6 C++\u5f00\u53d1\u6307\u5357 \u300b2023\uff08\u4e0a\u518c\uff0c\u5b8c\u6574\u7248\uff09_\u54d4\u54e9\u54d4\u54e9_bilibili<\/a><\/p>\n\n\n\n<p>EXP1<\/p>\n\n\n\n<p>\u8ddf\u7740\u6559\u7a0b\u505a\u4e00\u4e2a\u7b80\u5355\u7684\u5e94\u7528<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"723\" height=\"789\" src=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/05\/1715160121-1715160118068.png\" alt=\"\" class=\"wp-image-1294\" srcset=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/05\/1715160121-1715160118068.png 723w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/05\/1715160121-1715160118068-275x300.png 275w\" sizes=\"auto, (max-width: 723px) 100vw, 723px\" \/><\/figure>\n\n\n\n<p>\u6559\u7a0b\u8fd8\u662f\u7528\u7684qmake\uff0c\u4f46\u6211\u9879\u76ee\u9ed8\u8ba4\u7684\u662fcmake\uff0c\u5bfc\u5165qrc\u8d44\u6e90\u7684\u65f6\u5019\u6709\u70b9\u9ebb\u70e6\uff0cCmake\u91cc\u8fd9\u4e48\u5199\u3002\u7f51\u4e0a\u641c\u7684\u6559\u7a0b\u90fd\u662f\u518d\u5199\u4e00\u4e2aqt_add_executable\uff0c\u4f46\u662f\u51b2\u7a81\u4e86\uff0c\u76f4\u63a5\u52a0\u5728\u5df2\u6709\u7684qt_add_executable\u91cc<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>set(RESOURCES icons.qrc)\nqt6_add_resources(RESOURCES_CPP ${RESOURCES})\n\nif(${QT_VERSION_MAJOR} GREATER_EQUAL 6)\n    qt_add_executable(test1\n        MANUAL_FINALIZATION\n        ${PROJECT_SOURCES}\n        ${RESOURCES_CPP}\n    )<\/code><\/pre>\n\n\n\n<p>QT\u5c5e\u6027\u7cfb\u7edf<a href=\"https:\/\/zhuanlan.zhihu.com\/p\/516163795\" target=\"_blank\"  rel=\"nofollow\" >Qt\u7b14\u8bb0(\u516d\u5341\u4e00)\u4e4bQt\u5c5e\u6027\u7cfb\u7edfQ_PROPERTY - \u77e5\u4e4e (zhihu.com)<\/a><\/p>\n\n\n\n<p>Opengl\u6e32\u67d3\u7ba1\u7ebf\u770b\u4e0d\u660e\u767d\uff0c\u5148\u770b\u4e00\u4e0bgames101\u590d\u4e60\u4e00\u4e0b\u8ba1\u7b97\u673a\u56fe\u5f62\u5b66<\/p>\n\n\n\n<p><a href=\"https:\/\/www.bilibili.com\/video\/BV1X7411F744\" target=\"_blank\"  rel=\"nofollow\" >https:\/\/www.bilibili.com\/video\/BV1X7411F744<\/a><\/p>\n\n\n\n<p>\u5148\u4eceopengl\u5f00\u59cb\u5b66\u5427\uff0c\u987a\u4fbf\u5728\u590d\u4e60\u4e00\u4e0b\u5de5\u7a0b\u7ba1\u7406\uff0cCmake\u4ec0\u4e48\u7684<\/p>\n\n\n\n<p><a href=\"https:\/\/www.bilibili.com\/video\/BV1PV41197Vo\/?spm_id_from=333.788&amp;vd_source=e203e20b728f2194924c7f8b9d5478c9\" target=\"_blank\"  rel=\"nofollow\" >\u3010B\u7ad9\u6700\u597dOpenGL\u30116-\u5de5\u7a0b\u7ba1\u7406-\u7f16\u8bd1\u4e0e\u94fe\u63a5_\u54d4\u54e9\u54d4\u54e9_bilibili<\/a><\/p>\n\n\n\n<p>\u5927\u6982\u628aopengl\u5165\u95e8\u90e8\u5206\u8fc7\u4e86\u4e00\u904d\uff0c\u73b0\u5728\u5f00\u59cb\u5728qt\u91cc\u5b9e\u73b0<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">QT OpenGL\u7a97\u53e3<\/h2>\n\n\n\n<p>\u9996\u5148\u65b0\u5efaqt\u5de5\u7a0b\uff0ccmake\u6784\u5efa\uff0c\u62d6\u5165opengl widget\uff0c\u5e76\u5728cmake\u4e2d\u5bfc\u5165<\/p>\n\n\n\n<p>\u5728\u5e2e\u52a9\u4e2d\u9009\u62e9\u7d22\u5f15\uff0c\u67e5\u627eQopenglWidget\uff0c\u590d\u5236cmake\u8bed\u53e5\u7c98\u8d34cmake\u6587\u4ef6<\/p>\n\n\n\n<p>\u5728mainwindow.cpp\u4e2d\u628aCentralWidget\u8bbe\u7f6e\u6210opengl\u7a97\u53e3<\/p>\n\n\n\n<p>\u4f46\u6211\u4eec\u8fd8\u662f\u60f3\u8981\u81ea\u5b9a\u4e49\u4e00\u4e2a\u57fa\u4e8eopengl\u7684widget\uff0c\u4e8e\u662f\u521b\u5efa\u4e00\u4e2aMyOpenGLWidget\u7c7b\u7ee7\u627f\u81eaQOpenGLWidget\uff0c\u4e4b\u540e\u5728mainwindow\u4e2d\u4f5c\u4e3a\u6210\u5458\u53d8\u91cf\u5e76\u8bbe\u7f6e\u4e3acentralWidget<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myopenglwidget.h\n#ifndef MYOPENGLWIDGET_H\n#define MYOPENGLWIDGET_H\n\n#include &lt;QOpenGLWidget&gt;\n\nclass MyOpenGLWidget : public QOpenGLWidget\n{\n    Q_OBJECT\npublic:\n    explicit MyOpenGLWidget(QWidget* parent = nullptr);\n};\n\n#endif \/\/ MYOPENGLWIDGET_H\n\nmyopenglwidget.cpp\n#include \"myopenglwidget.h\"\n\nMyOpenGLWidget::MyOpenGLWidget(QWidget* parent):QOpenGLWidget(parent)\n{\n}\n\nmainwindow.h\n#ifndef MAINWINDOW_H\n#define MAINWINDOW_H\n\n#include &lt;QMainWindow&gt;\n#include \"myopenglwidget.h\"\n\nQT_BEGIN_NAMESPACE\nnamespace Ui { class MainWindow; }\nQT_END_NAMESPACE\n\nclass MainWindow : public QMainWindow\n{\n    Q_OBJECT\n\npublic:\n    MainWindow(QWidget *parent = nullptr);\n    ~MainWindow();\n\nprivate:\n    Ui::MainWindow *ui;\n    MyOpenGLWidget *openGLWidget;\n};\n#endif \/\/ MAINWINDOW_H\n\nmainwindow.cpp\n#include \"mainwindow.h\"\n#include \".\/ui_mainwindow.h\"\n\nMainWindow::MainWindow(QWidget *parent)\n    : QMainWindow(parent)\n    , ui(new Ui::MainWindow)\n{\n    ui-&gt;setupUi(this);\n    openGLWidget = new MyOpenGLWidget(parent);\n    setCentralWidget(openGLWidget);\n}\n\nMainWindow::~MainWindow()\n{\n    delete ui;\n}<\/code><\/pre>\n\n\n\n<p>\u4e4b\u540e\u91cd\u5199OpenglWidget\u7684\u4e09\u4e2a\u5173\u952e\u51fd\u6570\uff0c\u5e76\u4e14\u591a\u91cd\u7ee7\u627f\uff0c\u52a0\u5165QOpenGLFunctions_4_5_Core\u4ee5\u8c03\u7528opengl\u7684\u51fd\u6570<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myopenglwidget.h\n#ifndef MYOPENGLWIDGET_H\n#define MYOPENGLWIDGET_H\n\n#include &lt;QOpenGLWidget&gt;\n#include &lt;QOpenGLFunctions_4_5_Core&gt;\n\nclass MyOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_4_5_Core\n{\n    Q_OBJECT\npublic:\n    explicit MyOpenGLWidget(QWidget* parent = nullptr);\n\nprotected:\n    virtual void initializeGL();\n    virtual void resizeGL(int w, int h);\n    virtual void paintGL();\n};\n\n#endif \/\/ MYOPENGLWIDGET_H\n\nmyopenglwidget.cpp\n#include \"myopenglwidget.h\"\n\nMyOpenGLWidget::MyOpenGLWidget(QWidget* parent):QOpenGLWidget(parent){\n\n}\n\nvoid MyOpenGLWidget::initializeGL()\n{\n    this-&gt;initializeOpenGLFunctions();\n}\n\nvoid MyOpenGLWidget::resizeGL(int w, int h)\n{\n\n}\n\nvoid MyOpenGLWidget::paintGL()\n{\n    glClearColor(0.2f,0.3f,0.3f,1.0f);\n    glClear(GL_COLOR_BUFFER_BIT);\n}<\/code><\/pre>\n\n\n\n<p>\u4e4b\u540eVBO\uff0cEBO\uff0cVAO\uff0cSHADER\u90fd\u548cVS\u73af\u5883\u4e0b\u4e00\u6837\uff0c\u7565\u8fc7\u3002<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"myopenglwidget.h\"\n\nMyOpenGLWidget::MyOpenGLWidget(QWidget* parent):QOpenGLWidget(parent){\n\n}\n\nMyOpenGLWidget::~MyOpenGLWidget()\n{\n    makeCurrent();glDeleteVertexArrays(1,&amp;vao);\n    glDeleteBuffers(1,&amp;colorVbo);\n    glDeleteBuffers(1,&amp;posVbo);\n    glDeleteBuffers(1,&amp;ebo);\n    glDeleteProgram(program);\n    doneCurrent();\n}\n\nvoid MyOpenGLWidget::initializeGL()\n{\n    this-&gt;initializeOpenGLFunctions();\n    \/\/prepareSingleBuffer();\n    prepareVAO();\n    prepareShader();\n}\n\nvoid MyOpenGLWidget::resizeGL(int w, int h)\n{\n\n}\n\nvoid MyOpenGLWidget::paintGL()\n{\n    glClearColor(0.2f,0.3f,0.3f,1.0f);\n    glClear(GL_COLOR_BUFFER_BIT);\n    \/\/1 \u7ed1\u5b9a\u5f53\u524d\u7684program\n    glUseProgram(program);\n\n    \/\/2 \u7ed1\u5b9a\u5f53\u524d\u7684vao\n    glBindVertexArray(vao);\n\n    \/\/3 \u53d1\u51fa\u7ed8\u5236\u6307\u4ee4\n    \/\/glDrawArrays(GL_TRIANGLES, 0, 3);\n    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);\n    glBindVertexArray(0);\n}\n\nvoid MyOpenGLWidget::prepareSingleBuffer() {\n    \/\/1 \u51c6\u5907positions colors\u6570\u636e\n    float positions&#91;] = {\n        -0.5f, -0.5f, 0.0f,\n        0.5f, -0.5f, 0.0f,\n        0.0f,  0.5f, 0.0f\n    };\n    float colors&#91;] = {\n        1.0f, 0.0f, 0.0f,\n        0.0f, 1.0f, 0.0f,\n        0.0f,  0.0f, 1.0f\n    };\n\n\n    \/\/2 \u4f7f\u7528\u6570\u636e\u751f\u6210\u4e24\u4e2avbo posVbo\uff0c colorVbo\n    GLuint posVbo, colorVbo;\n    glGenBuffers(1, &amp;posVbo);\n    glGenBuffers(1, &amp;colorVbo);\n\n    glBindBuffer(GL_ARRAY_BUFFER, posVbo);\n    glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);\n\n    glBindBuffer(GL_ARRAY_BUFFER, colorVbo);\n    glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);\n\n    \/\/3 \u751f\u6210vao\u5e76\u4e14\u7ed1\u5b9a\n    glGenVertexArrays(1, &amp;vao);\n    glBindVertexArray(vao);\n\n    \/\/4 \u5206\u522b\u5c06\u4f4d\u7f6e\/\u989c\u8272\u5c5e\u6027\u7684\u63cf\u8ff0\u4fe1\u606f\u52a0\u5165vao\u5f53\u4e2d\n    \/\/4.1\u63cf\u8ff0\u4f4d\u7f6e\u5c5e\u6027\n    glBindBuffer(GL_ARRAY_BUFFER, posVbo);\/\/\u53ea\u6709\u7ed1\u5b9a\u4e86posVbo\uff0c\u4e0b\u9762\u7684\u5c5e\u6027\u63cf\u8ff0\u624d\u4f1a\u4e0e\u6b64vbo\u76f8\u5173\n    glEnableVertexAttribArray(0);\n    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);\n\n    \/\/4.2 \u63cf\u8ff0\u989c\u8272\u5c5e\u6027\n    glBindBuffer(GL_ARRAY_BUFFER, colorVbo);\n    glEnableVertexAttribArray(1);\n    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);\n\n    glBindVertexArray(0);\n}\nvoid MyOpenGLWidget::prepareVAO() {\n    \/\/1 \u51c6\u5907positions\n    float positions&#91;] = {\n        -0.5f, -0.5f, 0.0f,\n        0.5f, -0.5f, 0.0f,\n        0.0f,  0.5f, 0.0f,\n        0.5f,  0.5f, 0.0f,\n    };\n    float colors&#91;] = {\n        1.0f, 0.0f, 0.0f,\n        0.0f, 1.0f, 0.0f,\n        0.0f,  0.0f, 1.0f,\n        0.3f,  0.1f, 0.7f\n    };\n\n    unsigned int indices&#91;] = {\n        0, 1, 2,\n        2, 1, 3\n    };\n\n    GLuint posVbo, colorVbo;\n    glGenBuffers(1, &amp;posVbo);\n    glGenBuffers(1, &amp;colorVbo);\n\n    glBindBuffer(GL_ARRAY_BUFFER, posVbo);\n    glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);\n\n    glBindBuffer(GL_ARRAY_BUFFER, colorVbo);\n    glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);\n\n    \/\/3 EBO\u521b\u5efa\n    GLuint ebo;\n    glGenBuffers(1, &amp;ebo);\n    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);\n    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);\n\n    \/\/4 VAO\u521b\u5efa\n    glGenVertexArrays(1, &amp;vao);\n    glBindVertexArray(vao);\n\n    \/\/5 \u7ed1\u5b9avbo ebo \u52a0\u5165\u5c5e\u6027\u63cf\u8ff0\u4fe1\u606f\n    \/\/5.1 \u5206\u522b\u5c06\u4f4d\u7f6e\/\u989c\u8272\u5c5e\u6027\u7684\u63cf\u8ff0\u4fe1\u606f\u52a0\u5165vao\u5f53\u4e2d\n    \/\/5.1.2\u63cf\u8ff0\u4f4d\u7f6e\u5c5e\u6027\n    glBindBuffer(GL_ARRAY_BUFFER, posVbo);\/\/\u53ea\u6709\u7ed1\u5b9a\u4e86posVbo\uff0c\u4e0b\u9762\u7684\u5c5e\u6027\u63cf\u8ff0\u624d\u4f1a\u4e0e\u6b64vbo\u76f8\u5173\n    glEnableVertexAttribArray(0);\n    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);\n\n    \/\/5.1.2 \u63cf\u8ff0\u989c\u8272\u5c5e\u6027\n    glBindBuffer(GL_ARRAY_BUFFER, colorVbo);\n    glEnableVertexAttribArray(1);\n    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);\n\n    \/\/5.2 \u52a0\u5165ebo\u5230\u5f53\u524d\u7684vao\n    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);\n\n    glBindVertexArray(0);\n}\nvoid MyOpenGLWidget::prepareShader() {\n    \/\/1 \u5b8c\u6210vs\u4e0efs\u7684\u6e90\u4ee3\u7801\uff0c\u5e76\u4e14\u88c5\u5165\u5b57\u7b26\u4e32\n    const char* vertexShaderSource =\n        \"#version 460 core\\n\"\n        \"layout (location = 0) in vec3 aPos;\\n\"\n        \"layout (location = 1) in vec3 aColor;\\n\"\n        \"out vec4 color;\\n\"\n        \"void main()\\n\"\n        \"{\\n\"\n        \"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\\n\"\n        \"   color = vec4(aColor,1.0f);\\n\"\n        \"}\\0\";\n    const char* fragmentShaderSource =\n        \"#version 330 core\\n\"\n        \"in vec4 color;\\n\"\n        \"out vec4 FragColor;\\n\"\n        \"void main()\\n\"\n        \"{\\n\"\n        \"   FragColor = color;\\n\"\n        \"}\\n\\0\";\n\n\n    \/\/2 \u521b\u5efaShader\u7a0b\u5e8f\uff08vs\u3001fs\uff09\n    GLuint vertex, fragment;\n    vertex = glCreateShader(GL_VERTEX_SHADER);\n    fragment = glCreateShader(GL_FRAGMENT_SHADER);\n\n\n    \/\/3 \u4e3ashader\u7a0b\u5e8f\u8f93\u5165shader\u4ee3\u7801\n    glShaderSource(vertex, 1, &amp;vertexShaderSource, NULL);\n    glShaderSource(fragment, 1, &amp;fragmentShaderSource, NULL);\n\n    int success = 0;\n    char infoLog&#91;1024];\n    \/\/4 \u6267\u884cshader\u4ee3\u7801\u7f16\u8bd1\n    glCompileShader(vertex);\n    \/\/\u68c0\u67e5vertex\u7f16\u8bd1\u7ed3\u679c\n    glGetShaderiv(vertex, GL_COMPILE_STATUS, &amp;success);\n    if (!success) {\n        glGetShaderInfoLog(vertex, 1024, NULL, infoLog);\n        qDebug()&lt;&lt; \"Error: SHADER COMPILE ERROR --VERTEX\" &lt;&lt; \"\\n\" &lt;&lt; infoLog;\n    }\n\n    glCompileShader(fragment);\n    \/\/\u68c0\u67e5fragment\u7f16\u8bd1\u7ed3\u679c\n    glGetShaderiv(fragment, GL_COMPILE_STATUS, &amp;success);\n    if (!success) {\n        glGetShaderInfoLog(fragment, 1024, NULL, infoLog);\n        qDebug()&lt;&lt; \"Error: SHADER COMPILE ERROR --VERTEX\" &lt;&lt; \"\\n\" &lt;&lt; infoLog;\n    }\n\n    \/\/5 \u521b\u5efa\u4e00\u4e2aProgram\u58f3\u5b50\n    program = glCreateProgram();\n\n    \/\/6 \u5c06vs\u4e0efs\u7f16\u8bd1\u597d\u7684\u7ed3\u679c\u653e\u5230program\u8fd9\u4e2a\u58f3\u5b50\u91cc\n    glAttachShader(program, vertex);\n    glAttachShader(program, fragment);\n\n    \/\/7 \u6267\u884cprogram\u7684\u94fe\u63a5\u64cd\u4f5c\uff0c\u5f62\u6210\u6700\u7ec8\u53ef\u6267\u884cshader\u7a0b\u5e8f\n    glLinkProgram(program);\n\n    \/\/\u68c0\u67e5\u94fe\u63a5\u9519\u8bef\n    glGetProgramiv(program, GL_LINK_STATUS, &amp;success);\n    if (!success) {\n        glGetProgramInfoLog(program, 1024, NULL, infoLog);\n        \/\/std::cout &lt;&lt; \"Error: SHADER LINK ERROR \" &lt;&lt; \"\\n\" &lt;&lt; infoLog &lt;&lt; std::endl;\n    }\n\n    \/\/\u6e05\u7406\n    glDeleteShader(vertex);\n    glDeleteShader(fragment);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">QOpenGLShaderProgram<\/h2>\n\n\n\n<p>\u81ea\u5e26\u7684QOpenGLShaderProgram\u7ed9shader\u6ce8\u518c\u548c\u7ed1\u5b9a\u90fd\u5e26\u4e86\u904d\u5386\uff0c\u5728qt\u9879\u76ee\u4e2d\u65b0\u5efa\u8d44\u6e90\u6587\u4ef6\u5939\uff0c\u5c06\u73b0\u6709\u7684shader\u4ee3\u7801\u653e\u8fdb\u6587\u672c\u6587\u4ef6\u4e2d\uff0c\u7531QOpenGLShaderProgram\u8c03\u7528<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void MyOpenGLWidget::prepareShaderProgram(){\n    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,\":\/shaders\/shapes.vert\");\n    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,\":\/shaders\/shapes.frag\");\n    bool success = shaderProgram.link();\n    if(!success){\n        shaderProgram.log();\n    }\n    shaderProgram.bind();\n}\n\nvoid MyOpenGLWidget::paintGL()\n{\n    glClearColor(0.2f,0.3f,0.3f,1.0f);\n    glClear(GL_COLOR_BUFFER_BIT);\n    \/\/1 \u7ed1\u5b9a\u5f53\u524d\u7684program\n    \/\/glUseProgram(program);\n    glUseProgram(shaderProgram.programId());\n\n    \/\/2 \u7ed1\u5b9a\u5f53\u524d\u7684vao\n    glBindVertexArray(vao);\n\n    \/\/3 \u53d1\u51fa\u7ed8\u5236\u6307\u4ee4\n    \/\/glDrawArrays(GL_TRIANGLES, 0, 3);\n    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);\n    glBindVertexArray(0);\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Uniform<\/h2>\n\n\n\n<p>shader\u7684uniform\u5982\u679c\u8981\u968f\u65f6\u95f4\u53d8\u5316\u7684\u8bdd\uff0c\u5728qt\u91cc\u9762\u7684\u5b9e\u73b0\u4e00\u822c\u662f\u8c03\u7528\u5b9a\u65f6\u5668<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MyOpenGLWidget::MyOpenGLWidget(QWidget* parent):QOpenGLWidget(parent){\n    timer.setInterval(15);\n    connect(&amp;timer,&amp;QTimer::timeout,&#91;=](){\n        makeCurrent();\n        int timeValue = QTime::currentTime().msec()\/999;\n        setUniformFloat(\"time\",timeValue);\n        doneCurrent();\n        update();\n    });\n    timer.start();\n}\nvoid MyOpenGLWidget::setUniformFloat(const QString &amp;name, float value)\n{\n    \/\/1 \u901a\u8fc7\u540d\u79f0\u62ff\u5230Uniform\u53d8\u91cf\u7684\u4f4d\u7f6eLocation\n    GLint location = glGetUniformLocation(shaderProgram.programId(), name.toStdString().c_str());\n\n    \/\/qDebug()&lt;&lt;value;\n\n    \/\/2 \u901a\u8fc7Location\u66f4\u65b0Uniform\u53d8\u91cf\u7684\u503c\n    shaderProgram.setUniformValue(location, value);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Texture<\/h2>\n\n\n\n<p>\u5bf9\u4e8eTexture\uff0cqt\u4e5f\u6709\u76f8\u5e94\u7684\u5c01\u88c5<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/.h\n    QOpenGLTexture* texture0;\n    QOpenGLTexture* texture1;\n\n\/\/.cpp - preparetexture()\n    texture0 = new QOpenGLTexture(QOpenGLTexture::Target2D);\n    texture0-&gt;setMinificationFilter(QOpenGLTexture::Linear);\n    texture0-&gt;setMagnificationFilter(QOpenGLTexture::Linear);\n    texture0-&gt;setWrapMode(QOpenGLTexture::ClampToEdge);\n    texture0-&gt;setData(QImage(\":\/resources\/sayo.jpg\").mirrored());\n\n    texture1 = new QOpenGLTexture(QOpenGLTexture::Target2D);\n    texture1-&gt;setMinificationFilter(QOpenGLTexture::Linear);\n    texture1-&gt;setMagnificationFilter(QOpenGLTexture::Linear);\n    texture1-&gt;setWrapMode(QOpenGLTexture::ClampToEdge);\n    texture1-&gt;setData(QImage(\":\/resources\/maomiao.png\").mirrored());\n\n\/\/.cpp - paintGL()\n    texture0-&gt;bind(0);\n    texture1-&gt;bind(1);\n\n\/\/frag.glsl\n#version 460 core\nin vec4 color;\nin vec2 TexCoord;\nout vec4 FragColor;\nuniform sampler2D texture0;\nuniform sampler2D texture1;\nvoid main()\n{\n   \/\/FragColor = color;\n    FragColor = mix(texture(texture0,TexCoord),texture(texture1,TexCoord),0.5)*color;\n};<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Matrix<\/h2>\n\n\n\n<p>Qt\u81ea\u5e26\u7684Matrix\u7c7b\uff0c\u597d\u7528\uff01<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MyOpenGLWidget::MyOpenGLWidget(QWidget* parent):QOpenGLWidget(parent){\n    timer.setInterval(15);\n    connect(&amp;timer,&amp;QTimer::timeout,&#91;=](){\n        makeCurrent();\n        float timeValue = QTime::currentTime().msec()\/1000.0f*360.0f;\n        \/\/qDebug()&lt;&lt;timeValue;\n        QMatrix4x4 matrix;\n        matrix.translate(0.5f,-0.5f,0.0f);\n        matrix.rotate(timeValue,0.1f,0.1f,1.0f);\n        shaderProgram.setUniformValue(\"rotationmMatrix\",matrix);\n        doneCurrent();\n        update();\n    });\n    timer.start();\n}\n\n#version 460 core\nlayout (location = 0) in vec3 aPos;\nlayout (location = 1) in vec3 aColor;\nlayout (location = 2) in vec2 aTexCoord;\n\nout vec4 color;\nout vec2 TexCoord;\nuniform mat4 rotationmMatrix;\n\/\/uniform float time;\n\nvoid main()\n{\n   gl_Position = rotationmMatrix*vec4(aPos.x, aPos.y, aPos.z, 1.0);\n   \/\/gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n   color = vec4(aColor, 1.0f);\n   TexCoord = aTexCoord;\n};<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u5750\u6807\u7cfb<\/h2>\n\n\n\n<p>\u5c40\u90e8\u7a7a\u95f4-\u4e16\u754c\u7a7a\u95f4-\u89c2\u5bdf\u7a7a\u95f4-\u88c1\u526a\u7a7a\u95f4-\u6b63\u5c04\u6295\u5f71\/\u900f\u89c6\u6295\u5f71<\/p>\n\n\n\n<p>\u7531\u4e8e\u77e9\u9635\u4e58\u6cd5\u6027\u8d28\uff0c\u8981\u4ece\u53f3\u5411\u5de6\u4f9d\u6b21\u4e58<\/p>\n\n\n\n<p>Vclip=Mprojection\u22c5Mview\u22c5Mmodel\u22c5Vlocal<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.h\n#ifndef MYOPENGLWIDGET_H\r\n#define MYOPENGLWIDGET_H\r\n\r\n#include &lt;QOpenGLWidget>\r\n#include &lt;QOpenGLFunctions_4_5_Core>\r\n#include &lt;QOpenGLShaderProgram>\r\n#include &lt;QTimer>\r\n#include &lt;QTime>\r\n#include &lt;QOpenGLTexture>\r\n\r\nclass myOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_4_5_Core\r\n{\r\n    Q_OBJECT\r\npublic:\r\n    explicit myOpenGLWidget(QWidget* parent = nullptr);\r\n    ~myOpenGLWidget();\r\n\r\npublic:\r\n    void prepareInterleavedBuffer();\r\n    void prepareShaderProgram();\r\n    void prepareMatrix();\r\n\r\nprotected:\r\n    virtual void initializeGL();\r\n    virtual void resizeGL(int w, int h);\r\n    virtual void paintGL();\r\n\r\nprivate:\r\n    GLuint vbo,vao;\r\n    QOpenGLShaderProgram shaderProgram;\r\n    QOpenGLTexture* texture0;\r\n    QTimer timer;\r\n    QMatrix4x4 projection,view,model;\r\n\r\nprivate:\r\n    void checkError();\r\n};\r\n\r\n#endif \/\/ MYOPENGLWIDGET_H\n\n.cpp\n#include \"myopenglwidget.h\"\r\n\r\nmyOpenGLWidget::myOpenGLWidget(QWidget* parent):QOpenGLWidget(parent)\r\n{\r\n    timer.setInterval(15);\r\n    connect(&amp;timer, &amp;QTimer::timeout, this, &#91;=](){update();});\r\n    timer.start();\r\n}\r\n\r\nmyOpenGLWidget::~myOpenGLWidget()\r\n{\r\n    qDebug()&lt;&lt;\"release\";\r\n    delete texture0;\r\n    makeCurrent();\r\n    glDeleteVertexArrays(1,&amp;vao);\r\n    glDeleteBuffers(1,&amp;vbo);\r\n    doneCurrent();\r\n}\r\n\r\nvoid myOpenGLWidget::prepareInterleavedBuffer()\r\n{\r\n    float vertices&#91;] = {\r\n        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,\r\n        0.5f, -0.5f, -0.5f,  1.0f, 0.0f,\r\n        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,\r\n        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,\r\n        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,\r\n        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,\r\n\r\n        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,\r\n        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,\r\n        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,\r\n        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,\r\n        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,\r\n        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,\r\n\r\n        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,\r\n        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,\r\n        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,\r\n        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,\r\n        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,\r\n        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,\r\n\r\n        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,\r\n        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,\r\n        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,\r\n        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,\r\n        0.5f, -0.5f,  0.5f,  0.0f, 0.0f,\r\n        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,\r\n\r\n        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,\r\n        0.5f, -0.5f, -0.5f,  1.0f, 1.0f,\r\n        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,\r\n        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,\r\n        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,\r\n        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,\r\n\r\n        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,\r\n        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,\r\n        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,\r\n        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,\r\n        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,\r\n        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f\r\n    };\r\n    glGenBuffers(1,&amp;vbo);\r\n    glBindBuffer(GL_ARRAY_BUFFER,vbo);\r\n    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);\r\n\r\n    glGenVertexArrays(1,&amp;vao);\r\n    glBindVertexArray(vao);\r\n    glBindBuffer(GL_ARRAY_BUFFER, vbo);\r\n    \/\/position\r\n    glEnableVertexAttribArray(0);\r\n    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);\r\n\r\n    \/\/uv\r\n    glEnableVertexAttribArray(1);\r\n    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float),  (void*)(3 * sizeof(float)));\r\n\r\n    texture0 = new QOpenGLTexture(QOpenGLTexture::Target2D);\r\n    texture0->setMinificationFilter(QOpenGLTexture::Linear);\r\n    texture0->setMagnificationFilter(QOpenGLTexture::Linear);\r\n    texture0->setWrapMode(QOpenGLTexture::Repeat);\r\n    texture0->setData(QImage(\":\/resources\/sayo.jpg\").mirrored());\r\n\r\n    glBindVertexArray(0);\r\n    glBindBuffer(GL_ARRAY_BUFFER,0);\r\n\r\n    projection.setToIdentity();\r\n    projection.perspective(45,(float)width()\/height(),0.1f,100.0f);\r\n    shaderProgram.setUniformValue(\"projection\",projection);\r\n\r\n    view.setToIdentity();\r\n    view.translate(0.0f,0.0f,-3.0f);\r\n    shaderProgram.setUniformValue(\"view\",view);\r\n\r\n}\r\n\r\nvoid myOpenGLWidget::prepareShaderProgram()\r\n{\r\n    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,\":\/shaders\/shapes.vert\");\r\n    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,\":\/shaders\/shapes.frag\");\r\n    bool success = shaderProgram.link();\r\n    if(!success){\r\n        shaderProgram.log();\r\n    }\r\n    shaderProgram.bind();\r\n    shaderProgram.setUniformValue(\"texture0\",0);\r\n}\r\n\r\nvoid myOpenGLWidget::prepareMatrix()\r\n{\r\n    QMatrix4x4 matrix;\r\n    matrix.rotate(150,30,30,1);\r\n    \/\/matrix.translate(0.5f,-0.5f,0.0f);\r\n    shaderProgram.setUniformValue(\"rotationMatrix\",matrix);\r\n}\r\n\r\nvoid myOpenGLWidget::initializeGL()\r\n{\r\n    this->initializeOpenGLFunctions();\r\n    prepareShaderProgram();\r\n    prepareInterleavedBuffer();\r\n    \/\/prepareMatrix();\r\n    glEnable(GL_DEPTH_TEST);\r\n}\r\n\r\nvoid myOpenGLWidget::resizeGL(int w, int h)\r\n{\r\n\r\n}\r\n\r\nvoid myOpenGLWidget::paintGL()\r\n{\r\n    glClearColor(0.2f,0.3f,0.3f,1.0f);\r\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r\n    glUseProgram(shaderProgram.programId());\r\n    glBindVertexArray(vao);\r\n    texture0->bind(0);\r\n    model.setToIdentity();\r\n    float timeValue = QTime::currentTime().msec()\/999.0f*360;\r\n    model.rotate(timeValue,30.0f,30.0f,0.0f);\r\n    shaderProgram.setUniformValue(\"model\",model);\r\n    glDrawArrays(GL_TRIANGLES, 0, 36);\r\n    glBindVertexArray(0);\r\n    texture0->release();\r\n}\n\nglsl\n#version 460 core\r\nlayout (location = 0) in vec3 aPos;\r\nlayout (location = 1) in vec2 aTexCoord;\r\n\r\nout vec2 TexCoord;\r\nuniform mat4 model;\r\nuniform mat4 view;\r\nuniform mat4 projection;\r\n\r\nvoid main()\r\n{\r\n   gl_Position = projection*view*model*vec4(aPos.x, aPos.y, aPos.z, 1.0);\r\n   \/\/gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\r\n   TexCoord = aTexCoord;\r\n};\r<\/code><\/pre>\n\n\n\n<p>\u7ed8\u5236\u66f4\u591a\u7acb\u65b9\u4f53\uff0c\u5176\u5b9e\u5c31\u662f\u5e73\u79fb\u52a0\u591a\u6b21\u8c03\u7528program<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"504\" src=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724435286-image-1024x504.png\" alt=\"\" class=\"wp-image-1334\" style=\"width:878px;height:auto\" srcset=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724435286-image-1024x504.png 1024w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724435286-image-300x148.png 300w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724435286-image-768x378.png 768w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724435286-image-1536x756.png 1536w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724435286-image-2048x1008.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">\u6444\u50cf\u673a<\/h2>\n\n\n\n<p>\u524d\u9762\u8ba8\u8bba\u4e86\u89c2\u5bdf\u77e9\u9635\u4ee5\u53ca\u5982\u4f55\u4f7f\u7528\u89c2\u5bdf\u77e9\u9635\u79fb\u52a8\u573a\u666f\uff08\u6211\u4eec\u5411\u540e\u79fb\u52a8\u4e86\u4e00\u70b9\uff09\u3002OpenGL\u672c\u8eab\u6ca1\u6709<strong>\u6444\u50cf\u673a<\/strong>(Camera)\u7684\u6982\u5ff5\uff0c\u4f46\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u628a\u573a\u666f\u4e2d\u7684\u6240\u6709\u7269\u4f53\u5f80\u76f8\u53cd\u65b9\u5411\u79fb\u52a8\u7684\u65b9\u5f0f\u6765\u6a21\u62df\u51fa\u6444\u50cf\u673a\uff0c\u4ea7\u751f\u4e00\u79cd<strong>\u6211\u4eec<\/strong>\u5728\u79fb\u52a8\u7684\u611f\u89c9\uff0c\u800c\u4e0d\u662f\u573a\u666f\u5728\u79fb\u52a8\u3002<\/p>\n\n\n\n<p><a href=\"https:\/\/www.bilibili.com\/video\/BV1Qf421q7Dt?p=32&amp;vd_source=e203e20b728f2194924c7f8b9d5478c9\" target=\"_blank\"  rel=\"nofollow\" >F1\u6444\u50cf\u673a_\u54d4\u54e9\u54d4\u54e9_bilibili<\/a><\/p>\n\n\n\n<p>\u6444\u50cf\u673a\u5411\u91cf\u8ba1\u7b97\u539f\u7406<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"571\" src=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483494-image-1024x571.png\" alt=\"\" class=\"wp-image-1337\" style=\"width:840px;height:auto\" srcset=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483494-image-1024x571.png 1024w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483494-image-300x167.png 300w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483494-image-768x428.png 768w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483494-image-1536x857.png 1536w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483494-image-2048x1142.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>\u7531lookat\u5c01\u88c5\u597d\u7684api<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"535\" src=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483552-image-1024x535.png\" alt=\"\" class=\"wp-image-1338\" style=\"width:842px;height:auto\" srcset=\"https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483552-image-1024x535.png 1024w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483552-image-300x157.png 300w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483552-image-768x401.png 768w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483552-image-1536x803.png 1536w, https:\/\/www.gislxz.com\/wp-content\/uploads\/2024\/08\/1724483552-image-2048x1071.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>void myOpenGLWidget::keyPressEvent(QKeyEvent *event)\r\n{\r\n    currentFrame = elapsedTimer.elapsed();\r\n    float deltaTime = currentFrame-lastFrame;\r\n    if(deltaTime>50) deltaTime = 50;\r\n    lastFrame = currentFrame;\r\n    float cameraSpeed = 0.004*deltaTime;\r\n    QVector3D up(0.0f,1.0f,0.0f);\r\n    QVector3D cameraRight = QVector3D::crossProduct(cameraFront,up);\r\n    switch(event->key()){\r\n    case Qt::Key_W:cameraPos += cameraSpeed*cameraFront;break;\r\n    case Qt::Key_S:cameraPos -= cameraSpeed*cameraFront;break;\r\n    case Qt::Key_A:cameraPos -= cameraSpeed*cameraRight;break;\r\n    case Qt::Key_D:cameraPos += cameraSpeed*cameraRight;break;\r\n    }\r\n}\r\n\r\nvoid myOpenGLWidget::mouseMoveEvent(QMouseEvent *event)\r\n{\r\n    static QPoint deltaPos;\r\n    static QPoint lastPos;\r\n    static float yaw=-90;\r\n    static float pitch=0;\r\n\r\n    auto currentPos=event->pos();\r\n    deltaPos=currentPos-lastPos;\r\n    \/\/qDebug()&lt;&lt;deltaPos.x()&lt;&lt;\",\"&lt;&lt;deltaPos.y();\r\n    if(abs(deltaPos.x())>50||abs(deltaPos.y())>50) deltaPos=QPoint(0,0);\r\n    lastPos=currentPos;\r\n    float sensitivity = 0.1f;\/\/ change this value to your liking\r\n    deltaPos *= sensitivity;\r\n    yaw += deltaPos.x();\r\n    pitch -= deltaPos.y();\/\/reversed since y-coordinates go from bottom\r\n    if(pitch >89.0f)pitch = 89.0f;\r\n    if(pitch&lt;-89.0f)pitch = -89.0f;\r\n    cameraFront.setX(cos(yaw*M_PI\/180)*cos(pitch*M_PI\/180));\r\n    cameraFront.setY(sin(pitch*M_PI\/180));\r\n    cameraFront.setZ(sin(yaw*M_PI\/180)*cos(pitch*M_PI\/180));\r\n    cameraFront.normalize();\r\n}\r\n\r\nvoid myOpenGLWidget::wheelEvent(QWheelEvent *event)\r\n{\r\n    fov -= event->angleDelta().y()\/120;\r\n    if(fov&lt;=1.0) fov = 1.0f;\r\n    if(fov>=75.0f) fov = 75.0f;\r\n    makeCurrent();\r\n    projection.setToIdentity();\r\n    projection.perspective(fov,(float)width()\/height(),0.1f,100.0f);\r\n    shaderProgram.setUniformValue(\"projection\",projection);\r\n    doneCurrent();\r\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u5149\u7167<\/h2>\n\n\n\n<p>\u8bbe\u7f6e\u5149\u6e90\u4f4d\u7f6e\u3001\u989c\u8272<\/p>\n\n\n\n<p>\u6a21\u578b\u52a0\u4e0a\u6cd5\u7ebf\uff0c\u4e3b\u8981\u662f\u6539shader<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>shapes.vert\n#version 460 core\r\nlayout (location = 0) in vec3 aPos;\r\nlayout (location = 1) in vec3 aNormal;\r\nout vec3 FragPos;\r\nout vec3 Normal;\r\nuniform mat4 model;\r\nuniform mat4 view;\r\nuniform mat4 projection;\r\n\r\nvoid main()\r\n{\r\n   gl_Position = projection*view*model*vec4(aPos, 1.0);\r\n   FragPos = vec3(model * vec4(aPos, 1.0));\r\n   \/\/Normal = vec3(model*vec4(aNormal,1.0));\r\n   Normal = mat3(transpose(inverse(model))) * aNormal;\r\n};\n\nshapes.frag\n#version 460 core\r\nin vec3 Normal;\r\nin vec3 FragPos;\r\nout vec4 FragColor;\r\nuniform vec3 lightColor;\r\nuniform vec3 objectColor;\r\nuniform vec3 lightPos;\r\nuniform vec3 viewPos;\r\n\r\nvoid main()\r\n{\r\n    \/\/ambient\u73af\u5883\u5149\r\n    float ambientStrength = 0.1;\r\n    vec3 ambient = ambientStrength * lightColor;\r\n    \/\/diffuse\u6f2b\u53cd\u5c04\r\n    vec3 norm = normalize(Normal);\r\n    vec3 lightDir = normalize(lightPos - FragPos);\r\n    float diff = max(dot(norm, lightDir), 0.0);\r\n    vec3 diffuse = diff * lightColor;\r\n    \/\/specular\u955c\u9762\u53cd\u5c04\r\n    float specularStrength = 0.5;\r\n    vec3 viewDir = normalize(viewPos-FragPos);\r\n    vec3 reflectDir = reflect(-lightDir,norm);\r\n    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);\r\n    vec3 specular = specularStrength * spec * lightColor;\r\n    vec3 result = (ambient + diffuse + specular) * objectColor;\r\n    FragColor = vec4(result, 1.0);\r\n};\n\nmyopenglwidget.cpp\n#include \"myopenglwidget.h\"\r\n\r\nmyOpenGLWidget::myOpenGLWidget(QWidget* parent):QOpenGLWidget(parent)\r\n{\r\n    setFocusPolicy(Qt::StrongFocus);\r\n    elapsedTimer.start();\r\n    timer.setInterval(15);\r\n    connect(&amp;timer, &amp;QTimer::timeout, this, &#91;=](){update();});\r\n    timer.start();\r\n}\r\n\r\nmyOpenGLWidget::~myOpenGLWidget()\r\n{\r\n    qDebug()&lt;&lt;\"release\";\r\n    makeCurrent();\r\n    glDeleteVertexArrays(1,&amp;vao);\r\n    glDeleteBuffers(1,&amp;vbo);\r\n    doneCurrent();\r\n}\r\n\r\nvoid myOpenGLWidget::initializeGL()\r\n{\r\n    this->initializeOpenGLFunctions();\r\n    prepareShaderPrograms();\r\n    prepareLightingBuffer();\r\n    prepareMatrixs();\r\n    glEnable(GL_DEPTH_TEST);\r\n}\r\n\r\nvoid myOpenGLWidget::resizeGL(int w, int h)\r\n{\r\n\r\n}\r\n\r\nvoid myOpenGLWidget::paintGL()\r\n{\r\n    glClearColor(0.2f,0.3f,0.3f,1.0f);\r\n    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r\n    glBindVertexArray(vao);\r\n\r\n    shaderProgram.bind();\r\n    float timeValue = elapsedTimer.elapsed()\/1000.0f;\r\n    model.setToIdentity();\r\n    model.rotate(timeValue*15,35.0f,30.0f,1.0f);\r\n    shaderProgram.setUniformValue(\"projection\",projection);\r\n    shaderProgram.setUniformValue(\"model\",model);\r\n    shaderProgram.setUniformValue(\"view\",view);\r\n    shaderProgram.setUniformValue(\"viewPos\",cameraPos);\r\n    glDrawArrays(GL_TRIANGLES, 0, 36);\r\n\r\n    lightingShaderProgram.bind();\r\n    QMatrix4x4 model1;\r\n    model1.setToIdentity();\r\n    model1.translate(lightPos);\r\n    model1.scale(0.2f);\r\n    \/\/qDebug()&lt;&lt;model1;\r\n    lightingShaderProgram.setUniformValue(\"projection\",projection);\r\n    lightingShaderProgram.setUniformValue(\"model\",model1);\r\n    lightingShaderProgram.setUniformValue(\"view\",view);\r\n    glDrawArrays(GL_TRIANGLES, 0, 36);\r\n\r\n    glBindVertexArray(0);\r\n}\r\n\r\nvoid myOpenGLWidget::prepareLightingBuffer()\r\n{\r\n    float vertices&#91;] = {\r\n        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,\r\n        0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,\r\n        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,\r\n        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,\r\n        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,\r\n        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,\r\n\r\n        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,\r\n        0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,\r\n        0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,\r\n        0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,\r\n        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,\r\n        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,\r\n\r\n        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,\r\n        -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,\r\n        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,\r\n        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,\r\n        -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,\r\n        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,\r\n\r\n        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,\r\n        0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,\r\n        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,\r\n        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,\r\n        0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,\r\n        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,\r\n\r\n        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,\r\n        0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,\r\n        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,\r\n        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,\r\n        -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,\r\n        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,\r\n\r\n        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,\r\n        0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,\r\n        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,\r\n        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,\r\n        -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,\r\n        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f\r\n    };\r\n\r\n    glGenBuffers(1,&amp;vbo);\r\n    glBindBuffer(GL_ARRAY_BUFFER,vbo);\r\n    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);\r\n\r\n    glGenVertexArrays(1,&amp;vao);\r\n    glBindVertexArray(vao);\r\n    glBindBuffer(GL_ARRAY_BUFFER, vbo);\r\n\r\n    \/\/position\r\n    glEnableVertexAttribArray(0);\r\n    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)0);\r\n\r\n    \/\/Normal\r\n    glEnableVertexAttribArray(1);\r\n    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)(3*sizeof(float)));\r\n\r\n    glBindVertexArray(0);\r\n    glBindBuffer(GL_ARRAY_BUFFER,0);\r\n}\r\n\r\nvoid myOpenGLWidget::prepareShaderPrograms()\r\n{\r\n    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,\":\/shaders\/shapes.vert\");\r\n    shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,\":\/shaders\/shapes.frag\");\r\n    bool success = shaderProgram.link();\r\n    if(!success){\r\n        shaderProgram.log();\r\n    }\r\n    shaderProgram.bind();\r\n    shaderProgram.setUniformValue(\"lightColor\",lightColor);\r\n    shaderProgram.setUniformValue(\"objectColor\",objectColor);\r\n    shaderProgram.setUniformValue(\"lightPos\",lightPos);\r\n\r\n    lightingShaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,\":\/shaders\/lighting.vert\");\r\n    lightingShaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,\":\/shaders\/lighting.frag\");\r\n    success = lightingShaderProgram.link();\r\n    if(!success){\r\n        lightingShaderProgram.log();\r\n    }\r\n    lightingShaderProgram.bind();\r\n    lightingShaderProgram.setUniformValue(\"lightColor\",lightColor);\r\n}\r\n\r\nvoid myOpenGLWidget::prepareMatrixs()\r\n{\r\n    projection.setToIdentity();\r\n    projection.perspective(fov,(float)width()\/height(),0.1f,100.0f);\r\n    model.setToIdentity();\r\n    model.rotate(130.0f,120.0f,150.0f,0.0f);\r\n    view.setToIdentity();\r\n    view.lookAt(cameraPos,cameraPos+cameraFront,QVector3D(0.0f,1.0f,0.0f));\r\n}\r\n\r\nvoid myOpenGLWidget::mouseMoveEvent(QMouseEvent *event)\r\n{\r\n    static QPoint deltaPos;\r\n    static QPoint lastPos;\r\n    static float yaw=-90;\r\n    static float pitch=0;\r\n\r\n    auto currentPos=event->pos();\r\n    deltaPos=currentPos-lastPos;\r\n    \/\/qDebug()&lt;&lt;deltaPos.x()&lt;&lt;\",\"&lt;&lt;deltaPos.y();\r\n    if(abs(deltaPos.x())>50||abs(deltaPos.y())>50) deltaPos=QPoint(0,0);\r\n    lastPos=currentPos;\r\n    float sensitivity = 0.1f;\/\/ change this value to your liking\r\n    deltaPos *= sensitivity;\r\n    yaw += deltaPos.x();\r\n    pitch -= deltaPos.y();\/\/reversed since y-coordinates go from bottom\r\n    if(pitch >89.0f)pitch = 89.0f;\r\n    if(pitch&lt;-89.0f)pitch = -89.0f;\r\n    cameraFront.setX(cos(yaw*M_PI\/180)*cos(pitch*M_PI\/180));\r\n    cameraFront.setY(sin(pitch*M_PI\/180));\r\n    cameraFront.setZ(sin(yaw*M_PI\/180)*cos(pitch*M_PI\/180));\r\n    cameraFront.normalize();\r\n    \/\/shaderProgram.bind();\r\n    view.setToIdentity();\r\n    view.lookAt(cameraPos,cameraPos+cameraFront,QVector3D(0.0f,1.0f,0.0f));\r\n    \/\/shaderProgram.setUniformValue(\"view\",view);\r\n    update();\r\n}\r\n\r\nvoid myOpenGLWidget::wheelEvent(QWheelEvent *event)\r\n{\r\n    fov -= event->angleDelta().y()\/120;\r\n    if(fov&lt;=1.0) fov = 1.0f;\r\n    if(fov>=75.0f) fov = 75.0f;\r\n    \/\/shaderProgram.bind();\r\n    projection.setToIdentity();\r\n    projection.perspective(fov,(float)width()\/height(),0.1f,100.0f);\r\n    \/\/shaderProgram.setUniformValue(\"projection\",projection);\r\n    update();\r\n}\r\n\r\nvoid myOpenGLWidget::keyPressEvent(QKeyEvent *event)\r\n{\r\n    currentFrame = elapsedTimer.elapsed();\r\n    float deltaTime = currentFrame-lastFrame;\r\n    if(deltaTime>50) deltaTime = 50;\r\n    lastFrame = currentFrame;\r\n    float cameraSpeed = 0.002*deltaTime;\r\n    QVector3D up(0.0f,1.0f,0.0f);\r\n    QVector3D cameraRight = QVector3D::crossProduct(cameraFront,up);\r\n    switch(event->key()){\r\n    case Qt::Key_W:cameraPos += cameraSpeed*cameraFront;break;\r\n    case Qt::Key_S:cameraPos -= cameraSpeed*cameraFront;break;\r\n    case Qt::Key_A:cameraPos -= cameraSpeed*cameraRight;break;\r\n    case Qt::Key_D:cameraPos += cameraSpeed*cameraRight;break;\r\n    }\r\n    \/\/shaderProgram.bind();\r\n    view.setToIdentity();\r\n    view.lookAt(cameraPos,cameraPos+cameraFront,QVector3D(0.0f,1.0f,0.0f));\r\n    \/\/shaderProgram.setUniformValue(\"view\",view);\r\n    update();\r\n}\r<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u9996\u5148\u521b\u5efa\u4e00\u4e2a\u9ed8\u8ba4qt widget\u9879\u76ee\uff0c\u7136\u540e\u7528git\u505a\u4e00\u4e0b\u7248\u672c\u63a7\u5236\uff0c\u5947\u602a\u7684\u662f\u6211github\u4e0a\u7684\u9879\u76ee\u4ec0\u4e48\u6587\u4ef6\u90fd\u6ca1\u6709\uff0cpush\u65f6\u5374\u63d0\u9192 &#8230;<\/p>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1293","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/posts\/1293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/comments?post=1293"}],"version-history":[{"count":10,"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/posts\/1293\/revisions"}],"predecessor-version":[{"id":1342,"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/posts\/1293\/revisions\/1342"}],"wp:attachment":[{"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/media?parent=1293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/categories?post=1293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gislxz.com\/index.php\/wp-json\/wp\/v2\/tags?post=1293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}