#include "WidgetGL4.h" #include #include #include #include #include #include #include "spdlog/spdlog.h" WidgetGL4::WidgetGL4(QWidget *parent) { } WidgetGL4::~WidgetGL4() { } void WidgetGL4::initializeGL() { /* 初始化OpenGL函数 */ initializeOpenGLFunctions(); /* 创建VAO */ glGenVertexArrays(1, &m_VAO); /* 绑定VAO,后面的顶点属性设置和缓冲区绑定都会存储在这个VAO中 */ glBindVertexArray(m_VAO); /* ------------------------------ 设置VBO ------------------------------ */ float vertices[] = { /* -----位置----- ----颜色----- -----纹理坐标----- */ 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上角 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // 右下角 -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下角 -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // 左上角 }; unsigned int indices[] = { // 注意索引从0开始! // 此例的索引(0,1,2,3)就是顶点数组vertices的下标, // 这样可以由下标代表顶点组合成矩形 0, 1, 3, // 第一个三角形 1, 2, 3 // 第二个三角形 }; GLuint VBO = 0; /* 顶点缓冲对象 */ glGenBuffers(1, &VBO); /* 将VBO绑定到缓冲对象上(其实是用于激活这个VBO对象,可以对这个对象进行操作了) 说明:OpenGL的对象操作都要依赖OpenGL提供的函数,有很多对象类型,这里将VBO绑定在 GL_ARRAY_BUFFER 上,就像放在了对应的操作台上,之后就可以对这个对象进行 操作,后续的一切对 GL_ARRAY_BUFFER 的操作就是对VBO的操作 */ glBindBuffer(GL_ARRAY_BUFFER, VBO); /* 将数据拷贝到VBO中 */ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); /* 创建EBO */ GLuint EBO = 0; glGenBuffers(1, &EBO); /* 绑定EBO */ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); /* 将索引数据拷贝到EBO中 */ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); /* 设置顶点链接属性 */ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), 0); /* 启用顶点属性,这里是启用位置为0的顶点属性 */ glEnableVertexAttribArray(0); /* 设置颜色属性 */ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void*)(3*sizeof(float))); glEnableVertexAttribArray(1); /* 设置纹理坐标属性 */ glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void*)(6*sizeof(float))); glEnableVertexAttribArray(2); /* 解绑VBO */ glBindBuffer(GL_ARRAY_BUFFER, 0); /* 解绑VAO */ glBindVertexArray(0); /* 创建着色器对象 */ m_shader = new Shader(":/GLLearning/ShaderSource/vertexShader1.glsl", ":/GLLearning/ShaderSource/fragmentShader1.glsl"); m_shaderProgam = m_shader->getProgramID(); /* 加载纹理图片 */ QImage image; bool ret = image.load(":/image/1.jpg"); if (!ret) { SPDLOG_ERROR("加载纹理图片失败"); return; } /* 创建纹理 */ glGenTextures(1, &m_texture1); glBindTexture(GL_TEXTURE_2D, m_texture1); /* 设置纹理参数 */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* 将纹理图片数据传递给OpenGL */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits()); glGenerateMipmap(GL_TEXTURE_2D); } void WidgetGL4::resizeGL(int w, int h) { /* 设置视口 */ glViewport(0, 0, w, h); } void WidgetGL4::paintGL() { /* 清屏 */ glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); /* 绘制四边形 */ m_shader->use(); glBindVertexArray(m_VAO); glBindTexture(GL_TEXTURE_2D, m_texture1); // glDrawArrays(GL_TRIANGLES, 0, 6); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); /* 解绑VAO */ glBindVertexArray(0); } /* 打印编译错误 */ void WidgetGL4::printOpenGLCompileError(GLuint errorCode) { int sucess; char infoLog[512]; glGetShaderiv(errorCode, GL_COMPILE_STATUS, &sucess); if (!sucess) { glGetShaderInfoLog(errorCode, 512, nullptr, infoLog); SPDLOG_ERROR("OpenGL编译错误: {}", infoLog); } } /* 打印着色器链接错误 */ void WidgetGL4::printOpenGLLinkError(GLuint errorCode) { int sucess; char infoLog[512]; glGetProgramiv(errorCode, GL_LINK_STATUS, &sucess); if (!sucess) { glGetProgramInfoLog(errorCode, 512, nullptr, infoLog); SPDLOG_ERROR("OpenGL链接错误: {}", infoLog); } }