#include "WidgetGL3.h" #include #include #include #include "spdlog/spdlog.h" WidgetGL3::WidgetGL3(QWidget *parent) { } WidgetGL3::~WidgetGL3() { } void WidgetGL3::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, // 右上角 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 右下角 -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // 左下角 -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.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, 6*sizeof(float), 0); /* 启用顶点属性,这里是启用位置为0的顶点属性 */ glEnableVertexAttribArray(0); /* 设置颜色属性 */ glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float))); glEnableVertexAttribArray(1); /* 解绑VBO */ glBindBuffer(GL_ARRAY_BUFFER, 0); /* 解绑VAO */ glBindVertexArray(0); /* ------------------------------ 顶点着色器 ------------------------------ */ const char* vertexShaderSource = R"( #version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; out vec4 vertexColor; void main() { gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); vertexColor = vec4(aColor, 1.0); } )"; /* 创建顶点着色器对象 */ GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); /* 加载顶点着色器源码 */ glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); /* 编译着色器 */ glCompileShader(vertexShader); printOpenGLCompileError(vertexShader); /* ------------------------------ 片段着色器 ------------------------------ */ const char* fragmentShaderSource = R"( #version 330 core in vec4 vertexColor; out vec4 FragColor1; void main() { FragColor1 = vertexColor; } )"; /* 创建片段着色器对象 */ GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); /* 加载片段着色器源码 */ glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); /* 编译着色器 */ glCompileShader(fragmentShader); printOpenGLCompileError(fragmentShader); /* ------------------------------ 着色器程序对象 ------------------------------ */ m_shaderProgam = glCreateProgram(); /* 将顶点着色器和片段着色器附加到着色器程序对象上 */ glAttachShader(m_shaderProgam, vertexShader); glAttachShader(m_shaderProgam, fragmentShader); /* 链接着色器程序 */ glLinkProgram(m_shaderProgam); /* 销毁顶点着色器和片段着色器 */ glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } void WidgetGL3::resizeGL(int w, int h) { /* 设置视口 */ glViewport(0, 0, w, h); } void WidgetGL3::paintGL() { /* 清屏 */ glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); /* 绘制四边形 */ glUseProgram(m_shaderProgam); glBindVertexArray(m_VAO); // glDrawArrays(GL_TRIANGLES, 0, 6); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); /* 解绑VAO */ glBindVertexArray(0); } /* 打印编译错误 */ void WidgetGL3::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 WidgetGL3::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); } }