ShaderRect.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "ShaderRect.h"
  2. #include <QOpenGLWidget>
  3. #include <QOpenGLFunctions_3_3_Core>
  4. #include <GL/gl.h>
  5. #include "spdlog/spdlog.h"
  6. ShaderRect::ShaderRect()
  7. {
  8. }
  9. ShaderRect::~ShaderRect()
  10. {
  11. QOpenGLFunctions_3_3_Core *gl = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
  12. if (m_VAO != 0) {
  13. if (gl) {
  14. gl->glDeleteVertexArrays(1, &m_VAO);
  15. gl->glDeleteBuffers(1, &m_VBO);
  16. gl->glDeleteBuffers(1, &m_EBO);
  17. }
  18. }
  19. }
  20. /* 初始化形状 */
  21. GLuint ShaderRect::initShape()
  22. {
  23. const int vertexCount = 4; // 顶点数量
  24. const int vertexSize = 8; // 顶点大小
  25. /* 矩形位置,铺满屏幕 */
  26. float vertices [vertexCount * vertexSize] {
  27. /* ----- 位置 -----|-------- 颜色 ----------|----- 纹理坐标 ------ */
  28. -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, // 左下
  29. 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, // 右下
  30. 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // 右上
  31. -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f // 右上
  32. };
  33. const int indexCount = 6; // 索引数量
  34. /* 顶点顺序 */
  35. uint32_t indices [indexCount] {
  36. 0, 1, 2, // 第一个三角形
  37. 2, 3, 0 // 第二个三角形
  38. };
  39. QOpenGLFunctions_3_3_Core *gl = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
  40. if (!gl) {
  41. SPDLOG_ERROR("Failed to get OpenGL functions");
  42. return 0;
  43. }
  44. /* -------------------------------------------------------------------------------------
  45. * 顶点数组对象
  46. * ------------------------------------------------------------------------------------ */
  47. gl->glGenVertexArrays(1, &m_VAO); // 生成一个VAO,返回的ID存储在VAO1中
  48. gl->glBindVertexArray(m_VAO); // 绑定VAO
  49. /* -------------------------------------------------------------------------------------
  50. * 创建顶点数组缓冲区
  51. * ------------------------------------------------------------------------------------ */
  52. gl->glGenBuffers(1, &m_VBO);
  53. gl->glBindBuffer(GL_ARRAY_BUFFER, m_VBO); // 绑定VBO
  54. gl->glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize * sizeof(float), vertices, GL_STATIC_DRAW);
  55. /* -------------------------------------------------------------------------------------
  56. * 创建EBO
  57. * ------------------------------------------------------------------------------------ */
  58. gl->glGenBuffers(1, &m_EBO);
  59. gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
  60. gl->glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(uint32_t), indices, GL_STATIC_DRAW); // 绑定EBO
  61. /* -------------------------------------------------------------------------------------
  62. * 链接顶点属性
  63. * ------------------------------------------------------------------------------------ */
  64. // 设置顶点属性指针,告诉OpenGL如何解析顶点数据
  65. gl->glVertexAttribPointer(
  66. 0, /* 顶点属性位置,0表示第一个属性 */
  67. 3, /* 每个顶点属性的大小,这里是3,表示x、y、z坐标 */
  68. GL_FLOAT, GL_FALSE, /* 数据类型和是否标准化 */
  69. vertexSize * sizeof(float), /* 步长,表示每个顶点属性之间的间隔 */
  70. (void*)0 /* 偏移量,表示该属性(顶点坐标)从第0个字节开始 */
  71. );
  72. /* 启用顶点属性 */
  73. gl->glEnableVertexAttribArray(0);
  74. // 设置颜色位置,最后一个参数表示从第3个字节开始,倒数第二个参数是两个数据之间起始位置间隔8个字节
  75. gl->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (void*)(3*sizeof(float)));
  76. gl->glEnableVertexAttribArray(1);
  77. /* 设置纹理位置 */
  78. gl->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (void*)(6*sizeof(float))); // 纹理坐标位置
  79. gl->glEnableVertexAttribArray(2); // 启用纹理坐标属性
  80. return m_VAO;
  81. }
  82. /* 绘制图形 */
  83. void ShaderRect::drawShape()
  84. {
  85. QOpenGLFunctions_3_3_Core *gl = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
  86. /* 需要在使用时手动绑定VAO,绘制图形 */
  87. gl->glBindVertexArray(m_VAO); // 绑定VAO
  88. gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // 绘制四边形
  89. gl->glBindVertexArray(0); // 解绑VAO
  90. }
  91. /* 初始化纹理对象 */
  92. bool ShaderRect::initTextures()
  93. {
  94. /* 创建一个纹理对象 */
  95. auto unit = createTexture(m_textureRGBAName);
  96. if(unit < 0)
  97. {
  98. SPDLOG_ERROR("RGBA着色器创建纹理失败!");
  99. return false;
  100. }
  101. return true;
  102. }
  103. /* 刷新一帧 */
  104. bool ShaderRect::refreshFrameRGBA(const QImage& image, int textureUnit)
  105. {
  106. if(image.isNull()) {
  107. SPDLOG_WARN("Image is null");
  108. return false;
  109. }
  110. QOpenGLTexture* texture = m_mapTexture.find(textureUnit)->second;
  111. if(texture == nullptr)
  112. {
  113. SPDLOG_ERROR("错误的纹理编号:{}", textureUnit);
  114. return false;
  115. }
  116. if(m_lastSize != image.size())
  117. {
  118. texture->destroy(); // 释放OpenGL资源
  119. texture->create(); // 重新创建OpenGL资源
  120. texture->setSize(image.width(), image.height(), 1); // 设置纹理大小
  121. texture->setFormat(QOpenGLTexture::RGBA8_UNorm); // 设置纹理格式
  122. texture->allocateStorage(); // 分配纹理存储空间
  123. }
  124. m_lastSize = image.size();
  125. texture->setData(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, image.bits()); // 设置纹理数据
  126. texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear); // 纹理缩小过滤方式
  127. texture->setMagnificationFilter(QOpenGLTexture::Linear); // 纹理放大过滤方式
  128. texture->generateMipMaps(); // 生成多级渐远纹理
  129. printGLerror("ShaderRect::refreshFrame");
  130. return true;
  131. }