Horse3D引擎研发笔记(四):在QtOpenGL下仿three.js,封装EBO绘制四边形

Horse3D引擎研发笔记(一):从使用Qt的OpenGL库绘制三角形开始
Horse3D引擎研发笔记(二):基于QtOpenGL使用仿Three.js的BufferAttribute结构重构三角形绘制
Horse3D引擎研发笔记(三):使用QtOpenGL的Shader编程绘制彩色三角形
Horse3D引擎研发笔记(四):在QtOpenGL下仿three.js,封装EBO绘制四边形

在三维图形开发中,效率是至关重要的。今天,我们将深入探讨如何在QtOpenGL框架下实现高效的图形绘制,特别是通过封装EBO(Element Buffer Object)来绘制四边形。这篇文章将详细介绍EBO的优势、Horse3D引擎中的封装实现,以及如何通过EBO高效地绘制四边形。


一、EBO简介

EBO,全称Element Buffer Object,是OpenGL中用于存储索引数据的一种缓冲对象。它允许我们通过索引数组来引用顶点缓冲中的顶点,从而减少重复顶点的存储需求。EBO在现代图形渲染中被广泛使用,尤其是在需要高效绘制大量几何图形的场景中。


二、EBO的优势

  1. 减少顶点重复:通过索引数组,EBO可以显著减少顶点数据的重复存储。例如,一个四边形由两个三角形组成,共6个顶点。如果没有EBO,我们需要存储6个顶点;而使用EBO,我们只需要存储4个顶点,索引数组告诉OpenGL如何引用这些顶点。

  2. 提高渲染效率:EBO减少了GPU需要处理的顶点数量,从而提高了渲染性能。这对于大规模场景的渲染尤为重要。

  3. 降低带宽消耗:EBO的数据通常驻留在GPU内存中,减少了CPU和GPU之间的数据传输,进一步提升了性能。


三、Horse3D引擎中的EBO封装

Horse3D是一款基于Qt和OpenGL开发的三维渲染引擎,旨在提供高效的图形渲染能力。为了更好地支持高效的图形绘制,我们在Horse3D中封装了EBO的功能。

1. EBO的封装类

在Horse3D中,我们定义了一个IndicesAttribute类,用于管理EBO的创建和绑定。

cpp 复制代码
class IndicesAttribute {
private:
    std::vector<unsigned int> m_indices;
    GLuint m_ebo;

public:
    IndicesAttribute(const std::vector<unsigned int>& indices)
        : m_indices(indices) {}

    void createOpenGLState(IScreen* screen) {
        screen->glGenBuffers(1, &m_ebo);
        screen->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
        screen->glBufferData(GL_ELEMENT_ARRAY_BUFFER, 
                            m_indices.size() * sizeof(unsigned int), 
                            m_indices.data(), GL_STATIC_DRAW);
    }
};
  • 构造函数 :接收一个索引数组,并将其存储在m_indices中。
  • createOpenGLState方法 :用于创建EBO并绑定索引数据。该方法通过glGenBuffers生成EBO对象,通过glBindBuffer绑定EBO,并通过glBufferData将索引数据上传到GPU。

2. EBO的使用

在Horse3D中,我们通过以下步骤使用EBO:

  1. 创建顶点数据和索引数据。
  2. 使用BufferAttribute类管理顶点缓冲对象(VBO)。
  3. 使用IndicesAttribute类管理元素缓冲对象(EBO)。
  4. 在渲染循环中绑定VBO和EBO,并调用glDrawElements进行绘制。

四、绘制四边形的实现

接下来,我们将详细讲解如何在Horse3D中通过EBO绘制一个四边形。

1. 顶点数据与索引数据

我们定义了一个四边形的顶点数据和索引数据:

cpp 复制代码
const std::vector<GLfloat> 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    // 右上角
};

const std::vector<unsigned int> indices = {
    0, 1, 3, // 第一个三角形
    1, 2, 3  // 第二个三角形
};
  • 顶点数据:定义了四边形的四个顶点坐标。
  • 索引数据:定义了两个三角形的索引数组,每个三角形由3个顶点索引组成。

2. 初始化与绑定

在初始化阶段,我们创建了顶点缓冲对象(VBO)和元素缓冲对象(EBO),并将它们绑定到顶点数组对象(VAO)中。

cpp 复制代码
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

bufferAttribute->createOpenGLState(this); // 创建并绑定VBO
indicesAttribute->createOpenGLState(this); // 创建并绑定EBO

3. 着色器程序

我们定义了一个简单的着色器程序,用于为四边形着色。

cpp 复制代码
shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
R"(#version 450 core
 layout (location = 0) in vec3 aPos;
 void main()
 {
     gl_Position = vec4(aPos, 1.0);
 })");

shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
R"(#version 450 core
 out vec4 FragColor;
 void main()
 {
     FragColor = vec4(1.0, 0.5, 0.0, 1.0); // 橙色
 })");
shaderProgram->link();
  • 顶点着色器:将顶点位置传递给片段着色器。
  • 片段着色器:为每个像素设置颜色(橙色)。

4. 绘制过程

paintGL方法中,我们执行以下步骤:

  1. 清除颜色缓冲。
  2. 绑定着色器程序。
  3. 绑定顶点数组对象(VAO)。
  4. 调用glDrawElements进行绘制。
cpp 复制代码
glClear(GL_COLOR_BUFFER_BIT);
shaderProgram->bind();
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
shaderProgram->release();

glDrawElements :使用EBO中的索引数据绘制三角形。GL_TRIANGLES表示绘制模式为三角形,6表示索引数量,GL_UNSIGNED_INT表示索引类型,0表示索引数据的起始位置。


五、Horse3D引擎项目介绍

Horse3D是一款基于Qt和OpenGL开发的三维渲染引擎,旨在提供高效的图形渲染能力。与three.js和Unity类似,Horse3D通过封装底层OpenGL功能,为开发者提供了一组简洁易用的API。

项目目标

  1. 高效渲染:通过优化OpenGL调用和数据管理,提供高性能的图形渲染能力。
  2. API友好:借鉴three.js和Unity的API设计,提供简洁直观的接口。
  3. 跨平台支持:基于Qt的跨平台能力,支持Windows、Linux和macOS等平台。

项目地址

感兴趣的朋友可以访问我们的Gitee仓库,查看更多细节和源代码:

https://gitee.com/shendeyidi/horse_x


六、总结

通过封装EBO,我们成功地在Horse3D引擎中实现了高效的四边形绘制。这一实现不仅减少了顶点数据的重复存储,还提高了渲染性能。未来,我们将继续优化Horse3D引擎的功能,为开发者提供更强大的三维图形渲染能力。

相关推荐
故事和你9144 分钟前
洛谷-数据结构1-1-线性表1
开发语言·数据结构·c++·算法·leetcode·动态规划·图论
脱氧核糖核酸__1 小时前
LeetCode热题100——53.最大子数组和(题解+答案+要点)
数据结构·c++·算法·leetcode
脱氧核糖核酸__1 小时前
LeetCode 热题100——42.接雨水(题目+题解+答案)
数据结构·c++·算法·leetcode
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:数列分段 Section I
c++·算法·编程·贪心·csp·信奥赛·线性扫描贪心
王老师青少年编程2 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【线性扫描贪心】:分糖果
c++·算法·贪心算法·csp·信奥赛·线性扫描贪心·分糖果
南無忘码至尊2 小时前
Unity学习90天 - 第 6天 - 学习协程 Coroutine并实现每隔 2 秒生成一波敌人
学习·unity·c#·游戏引擎
图扑可视化2 小时前
水墨国风智慧大坝 3D 可视化系统技术实现
3d·数字孪生·智慧水利·水利发电
leaves falling3 小时前
C++模板进阶
开发语言·c++
无敌昊哥战神3 小时前
【保姆级题解】力扣17. 电话号码的字母组合 (回溯算法经典入门) | Python/C/C++多语言详解
c语言·c++·python·算法·leetcode
脱氧核糖核酸__3 小时前
LeetCode热题100——238.除了自身以外数组的乘积(题目+题解+答案)
数据结构·c++·算法·leetcode