OpenGL 索引缓存对象EBO和线宽模式

索引缓存器

当绘制一些联系的图形的时候,通常有一些点是连续的,可以被重复使用的点。比如重合的点,我只要在内存中定义一次,然后在显卡缓存中的可以重复使用,只要告诉数据的位置即可。这里就用到了索引缓存器(EBO)。

这里需要注意两点:首先需要配置好VBO,然后才能使用EBO
代码如下:

#pragma once

#include <QOpenGLWindow>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
class QOpenGLFunctions_3_3_Core;
//索引缓存对象的使用

class EBOWnd : public QOpenGLWindow{
	Q_OBJECT

public:
	EBOWnd();
	~EBOWnd();

	void initializeGL()override;
	void resizeGL(int w, int h)override;
	void paintGL()override;

private:
	QOpenGLFunctions_3_3_Core* _openGLCore;
	GLuint _EBO;
	GLuint _VBO;
	GLuint _VAO;
	QOpenGLShaderProgram _shaderProgram;//着色器程序,所里系统所有的着色器
};

#include "EBOWnd.h"
#include <QOpenGLFunctions_3_3_Core>

EBOWnd::EBOWnd(){
}

EBOWnd::~EBOWnd(){
}

void EBOWnd::initializeGL() {
	_openGLCore = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();

	/*
	** 首先把所有图形的点按照一定的顺序列出来,然后在列一个索引表,指明哪些数据是一组
	*/
	GLfloat ver[] = {
		0.5f,  0.5f, 0.0f, //第一象限
		0.5f, -0.5f, 0.0f, //第四象限
	   -0.5f, -0.5f, 0.0f, //第三象限
	   -0.5f,  0.5f, 0.0f, //第二象限
	};

	GLuint idexVer[] = {
		0, 1, 2, //数组中的第0/1/2三个点组成第一个三角形
		1, 2, 3  //第1/2/3组成第二个三角形
	};

	//创建VAO,用来记录各种数据属性
	_openGLCore->glGenVertexArrays(1, &_VAO);
	//绑定VAO
	_openGLCore->glBindVertexArray(_VAO);


	//创建EBO VBO
	_openGLCore->glGenBuffers(1, &_EBO);
	_openGLCore->glGenBuffers(1, &_VBO);
	//绑定EBO VBO
	_openGLCore->glBindBuffer(GL_ARRAY_BUFFER, _VBO);
	_openGLCore->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _EBO);
	//传送数据
	_openGLCore->glBufferData(GL_ARRAY_BUFFER, sizeof(ver), ver, GL_STATIC_DRAW);
	_openGLCore->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(idexVer), idexVer, GL_STATIC_DRAW);

	/*
	** 对VBO进行属性配置
	*/
	_openGLCore->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);

	//启用着色器
	_openGLCore->glEnableVertexAttribArray(0);

	//解绑VAO
	_openGLCore->glBindVertexArray(0);

	//解绑VBO
	_openGLCore->glBindBuffer(GL_ARRAY_BUFFER, 0);
	//解绑EBO
	_openGLCore->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	/*
	** 着色器
	** 着色器属于动态编译
	*/
	QOpenGLShader vertexShager(QOpenGLShader::Vertex);//顶点着色器
	vertexShager.compileSourceFile("E:/Projects/QtGuiTest/OPenGLApp/shader/triangle.vert");
	QOpenGLShader fragmentShager(QOpenGLShader::Fragment);//片段着色器
	fragmentShager.compileSourceFile("E:/Projects/QtGuiTest/OPenGLApp/shader/triangle.frag");
	_shaderProgram.addShader(&vertexShager);
	_shaderProgram.addShader(&fragmentShager);

	_shaderProgram.link();
}

void EBOWnd::resizeGL(int w, int h) {

}

void EBOWnd::paintGL() {
	//设置清除颜色,使用当前颜色,清除背景
	_openGLCore->glClearColor(0.6f, 0.6f, 0.6f, 1.0f);
	_openGLCore->glClear(GL_COLOR_BUFFER_BIT);

	//把着色器送入显卡缓存
	_shaderProgram.bind();

	_openGLCore->glBindVertexArray(_VAO);//会将它记忆的那些状态,相当于那几个函数执行一遍

	/*
	**  第一个参数:绘制类型 三角形
	**  第二个参数:绘制点数,两三角形就是6个点
	**  第三个参数:数据类型,索引的值的类型 idexVer 为无符号整形
	**  第四个参数:设置为0
	*/
	_openGLCore->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

	update();
}

运行结果:
在这里插入图片描述

线框模式

我们重新调整一下点索引数组的顺序

GLuint idexVer[] = {
		0, 1, 2, //数组中的第0/1/2三个点组成第一个三角形,顺时针
		2, 0, 3  //第1/2/3组成第二个三角形,逆时针
	};

解绑VAO之前调用这个函数,可以看到
其中第一个参数有多个选项:
#define GL_FRONT 0x0404
#define GL_BACK 0x0405
#define GL_FRONT_AND_BACK 0x0408
分别是前、后、前和后。

那什么才是一个多边形的前和后呢?

 在OpenGL中一个面的法向量,与绘制这个面时的点的顺序有关;
 以屏幕为例,如果一个多边形的点是顺时针绘制的,则法向量的从屏幕向里的,如果是逆时针在法向量的方向是向外的。
 符合右手定则。
 法向量向外的称为前面,法向量向内的称为后面
_openGLCore->glPolygonMode(GL_BACK, GL_LINE);

可以看一下效果:
在这里插入图片描述

aaa

您好!对于使用OpenGL 3.3和EBO(Element Buffer Object)进行分组绘制的问题,我可以为您提供一些建议。 首先,让我们来了解一下EBO的概念。EBO是一种用于索引绘制的OpenGL对象,它允许我们将顶数据和索引数据分开存储。使用EBO可以减少内存占用,并提高渲染效率。 下面是一个使用EBO进行分组绘制的基本步骤: 1. 创建并绑定一个顶缓冲对象(Vertex Buffer Object,VBO),并将顶数据发送到VBO中。 ```cpp GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); ``` 2. 创建并绑定一个索引缓冲对象(Element Buffer Object,EBO),并将索引数据发送到EBO中。 ```cpp GLuint ebo; glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); ``` 3. 在顶着色器中定义顶属性,并启用相应的顶属性。 ```cpp layout (location = 0) in vec3 position; void main() { // ... } ``` 4. 在渲染循环中,绑定VBO和EBO,并告诉OpenGL如何解析顶数据。 ```cpp glBindBuffer(GL_ARRAY_BUFFER, vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*)0); glEnableVertexAttribArray(0); ``` 5. 使用glDrawElements函数进行绘制,指定绘制的图元类型和索引数量。 ```cpp glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0); ``` 这些是使用EBO进行分组绘制的基本步骤。您可以根据具体的需求进行调整和优化。希望对您有所帮助!如果您还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值