|
@@ -0,0 +1,181 @@
|
|
|
|
|
+#include "WidgetGL2.h"
|
|
|
|
|
+#include <gl/gl.h>
|
|
|
|
|
+#include <qopenglext.h>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#include "spdlog/spdlog.h"
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+WidgetGL2::WidgetGL2(QWidget *parent)
|
|
|
|
|
+{
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+WidgetGL2::~WidgetGL2()
|
|
|
|
|
+{
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+void WidgetGL2::initializeGL()
|
|
|
|
|
+{
|
|
|
|
|
+ /* 初始化OpenGL函数 */
|
|
|
|
|
+ initializeOpenGLFunctions();
|
|
|
|
|
+
|
|
|
|
|
+ /* 创建VAO */
|
|
|
|
|
+ glGenVertexArrays(1, &m_VAO);
|
|
|
|
|
+ /* 绑定VAO,后面的顶点属性设置和缓冲区绑定都会存储在这个VAO中 */
|
|
|
|
|
+ glBindVertexArray(m_VAO);
|
|
|
|
|
+
|
|
|
|
|
+ /* ------------------------------ 设置VBO ------------------------------ */
|
|
|
|
|
+ /* 顶点输入 */
|
|
|
|
|
+ float vertices[] = {
|
|
|
|
|
+ -0.8f, -0.5f, 0.0f,
|
|
|
|
|
+ -0.2f, -0.5f, 0.0f,
|
|
|
|
|
+ -0.5f, 0.5f, 0.0f,
|
|
|
|
|
+ -0.2f, -0.5f, 0.0f,
|
|
|
|
|
+ 0.8f, -0.5f, 0.0f,
|
|
|
|
|
+ 0.3f, 0.5f, 0.0f
|
|
|
|
|
+ };
|
|
|
|
|
+ // float vertices[] = {
|
|
|
|
|
+ // 0.5f, 0.5f, 0.0f, // 右上角
|
|
|
|
|
+ // 0.5f, -0.5f, 0.0f, // 右下角
|
|
|
|
|
+ // -0.5f, -0.5f, 0.0f, // 左下角
|
|
|
|
|
+ // -0.5f, 0.5f, 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, 3*sizeof(float), 0);
|
|
|
|
|
+ /* 启用顶点属性,这里是启用位置为0的顶点属性 */
|
|
|
|
|
+ glEnableVertexAttribArray(0);
|
|
|
|
|
+
|
|
|
|
|
+ /* 解绑VBO */
|
|
|
|
|
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
+ /* 解绑VAO */
|
|
|
|
|
+ glBindVertexArray(0);
|
|
|
|
|
+
|
|
|
|
|
+ /* ------------------------------ 顶点着色器 ------------------------------ */
|
|
|
|
|
+ const char* vertexShaderSource = R"(
|
|
|
|
|
+ #version 330 core
|
|
|
|
|
+ layout (location = 0) in vec3 aPos;
|
|
|
|
|
+
|
|
|
|
|
+ void main()
|
|
|
|
|
+ {
|
|
|
|
|
+ gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
|
|
|
|
|
+ }
|
|
|
|
|
+ )";
|
|
|
|
|
+ /* 创建顶点着色器对象 */
|
|
|
|
|
+ GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
|
|
|
+ /* 加载顶点着色器源码 */
|
|
|
|
|
+ glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
|
|
|
|
|
+ /* 编译着色器 */
|
|
|
|
|
+ glCompileShader(vertexShader);
|
|
|
|
|
+ printOpenGLCompileError(vertexShader);
|
|
|
|
|
+
|
|
|
|
|
+ /* ------------------------------ 片段着色器 ------------------------------ */
|
|
|
|
|
+ const char* fragmentShaderSource = R"(
|
|
|
|
|
+ #version 330 core
|
|
|
|
|
+ out vec4 FragColor;
|
|
|
|
|
+
|
|
|
|
|
+ void main()
|
|
|
|
|
+ {
|
|
|
|
|
+ FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
|
|
|
|
|
+ }
|
|
|
|
|
+ )";
|
|
|
|
|
+ /* 创建片段着色器对象 */
|
|
|
|
|
+ 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 WidgetGL2::resizeGL(int w, int h)
|
|
|
|
|
+{
|
|
|
|
|
+ /* 设置视口 */
|
|
|
|
|
+ glViewport(0, 0, w, h);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void WidgetGL2::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 WidgetGL2::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 WidgetGL2::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);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|