QT 移植LearnOpenGL 代码

前言

LearnOpenGL 网址:
https://learnopengl-cn.github.io/

LearnOpenGL : GLAD(提供opengl 库函数)+ GLFW(界面窗口)

以“立方体贴图”为例,移植到QT 平台,用GLEW 提供opengl 函数库

LearnOpenGL代码:
https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/06%20Cubemaps/

https://learnopengl.com/code_viewer_gh.php?code=src/4.advanced_opengl/6.2.cubemaps_environment_mapping/cubemaps_environment_mapping.cpp

一 、 环境配置

环境: Qt5.12.7
1、配置glew库lib,pro文件中添加如下:

    LIBS += -L$$quote("D:\Works\code\opengl\QGLDemo\openGL\libs") -lglew32

2、SkyboxForm 继承QOpenGLExtraFunctions,便于直接试用opengl 函数,代码风格和learnopengl 一致

class SkyboxForm :public QOpenGLWidget ,public QOpenGLExtraFunctions
{
}

二、使用步骤

1.initializeGL()

代码如下(示例):

GLenum err = glewInit();
	if (err != GLEW_OK) {
		std::cerr << "GLEW initialization failed" << std::endl;
		fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
		return;
	}
    //初始化opengl 函数
     initializeOpenGLFunctions();
	
     glEnable(GL_DEPTH_TEST);

     // ------------------------------------------------------------------
        float cubeVertices[] = {
            // positions          // normals
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

            -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
             0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
             0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
             0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
            -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
            -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,

            -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
            -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
            -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
            -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
            -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
            -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

             0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
             0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
             0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
             0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
             0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
             0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

            -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
             0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
             0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
             0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
            -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
            -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

            -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
             0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
             0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
            -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
            -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
        };
        float skyboxVertices[] = {
            // positions
            -1.0f,  1.0f, -1.0f,
            -1.0f, -1.0f, -1.0f,
             1.0f, -1.0f, -1.0f,
             1.0f, -1.0f, -1.0f,
             1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,

            -1.0f, -1.0f,  1.0f,
            -1.0f, -1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f, -1.0f,
            -1.0f,  1.0f,  1.0f,
            -1.0f, -1.0f,  1.0f,

             1.0f, -1.0f, -1.0f,
             1.0f, -1.0f,  1.0f,
             1.0f,  1.0f,  1.0f,
             1.0f,  1.0f,  1.0f,
             1.0f,  1.0f, -1.0f,
             1.0f, -1.0f, -1.0f,

            -1.0f, -1.0f,  1.0f,
            -1.0f,  1.0f,  1.0f,
             1.0f,  1.0f,  1.0f,
             1.0f,  1.0f,  1.0f,
             1.0f, -1.0f,  1.0f,
            -1.0f, -1.0f,  1.0f,

            -1.0f,  1.0f, -1.0f,
             1.0f,  1.0f, -1.0f,
             1.0f,  1.0f,  1.0f,
             1.0f,  1.0f,  1.0f,
            -1.0f,  1.0f,  1.0f,
            -1.0f,  1.0f, -1.0f,

            -1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f,  1.0f,
             1.0f, -1.0f, -1.0f,
             1.0f, -1.0f, -1.0f,
            -1.0f, -1.0f,  1.0f,
             1.0f, -1.0f,  1.0f
        };

        glGenVertexArrays(1,&VAO);
        glGenBuffers(1,&VBO);
        glBindVertexArray(VAO);

        glBindBuffer(GL_ARRAY_BUFFER,VBO);
         glBufferData(GL_ARRAY_BUFFER,sizeof (cubeVertices),cubeVertices,GL_STATIC_DRAW);
         // 坐标数据
          glEnableVertexAttribArray(0);
         glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,6 * sizeof(float), (void*)0);

         //法线数据
         glEnableVertexAttribArray(1);
         glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));

         // skybox VAO

         glGenVertexArrays(1, &skyboxVAO);
         glGenBuffers(1, &skyboxVBO);
         glBindVertexArray(skyboxVAO);
         glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
         glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
         glEnableVertexAttribArray(0);
         glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

//          cubeTexture = loadTexture(std::string("./skybox/container.jpg").c_str());
         std::vector<std::string> vCubeFaces = {
             "./skybox/right.jpg",
             "./skybox/left.jpg",
             "./skybox/top.jpg",
             "./skybox/bottom.jpg",
             "./skybox/front.jpg",
             "./skybox/back.jpg"};
     cubemapTexture = loadCubemap(vCubeFaces);

	 shader = new Shader("./skybox/cubemaps_vs.txt", "./skybox/cubemaps_fs.txt");
	 skyboxShader = new Shader("./skybox/skybox_vs.txt", "./skybox/skybox_fs.txt");
	 camera = new Camera(glm::vec3(0.0f, 0.0f, 3.0f));
     shader->use();
     shader->setInt("skybox", 0);

     skyboxShader->use();
     skyboxShader->setInt("skybox", 0);

2.paintGL()

代码如下(示例):

 glClearColor(0.1f,0.1f,0.1f,0.1f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shader->use();

    glm::mat4 model = glm::mat4(1.0f);
    glm::mat4 view =camera->GetViewMatrix();
    glm::mat4 projection  = glm::perspective(glm::radians(camera->Zoom),(float)width()/height(),0.1f,100.0f);
    shader->setMat4("model",model);
    shader->setMat4("view",view);
    shader->setMat4("projection",projection);
    shader->setVec3("cameraPos",camera->Position);

    //cube
    glBindVertexArray(VAO);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP,cubemapTexture);

    glDrawArrays(GL_TRIANGLES,0,36);
    glBindVertexArray(0);

    //draw skybox
    glDepthFunc(GL_LEQUAL);
    skyboxShader->use();
    view  = glm::mat4(glm::mat3(camera->GetViewMatrix()));
    skyboxShader->setMat4("view",view);
    skyboxShader->setMat4("projection",projection);

    glBindVertexArray(skyboxVAO);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);
    glDepthFunc(GL_LESS); // set depth function back to default

3.resizeGL(int w, int h)

代码如下(示例):

 glViewport(0,0,w,h);

4.mouseMoveEvent(QMouseEvent *event)//左右视角移动

代码如下(示例):

 static bool firstMouse = true;

	static float lastX = (float)width() / 2.0;
	static float lastY = (float)height() / 2.0;
    float xpos = event->x();
    float ypos = event->y();
    if (firstMouse)
       {
           lastX = xpos;
           lastY = ypos;
           firstMouse = false;
       }

       float xoffset = xpos - lastX;
       float yoffset = lastY - ypos; // reversed since y-coordinates go from bottom to top

       lastX = xpos;
       lastY = ypos;

       camera->ProcessMouseMovement(xoffset, yoffset);
	   update();
       event->ignore();

5.void wheelEvent(QWheelEvent *event)//缩放

代码如下(示例):

QPoint numDegrees = event->angleDelta() / 20;
    camera->ProcessMouseScroll(numDegrees.ry());
	update();
    event->ignore();

6.完整头文件

代码如下(示例):

class SkyboxForm :public QOpenGLWidget ,public QOpenGLExtraFunctions
{
    Q_OBJECT

public:
    explicit SkyboxForm(QWidget *parent = nullptr);
    ~SkyboxForm();
    void paintGL() override;
    void initializeGL() override;
    void resizeGL(int w, int h) override;
unsigned int loadCubemap(std::vector<std::string> faces);
unsigned int loadTexture(char const * path);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
private:
    Ui::SkyboxForm *ui;
    unsigned int VAO ,VBO;
    unsigned int skyboxVAO, skyboxVBO;
     unsigned int cubemapTexture;
     unsigned int cubeTexture;
     Shader *shader;
     Shader *skyboxShader;
     Camera *camera;

};

总结

Shader 、Camera 实现参照learnopengl ,
只用stb_image.h读取图像的时候在 #include 前 #define STB_IMAGE_IMPLEMENTATION,代码如下:

#define STB_IMAGE_IMPLEMENTATION
#include"stb_image.h"

运行效果:

在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐