WidgetGL3.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "WidgetGL3.h"
  2. #include <gl/gl.h>
  3. #include <qopenglext.h>
  4. #include <QTime>
  5. #include "spdlog/spdlog.h"
  6. WidgetGL3::WidgetGL3(QWidget *parent)
  7. {
  8. }
  9. WidgetGL3::~WidgetGL3()
  10. {
  11. }
  12. void WidgetGL3::initializeGL()
  13. {
  14. /* 初始化OpenGL函数 */
  15. initializeOpenGLFunctions();
  16. /* 创建VAO */
  17. glGenVertexArrays(1, &m_VAO);
  18. /* 绑定VAO,后面的顶点属性设置和缓冲区绑定都会存储在这个VAO中 */
  19. glBindVertexArray(m_VAO);
  20. /* ------------------------------ 设置VBO ------------------------------ */
  21. float vertices[] = {
  22. 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右上角
  23. 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 右下角
  24. -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // 左下角
  25. -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f // 左上角
  26. };
  27. unsigned int indices[] = {
  28. // 注意索引从0开始!
  29. // 此例的索引(0,1,2,3)就是顶点数组vertices的下标,
  30. // 这样可以由下标代表顶点组合成矩形
  31. 0, 1, 3, // 第一个三角形
  32. 1, 2, 3 // 第二个三角形
  33. };
  34. GLuint VBO = 0;
  35. /* 顶点缓冲对象 */
  36. glGenBuffers(1, &VBO);
  37. /* 将VBO绑定到缓冲对象上(其实是用于激活这个VBO对象,可以对这个对象进行操作了)
  38. 说明:OpenGL的对象操作都要依赖OpenGL提供的函数,有很多对象类型,这里将VBO绑定在 GL_ARRAY_BUFFER 上,就像放在了对应的操作台上,之后就可以对这个对象进行
  39. 操作,后续的一切对 GL_ARRAY_BUFFER 的操作就是对VBO的操作 */
  40. glBindBuffer(GL_ARRAY_BUFFER, VBO);
  41. /* 将数据拷贝到VBO中 */
  42. glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  43. /* 创建EBO */
  44. GLuint EBO = 0;
  45. glGenBuffers(1, &EBO);
  46. /* 绑定EBO */
  47. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
  48. /* 将索引数据拷贝到EBO中 */
  49. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  50. /* 设置顶点链接属性 */
  51. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), 0);
  52. /* 启用顶点属性,这里是启用位置为0的顶点属性 */
  53. glEnableVertexAttribArray(0);
  54. /* 设置颜色属性 */
  55. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float)));
  56. glEnableVertexAttribArray(1);
  57. /* 解绑VBO */
  58. glBindBuffer(GL_ARRAY_BUFFER, 0);
  59. /* 解绑VAO */
  60. glBindVertexArray(0);
  61. /* ------------------------------ 顶点着色器 ------------------------------ */
  62. const char* vertexShaderSource = R"(
  63. #version 330 core
  64. layout (location = 0) in vec3 aPos;
  65. layout (location = 1) in vec3 aColor;
  66. out vec4 vertexColor;
  67. void main()
  68. {
  69. gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
  70. vertexColor = vec4(aColor, 1.0);
  71. }
  72. )";
  73. /* 创建顶点着色器对象 */
  74. GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
  75. /* 加载顶点着色器源码 */
  76. glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
  77. /* 编译着色器 */
  78. glCompileShader(vertexShader);
  79. printOpenGLCompileError(vertexShader);
  80. /* ------------------------------ 片段着色器 ------------------------------ */
  81. const char* fragmentShaderSource = R"(
  82. #version 330 core
  83. in vec4 vertexColor;
  84. out vec4 FragColor1;
  85. void main()
  86. {
  87. FragColor1 = vertexColor;
  88. }
  89. )";
  90. /* 创建片段着色器对象 */
  91. GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
  92. /* 加载片段着色器源码 */
  93. glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
  94. /* 编译着色器 */
  95. glCompileShader(fragmentShader);
  96. printOpenGLCompileError(fragmentShader);
  97. /* ------------------------------ 着色器程序对象 ------------------------------ */
  98. m_shaderProgam = glCreateProgram();
  99. /* 将顶点着色器和片段着色器附加到着色器程序对象上 */
  100. glAttachShader(m_shaderProgam, vertexShader);
  101. glAttachShader(m_shaderProgam, fragmentShader);
  102. /* 链接着色器程序 */
  103. glLinkProgram(m_shaderProgam);
  104. /* 销毁顶点着色器和片段着色器 */
  105. glDeleteShader(vertexShader);
  106. glDeleteShader(fragmentShader);
  107. }
  108. void WidgetGL3::resizeGL(int w, int h)
  109. {
  110. /* 设置视口 */
  111. glViewport(0, 0, w, h);
  112. }
  113. void WidgetGL3::paintGL()
  114. {
  115. /* 清屏 */
  116. glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
  117. glClear(GL_COLOR_BUFFER_BIT);
  118. /* 绘制四边形 */
  119. glUseProgram(m_shaderProgam);
  120. glBindVertexArray(m_VAO);
  121. // glDrawArrays(GL_TRIANGLES, 0, 6);
  122. glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
  123. /* 解绑VAO */
  124. glBindVertexArray(0);
  125. }
  126. /* 打印编译错误 */
  127. void WidgetGL3::printOpenGLCompileError(GLuint errorCode)
  128. {
  129. int sucess;
  130. char infoLog[512];
  131. glGetShaderiv(errorCode, GL_COMPILE_STATUS, &sucess);
  132. if (!sucess)
  133. {
  134. glGetShaderInfoLog(errorCode, 512, nullptr, infoLog);
  135. SPDLOG_ERROR("OpenGL编译错误: {}", infoLog);
  136. }
  137. }
  138. /* 打印着色器链接错误 */
  139. void WidgetGL3::printOpenGLLinkError(GLuint errorCode)
  140. {
  141. int sucess;
  142. char infoLog[512];
  143. glGetProgramiv(errorCode, GL_LINK_STATUS, &sucess);
  144. if (!sucess)
  145. {
  146. glGetProgramInfoLog(errorCode, 512, nullptr, infoLog);
  147. SPDLOG_ERROR("OpenGL链接错误: {}", infoLog);
  148. }
  149. }