LearnGL - 学习笔记目录
本人才疏学浅,如有什么错误,望不吝指出。
上一篇:LearnGL - 03 - DrawQuad - VBO/EBO,学会了如何使用 EBO/IBO 画一个四边形。
这一篇:我将使用C++写个类似 OpenGL 在使用 VAO 期间的功能:
VAO 结构
VAO的结果差不多就如下图:
GL LIKE 测试项目
我模仿 OpenGL 一部分的 API 编写了测试项目:
gl_like.h
// gl_like.h
// jave.lin - 测试模仿 opengl 的规范,没有参考 opengl specification 规范,只是自己的理解
// 不做过多的封装,只为简单的理解结束结构,大致的功能
//(什么 private fields, public getter/setter都不封装),实际项目时是不能这么封装的
#ifndef _GL_LIKE__H_
#define _GL_LIKE__H_
#include<string.h>
#include<stdlib.h>
#include<vector>
// 获取地址类型对象指针
#define GET_POINSTER_BY_VALUE(type, addressValue) ((type)((void*)addressValue))
// 获取指针对象地址值
#define GET_ADDRESS_VALUE(address) ((uint)address);
//
// symbol constants - 符号常量,参考 glad 的定义
//
#define GL_ARRAY_BUFFER 0x8892
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_STATIC_DRAW 0x88E4
#define GL_BYTE 0x1400
#define GL_UNSIGNED_BYTE 0x1401
#define GL_SHORT 0x1402
#define GL_UNSIGNED_SHORT 0x1403
#define GL_INT 0x1404
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
#define GL_POINTS 0x0000
#define GL_LINES 0x0001
#define GL_LINE_LOOP 0x0002
#define GL_LINE_STRIP 0x0003
#define GL_TRIANGLES 0x0004
#define GL_TRIANGLE_STRIP 0x0005
#define GL_TRIANGLE_FAN 0x0006
//
// custom symbol constants - 符号常量,自定义的,暂时还没有看到的参考资料
//
#define GL_MAX_NUM_OF_VAO 4096
#define GL_MAX_NUM_OF_VBO 4096
#define GL_TRUE 1
#define GL_FALSE 0
#define GL_INVALIDATED_CONTEXT 1
#define GL_OUT_BO_MAX_COUNT 2
#define GL_CREATE_FAILURE 3
#define GL_CONTEXT_NOT_NULL 4
#define GL_BINDING_UN_HANDLE_BUFF_TYPE 5
#define GL_SET_BUFF_VALUES_BUFF_NULL 6
//
// declaretion - empty - 空定义
//
//
// typdef - 参考 glad 的 typedef 别名(C++中的话,使用using会更好,因为支持template,但typedef一直到c会更好)
//
typedef unsigned int GLenum;
typedef unsigned char GLboolean;
typedef unsigned int GLbitfield;
typedef void GLvoid;
typedef signed char GLbyte;
typedef unsigned char GLubyte;
typedef signed short GLshort;
typedef unsigned short GLushort;
typedef int GLint;
typedef unsigned int GLuint;
typedef int GLclampx;
typedef int GLsizei;
typedef float GLfloat;
typedef float GLclampf;
typedef double GLdouble;
typedef double GLclampd;
typedef void* GLeglClientBufferEXT;
typedef void* GLeglImageOES;
typedef char GLchar;
typedef char GLcharARB;
typedef signed long int GLsizeiptr;
typedef GLbyte* _buffer_t;
typedef GLubyte* _ubuffer_T;
//
// declaretion - sold
//
class _BuffObject {
public:
_ubuffer_T data = NULL;
GLsizei size = 0;
GLsizei capacity = 0;
~_BuffObject();
};
class BufferObject { // 缓存对象
public:
_BuffObject* buf = NULL;
~BufferObject();
};
class VertexAttributeFormat {
public:
GLuint index = -1; // location 索引
GLint numOfComponent = 0; // 分量的数量
GLenum typeOfComponent = 0; // 分量的类型
GLboolean normalized = 0; // 分量值是否归一化
GLsizei stride = 0; // 顶点属性所在数据数组的每个分段大小
void* pointer = 0; // 在对应分段的字节偏移
GLuint setupToVBO = 0; // 安装到vbo
~VertexAttributeFormat();
};
class VertexArrayObject { // VAO
public:
BufferObject* vbo = NULL; // VBO 指针
BufferObject* ebo = NULL; // EBO 指针
std::vector<VertexAttributeFormat*>* vafs = NULL; // VBO 格式(规范)
std::vector<GLuint>* vafs_enabled = NULL; // 启用的 VBO 格式
VertexArrayObject();
~VertexArrayObject();
};
class Context {
public:
GLuint major = 0;
GLuint minor = 0;
VertexArrayObject* bindingVAO = NULL; // 绑定之后的VAO
VertexArrayObject* defalultVAO = NULL; // 未绑定的VAO
std::vector<VertexArrayObject*>* VAOs = NULL; // 已申请的所有 VAO 对象
std::vector<BufferObject*>* BOs = NULL; // 已申请的所有 BO 对象
Context();
~Context();
inline VertexArrayObject* GetUsingVAO() const; // 获取当前用的VAO
};
//
// function - others
//
void Terminate();
void MakeCurrentContext(GLuint context);
void CheckBuffType(GLenum buffType);
void Error(const GLuint ec, const GLchar* msg);
GLboolean CreateContext(GLuint major, GLuint minor, GLuint* context);
void glGenVertexArrays(GLsizei n, GLuint* arrays);
void glDeleteVertexArrays(GLsizei n, GLuint* arrays);
void glBindVertexArray(GLuint array);
void glGenBuffers(GLsizei n, GLuint* buffers);
void glDeleteBuffers(GLsizei n, GLuint* buffers);
void glBindBuffer(GLenum target, GLuint buffer);
void glBufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer);
void glEnableVertexAttribArray(GLuint index);
void glDisableVertexAttribArray(GLuint index);
void glDrawArrays(GLenum mode, GLint first, GLsizei count);
void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices);
#endif // #ifndef _GL_LIKE__H_
gl_like_gv.h
// gl_like_gv.h
// jave.lin - global variables
#include"gl_like.h"
#ifndef _GL_LIKE_GV__H_
#define _GL_LIKE_GV__H_
Context* currentContext = NULL;
GLint errorCode = 0;
GLchar* errorMsg = NULL;
#endif
gl_like.cpp
// gl_like.cpp
// jave.lin - 定义以及实现
// 实现不一定是按 OpenGL 来的,都只是自己看了一些官方文档了解功能后,而编写的功能
// 所以会出现,只实现了部分的功能,会之不对的功能
#include<iostream>
#include<string.h>
#include<math.h>
#include"gl_like_gv.h"
#include"gl_like.h"
extern Context* currentContext;
extern GLint errorCode;
extern GLchar* errorMsg;
//
// function - definition
//
/* 暂时没用上,这时对 glVertexAttribPointer 是的 normalized 来确定要不要归一化数据额类型的,
需要再传入(复制)到 GPU 前就得处理的归一化
// jave.lin : 这是处理数据类型归一化到单精度的过程
// 有符号数据类型归一化处理
template<typename DataType>
inline GLfloat Normalized_signed(DataType value) {
// jave.lin : 对应 Katex 是: f = \frac{c}{2^b-1}
return (GLfloat)((value) / (std::pow(2, sizeof(DataType) * 8 - 1)));
}
// 无符号数据类型归一化处理
template<typename DataType>
inline GLfloat Normalized_unsigned(DataType value) {
// jave.lin : 对应 Katex 是: f = \frac{2c + 1}{2^b-1}
return (GLfloat)((value * 2 + 1) / (std::pow(2, sizeof(DataType) * 8 - 1)));
}
*/
void PrintVertex(GLuint vertexID, VertexAttributeFormat* format, _ubuffer_T buffer) {
std::cout
<< "VertexID:" << vertexID
<< " Location:" << format->index
<< " NumOfComponent:" << format->numOfComponent
<< " TypeOfComponent:" << format->typeOfComponent
<< " Normalized:" << (format->normalized == GL_TRUE ? "true" : "false")
<< " Strid:" << format->stride
<< " Pointer(Offset):" << ((GLuint)format->pointer)
<< "\n";
if (format->typeOfComponent == GL_FLOAT) {
GLuint offset = (GLuint)format->pointer;
GLfloat* pointer = (GLfloat*)(buffer + offset);
std::cout << (format->numOfComponent == 1 ? "float" : "vec") << format->numOfComponent << "( ";
for (size_t i = 0; i < format->numOfComponent; i++) {
std::cout << *(pointer + i) << (i == (format->numOfComponent - 1) ? " " : ", ");
}
std::cout << ")";
}
else {
GLchar str[512];
sprintf_s(str, "PrintVertex Error, type of component unhandle : %d", format->typeOfComponent);
throw str;
}
std::cout << "\n";
} // PrintVertex
//
// api function - definition
//
inline VertexArrayObject* Context::GetUsingVAO() const {
// 如果没有绑定 VAO,就使用默认的 VAO
return this->bindingVAO ? this->bindingVAO : this->defalultVAO;
} // Context::GetUsingVAO
//
// construct function - definition
//
VertexArrayObject::VertexArrayObject() {
this->vafs = new std::vector<VertexAttributeFormat*>;
this->vafs_enabled = new std::vector<GLuint>();
} // VertexArrayObject
Context::Context() {
this->defalultVAO = new VertexArrayObject;
this->VAOs = new std::vector<VertexArrayObject*>;
this->BOs = new std::vector<BufferObject*>;
} // Context
//
// destruct function - definition
//
_BuffObject::~_BuffObject() {
if (this->data != NULL) free(this->data);
this->data = NULL;
} // ~_BuffObject
BufferObject::~BufferObject() {
if (this->buf != NULL) delete this->buf;
this->buf = NULL;
} // ~BufferObject
VertexArrayObject::~VertexArrayObject() {
this->vbo = NULL;
this->ebo = NULL;
if (this->vafs != NULL) {
std::vector<VertexAttributeFormat*>::iterator begin = this->vafs->begin();
std::vector<VertexAttributeFormat*>::iterator end = this->vafs->end();
for (; begin != end; begin++) {
delete* begin;
}
this->vafs->clear();
this->vafs = NULL;
}
if (this->vafs_enabled != NULL) {
this->vafs_enabled->clear();
this->vafs_enabled = NULL;
}
} // VertexArrayObject
VertexAttributeFormat::~VertexAttributeFormat() {
this->pointer = NULL;
} // ~VertexAttributeFormat
Context::~Context() {
if (this->VAOs != NULL) {
std::vector<VertexArrayObject*>::iterator begin_vao = this->VAOs->begin();
std::vector<VertexArrayObject*>::iterator end_va0 = this->VAOs->end();
for (; begin_vao != end_va0; begin_vao++) {
delete* begin_vao;
}
this->VAOs->clear();
this->VAOs = NULL;
}
if (this->BOs != NULL) {
std::vector<BufferObject*>::iterator begin_vbo = this->BOs->begin();
std::vector<BufferObject*>::iterator end_vb0 = this->BOs->end();
for (; begin_vbo != end_vb0; begin_vbo++) {
delete* begin_vbo;
}
this->BOs->clear();
this->BOs = NULL;
}
if (this->defalultVAO != NULL) {
delete this->defalultVAO;
this->defalultVAO = NULL;
}
this->bindingVAO = NULL;
} // ~Context
void Terminate() {
if (currentContext != NULL) {
delete currentContext;
currentContext = NULL;
}
} // Terminater
void MakeCurrentContext(GLuint context) {
currentContext = (Context*)((void*)context);
} // MakeCurrentContext
void CheckBuffType(GLenum buffType) {
switch (buffType)
{
case GL_ARRAY_BUFFER: // VBO
break;
case GL_ELEMENT_ARRAY_BUFFER: // EBO
break;
default:
GLchar str[512];
sprintf_s(str, "binding unhandle buffer type : %d", buffType);
Error(GL_BINDING_UN_HANDLE_BUFF_TYPE, (const GLchar*)str);
break;
} // end switch
} // end CheckBuffType
void Error(const GLuint ec, const GLchar* msg) {
errorCode = ec;
if (errorMsg == NULL) {
errorMsg = (GLchar*)malloc(512);
}
strcpy_s(errorMsg, 512, msg);
throw msg;
} // end Error
GLboolean CreateContext(GLuint major, GLuint minor, GLuint* context) {
if (currentContext != NULL) {
Error(GL_CONTEXT_NOT_NULL, (const GLchar*)"context not null");
return GL_FALSE;
}
Context* p = new Context();
*context = (GLuint) (p);
if (p == NULL) {
Error(GL_CREATE_FAILURE, (const GLchar*)"create context failure");
return GL_FALSE;
}
p->major = major;
p->minor = minor;
return GL_TRUE;
} // end CreateContext
//
// gllike api
//
void glGenVertexArrays(GLsizei n, GLuint* arrays) {
*arrays = 0;
if (currentContext == NULL) {
Error(GL_INVALIDATED_CONTEXT, (const GLchar*)"context == null");
return;
}
if ((currentContext->VAOs->size() + n) >= GL_MAX_NUM_OF_VAO) {
Error(GL_OUT_BO_MAX_COUNT, (const GLchar*)"out of vao buffer object max count");
return;
}
for (size_t i = 0; i < n; i++) {
// glGenVertexArrays 只生成空数据的指针 VAO 对象
VertexArrayObject* vao = new VertexArrayObject;
*(arrays + i) = (GLuint)((void*)(vao));
if (*(arrays + i) == 0) {
Error(GL_CREATE_FAILURE, (const GLchar*)"gen vao buffer failure");
return;
}
else {
currentContext->VAOs->push_back(vao);
}
}
} // end glGenVertexArrays
void glDeleteVertexArrays(GLsizei n, GLuint* arrays) {
for (size_t i = 0; i < n; i++) {
VertexArrayObject* p = (VertexArrayObject*)(*(arrays + i));
std::vector<VertexArrayObject*>::const_iterator begin = currentContext->VAOs->begin();
std::vector<VertexArrayObject*>::const_iterator end = currentContext->VAOs->end();
for (; begin != end; begin++) {
if (*begin == p) {
currentContext->VAOs->erase(begin);
break;
}
}
delete p;
*(arrays + i) = 0;
}
} // end glDeleteVertexArrays
void glBindVertexArray(GLuint array) {
currentContext->bindingVAO = (VertexArrayObject*)array;
currentContext->defalultVAO->vbo = NULL;
currentContext->defalultVAO->ebo = NULL;
if (currentContext->defalultVAO->vafs != NULL) {
std::vector<VertexAttributeFormat*>::const_iterator begin_vaf, end_vaf;
begin_vaf = currentContext->defalultVAO->vafs->begin();
end_vaf = currentContext->defalultVAO->vafs->end();
for (; begin_vaf != end_vaf; begin_vaf++) {
delete *begin_vaf;
}
currentContext->defalultVAO->vafs->clear();
}
if (currentContext->defalultVAO->vafs_enabled != NULL) {
currentContext->defalultVAO->vafs_enabled->clear();
}
} // end glBindVertexArray
void glGenBuffers(GLsizei n, GLuint* buffers) {
*buffers = 0;
if (currentContext == NULL) {
Error(GL_INVALIDATED_CONTEXT, (const GLchar*)"context == null");
return;
}
if ((currentContext->BOs->size() + n) >= GL_MAX_NUM_OF_VBO) {
Error(GL_OUT_BO_MAX_COUNT, (const GLchar*)"out of bo buffer object max count");
return;
}
for (size_t i = 0; i < n; i++) {
// glGenBuffers 只生成空数据的指针 VBO 对象
BufferObject* vbo = new BufferObject;
*(buffers + i) = (GLuint)((void*)(vbo));
if (*(buffers + i) == 0) {
Error(GL_CREATE_FAILURE, (const GLchar*)"gen bo buffer failure");
return;
}
else {
currentContext->BOs->push_back(vbo);
}
}
} // glGenBuffers
void glDeleteBuffers(GLsizei n, GLuint* buffers) {
for (size_t i = 0; i < n; i++) {
BufferObject* p = (BufferObject*)(*(buffers + i));
std::vector<BufferObject*>::const_iterator begin = currentContext->BOs->begin();
std::vector<BufferObject*>::const_iterator end = currentContext->BOs->end();
for (; begin != end; begin++) {
if (*begin == p) {
currentContext->BOs->erase(begin);
break;
}
}
delete p;
*(buffers + i) = 0;
}
} // glDeleteBuffers
void glBindBuffer(GLenum target, GLuint buffer) {
CheckBuffType(target);
switch (target)
{
case GL_ARRAY_BUFFER: // VBO
currentContext->GetUsingVAO()->vbo = (BufferObject*)(buffer);
break;
case GL_ELEMENT_ARRAY_BUFFER: // EBO
currentContext->GetUsingVAO()->ebo = (BufferObject*)(buffer);
break;
default:
throw "un handle glBindBuffer target type";
break;
}
} // glBindBuffer
void glBufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) {
CheckBuffType(target);
// usage 参数不使用,因为这个与硬件加速相关
GLboolean validated = true;
_BuffObject** buffObj = NULL;
// 目前只对两种缓存类型做处理
switch (target)
{
case GL_ARRAY_BUFFER: // VBO
buffObj = &(currentContext->GetUsingVAO()->vbo->buf);
break;
case GL_ELEMENT_ARRAY_BUFFER: // EBO
buffObj = &(currentContext->GetUsingVAO()->ebo->buf);
break;
default:
validated = false;
GLchar str[512];
sprintf_s(str, "binding unhandle buffer type : %d", target);
Error(GL_BINDING_UN_HANDLE_BUFF_TYPE, (const GLchar*)str);
break;
} // end switch
if (validated) {
if (*buffObj == NULL) {
*buffObj = new _BuffObject();
}
if ((*buffObj)->size < size) {
if ((*buffObj)->data == NULL) {
(*buffObj)->data = (_ubuffer_T)malloc(size);
}
else {
(*buffObj)->data = (_ubuffer_T)realloc((void*)((*buffObj)->data), size);
}
(*buffObj)->capacity = size;
}
(*buffObj)->size = size;
memcpy((*buffObj)->data, data, size);
}
} // end glBufferData
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* pointer) {
std::vector<VertexAttributeFormat*>* pVec = currentContext->GetUsingVAO()->vafs;
std::vector<VertexAttributeFormat*>::const_iterator begin = pVec->begin();
std::vector<VertexAttributeFormat*>::const_iterator end = pVec->end();
bool found = false;
VertexAttributeFormat* p = NULL;
for (; begin != end; begin++) {
p = *begin;
if (p->index == index) { // 先看看目前有无重复设置的
found = true; // 有重复的
break;
}
}
if (!found) { // 没有重复的,则新建一个
p = new VertexAttributeFormat;
p->index = index;
pVec->push_back(p);
}
if (pVec->size() > 128) { // 假装最多只能有 128 个 vertex attribute
GLchar str[512];
sprintf_s(str, "glVertexAttribPointer number of vertex attribute more than 128");
throw str;
}
p->numOfComponent = size;
p->typeOfComponent = type;
p->normalized = normalized;
p->stride = stride;
p->pointer = (void*)pointer;
p->setupToVBO = (GLuint)((void*)currentContext->GetUsingVAO()->vbo); // 记录安装时的 VBO 是哪个
} // end glVertexAttribPointer
void glEnableVertexAttribArray(GLuint index) {
std::vector<GLuint>* pVec = currentContext->GetUsingVAO()->vafs_enabled; // 启用 attribute 的数据记录
std::vector<GLuint>::const_iterator begin = pVec->begin();
std::vector<GLuint>::const_iterator end = pVec->end();
VertexAttributeFormat* p = NULL;
bool found = false;
for (; begin != end; begin++) {
if ((*begin) == index) { // 如果本身是启用的,则不添加
found = true;
break;
}
}
if (found == false) { // 如果没有启用,则添加
pVec->push_back(index);
}
} // end glEnableVertexAttribArray
void glDisableVertexAttribArray(GLuint index) {
std::vector<GLuint>* pVec = currentContext->GetUsingVAO()->vafs_enabled;
std::vector<GLuint>::const_iterator begin = pVec->begin();
std::vector<GLuint>::const_iterator end = pVec->end();
VertexAttributeFormat* p = NULL;
for (; begin != end; begin++) {
if ((*begin) == index) {
pVec->erase(begin); // 找到启用的 attribute 索引,就删除
break;
}
}
} // end glDisableVertexAttribArray
void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
if (mode == GL_TRIANGLES) { // 目前只支持三角形
std::cout << "glDrawArray mode : GL_TRIANGLES\n";
if (count <= 0 || count % 3 != 0) { // 如果绘制的索引数量不是 3 的倍数,则报错
GLchar str[512];
sprintf_s(str, "glDrawArrays mode is triangle, but 'count' not the times of three : %d", count);
throw str;
}
VertexArrayObject* vao;
std::vector<GLuint>::const_iterator begin_enabled_index, end_enabled_index;
std::vector<VertexAttributeFormat*>::const_iterator begin_vaf, end_vaf;
vao = currentContext->GetUsingVAO(); // 使用的 VAO
end_enabled_index = vao->vafs_enabled->end(); // 顶点规范的启用索引数组
end_vaf = vao->vafs->end();
// 遍历顶点数
for (size_t i = 0; i < count; i ++) {
// 遍历属性索引
begin_enabled_index = vao->vafs_enabled->begin();
for (; begin_enabled_index != end_enabled_index; begin_enabled_index++) {
GLboolean found = false;
// 查找属性索引对应的格式(规范)
begin_vaf = vao->vafs->begin();
for (; begin_vaf != end_vaf; begin_vaf++) {
if ((*begin_vaf)->index == *begin_enabled_index) {
found = true;
break;
}
}
// 如果找不到启用的 attribute,则报错(OpenGL 这里会使用 静态的顶点属性,这里就不实现了,直接报错)
if (!found) {
GLchar str[512];
sprintf_s(str, "glDrawArrays mode is triangle, but not found attribute loation : %d", *begin_enabled_index);
throw str;
}
// 取格式(规范)中绑定的 VBO
BufferObject* vbo = (BufferObject*)((*begin_vaf)->setupToVBO);
// 取 VBO 中的数据
_ubuffer_T buffer = (vbo->buf->data);
// 取顶点的偏移,按 stride 来偏移
// 这里为了测试 VAO 整体应用,只打印一下数据即可
// 其实也可以再写个 C++ 版本的软渲染器来替换这里的打印也是可以的
GLuint offset = ((GLuint)((*begin_vaf)->stride)) * i;
PrintVertex(i, *begin_vaf, buffer + offset);
}
}
}
else {
GLchar str[512];
sprintf_s(str, "unhandle glDrawArrays mode : %d", mode);
throw str;
}
} // end glDrawArrays
void glDrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) {
if (mode == GL_TRIANGLES) { // 目前只支持三角形
std::cout << "glDrawElements mode : GL_TRIANGLES\n";
if (count <= 0 || count % 3 != 0) { // 如果绘制的索引数量不是 3 的倍数,则报错
GLchar str[512];
sprintf_s(str, "glDrawElements mode is triangle, but 'count' not the times of three : %d", count);
throw str;
}
VertexArrayObject* vao;
BufferObject* ebo;
GLuint vertexIndex;
std::vector<GLuint>::const_iterator begin_enabled_index, end_enabled_index;
std::vector<VertexAttributeFormat*>::const_iterator begin_vaf, end_vaf;
vao = currentContext->GetUsingVAO();
ebo = vao->ebo;
end_enabled_index = vao->vafs_enabled->end();
end_vaf = vao->vafs->end();
if (type != GL_UNSIGNED_INT) {
GLchar str[512];
sprintf_s(str, "glDrawElements unhandle type : %d", type);
throw str;
}
GLuint* indexBuffer = (GLuint*)(ebo->buf->data + (GLuint)indices); // 真正的索引缓存数据
// 根据索引遍历顶点数
for (size_t i = 0; i < count; i++) {
// 获取 EBO 中的索引值
vertexIndex = *(indexBuffer + i);
// 遍历属性索引
begin_enabled_index = vao->vafs_enabled->begin();
for (; begin_enabled_index != end_enabled_index; begin_enabled_index++) {
GLboolean found = false;
// 查找属性索引对应的格式(规范)
begin_vaf = vao->vafs->begin();
for (; begin_vaf != end_vaf; begin_vaf++) {
if ((*begin_vaf)->index == *begin_enabled_index) {
found = true;
break;
}
}
if (!found) {
GLchar str[512];
sprintf_s(str, "glDrawElements mode is triangle, but not found attribute loation : %d", *begin_enabled_index);
throw str;
}
// 取格式(规范)中绑定的 VBO
BufferObject* vbo = (BufferObject*)((*begin_vaf)->setupToVBO);
// 取 VBO 中的数据
_ubuffer_T buffer = (vbo->buf->data);
// 取顶点的偏移,按 stride 来偏移
// 这里为了测试 VAO 整体应用,只打印一下数据即可
// 其实也可以再写个 C++ 版本的软渲染器来替换这里的打印也是可以的
GLuint offset = ((GLuint)((*begin_vaf)->stride)) * vertexIndex; // 使用索引值来偏移 VBO 数据
PrintVertex(i, *begin_vaf, buffer + offset);
}
}
}
else {
GLchar str[512];
sprintf_s(str, "unhandle glDrawElements mode : %d", mode);
throw str;
}
} // end glDrawElements
Main.cpp
// Main.cpp
// jave.lin - 测试自己写的 gllike,目前为了测试 VAO/VBO/EBO 等接口的使用
#include<iostream>
#include<string.h>
#include"gl_like.h"
extern Context* currentContext;
extern GLint errorCode;
extern GLchar* errorMsg;
void PrintGlobalError() {
GLchar errorCodeMeans[512] = { 0 };
switch (errorCode)
{
case GL_INVALIDATED_CONTEXT: strcpy_s(errorCodeMeans, 512, "Invalidated context"); break;
case GL_OUT_BO_MAX_COUNT: strcpy_s(errorCodeMeans, 512, "Out of buffer object max count"); break;
case GL_CREATE_FAILURE: strcpy_s(errorCodeMeans, 512, "Create / alloc failure"); break;
case GL_CONTEXT_NOT_NULL: strcpy_s(errorCodeMeans, 512, "Context not null"); break;
case GL_BINDING_UN_HANDLE_BUFF_TYPE: strcpy_s(errorCodeMeans, 512, "Binding unhandle buffer type"); break;
case GL_SET_BUFF_VALUES_BUFF_NULL: strcpy_s(errorCodeMeans, 512, "Buffer is NULL, while Setting buffer"); break;
default:
break;
}
if (errorCode != 0) {
std::cout << "Error Code : " << errorCode << ", Mean : " << errorCodeMeans << ", Message : " << (errorMsg == NULL ? "" : errorMsg) << "\n";
}
}
void testDrawTriangleByOnlyVBO_2FloatComponent() {
GLuint vbo;
// 生成 VBO
glGenBuffers(1, &vbo);
if (vbo == 0) {
std::cout << "Generate VBO Buffer Failure : " << vbo << "\n";
exit(EXIT_FAILURE);
}
// 顶点
GLfloat vertices[9] = {
-0.5f, -0.5f,
+0.5f, -0.5f,
+0.0f, +0.5f,
};
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, (GLsizei)sizeof(GLfloat) * 2, 0);
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
// 绘制 VBO 内容
glDrawArrays(GL_TRIANGLES, 0, 3);
// 禁用 0 索引顶点属性 VBO 格式
glDisableVertexAttribArray(0);
// 取消绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 删除 VBO
glDeleteBuffers(1, &vbo);
} // testDrawTriangleByOnlyVBO
void testDrawTriangleByOnlyVBO() {
GLuint vbo;
// 生成 VBO
glGenBuffers(1, &vbo);
if (vbo == 0) {
std::cout << "Generate VBO Buffer Failure : " << vbo << "\n";
exit(EXIT_FAILURE);
}
// 顶点
GLfloat vertices[9] = {
-0.5f, -0.5f, +0.0f,
+0.5f, -0.5f, +0.0f,
+0.0f, +0.5f, +0.0f,
};
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (GLsizei)sizeof(GLfloat) * 3, 0);
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
// 绘制 VBO 内容
glDrawArrays(GL_TRIANGLES, 0, 3);
// 禁用 0 索引顶点属性 VBO 格式
glDisableVertexAttribArray(0);
// 取消绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 删除 VBO
glDeleteBuffers(1, &vbo);
} // testDrawTriangleByOnlyVBO
void testDrawQuadByOnlyVBO() {
GLuint vbo;
// 生成 VBO
glGenBuffers(1, &vbo);
if (vbo == 0) {
std::cout << "Generate VBO Buffer Failure : " << vbo << "\n";
exit(EXIT_FAILURE);
}
// 顶点
GLfloat vertices[18] = {
-0.5f, -0.5f, +0.0f,
+0.5f, -0.5f, +0.0f,
-0.5f, +0.5f, +0.0f,
+0.5f, -0.5f, +0.0f,
+0.5f, +0.5f, +0.0f,
-0.5f, +0.5f, +0.0f,
};
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (GLsizei)sizeof(GLfloat) * 3, 0);
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
// 绘制 VBO 内容
glDrawArrays(GL_TRIANGLES, 0, 6);
// 禁用 0 索引顶点属性 VBO 格式
glDisableVertexAttribArray(0);
// 取消绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 删除 VBO
glDeleteBuffers(1, &vbo);
} // testDrawQuadByOnlyVBO
void testDrawQuadByOnlyVBO_2Attribute_Pos_Col_inSingleVBO() {
GLuint vbo;
// 生成 VBO
glGenBuffers(1, &vbo);
if (vbo == 0) {
std::cout << "Generate VBO Buffer Failure : " << vbo << "\n";
exit(EXIT_FAILURE);
}
// 顶点
GLfloat vertices[36] = {
// x y z r g b
-0.5f, -0.5f, +0.0f, 1.0f, 0.0f, 0.0f,
+0.5f, -0.5f, +0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, +0.5f, +0.0f, 0.0f, 0.0f, 1.0f,
+0.5f, -0.5f, +0.0f, 0.0f, 1.0f, 0.0f,
+0.5f, +0.5f, +0.0f, 1.0f, 1.0f, 0.0f,
-0.5f, +0.5f, +0.0f, 0.0f, 0.0f, 1.0f,
};
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (GLsizei)sizeof(GLfloat) * 6, 0);
// 设置 1 索引顶点属性 VBO 格式
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, (GLsizei)sizeof(GLfloat) * 6, (const void*)(sizeof(GLfloat) * 3));
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
// 启用 1 索引顶点属性 VBO 格式
glEnableVertexAttribArray(1);
// 绘制 VBO 内容
glDrawArrays(GL_TRIANGLES, 0, 6);
// 禁用 0 索引顶点属性 VBO 格式
glDisableVertexAttribArray(0);
// 禁用 1 索引顶点属性 VBO 格式
glDisableVertexAttribArray(1);
// 取消绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 删除 VBO
glDeleteBuffers(1, &vbo);
} // testDrawQuadByOnlyVBO
void testDrawQuadByOnlyVBO_2Attribute_Pos_Col_TwoVBO() {
GLuint vbo[2];
// 生成 VBO
glGenBuffers(2, vbo);
if (vbo[0] == 0 || vbo[1] == 0) {
std::cout << "Generate VBO Buffer Failure : [0]=" << vbo[0] << "[1]=" << vbo[1] << "\n";
exit(EXIT_FAILURE);
}
// 顶点
GLfloat vertices[18] = {
// x y z
-0.5f, -0.5f, +0.0f,
+0.5f, -0.5f, +0.0f,
-0.5f, +0.5f, +0.0f,
+0.5f, -0.5f, +0.0f,
+0.5f, +0.5f, +0.0f,
-0.5f, +0.5f, +0.0f,
};
// 颜色
GLfloat colors[18] = {
//r g b
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
};
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, (GLsizei)sizeof(GLfloat) * 3, 0);
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, (GLsizei)sizeof(GLfloat) * 3, 0);
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(1);
// 绘制 VBO 内容
glDrawArrays(GL_TRIANGLES, 0, 6);
// 禁用 0 索引顶点属性 VBO 格式
glDisableVertexAttribArray(0);
// 禁用 1 索引顶点属性 VBO 格式
glDisableVertexAttribArray(1);
// 取消绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 删除 VBO
glDeleteBuffers(2, vbo);
} // testDrawQuadByOnlyVBO
void testVAO_VBO_EBO_vertex_single_buff() {
GLuint vao;
// 生成 VAO
glGenVertexArrays(1, &vao);
if (vao == 0) {
std::cout << "Generate VAO Buffer Failure : " << vao << "\n";
exit(EXIT_FAILURE);
}
GLuint vbo;
// 生成 VBO
glGenBuffers(1, &vbo);
if (vbo == 0) {
std::cout << "Generate VBO Buffer Failure : " << vbo << "\n";
exit(EXIT_FAILURE);
}
GLuint ebo;
// 生成 EBO
glGenBuffers(1, &ebo);
if (ebo == 0) {
std::cout << "Generate EBO Buffer Failure : " << ebo << "\n";
exit(EXIT_FAILURE);
}
// 顶点
GLfloat vertices[24] = {
// x y z r g b
-0.5f, -0.5f, +0.0f, 1.0f, 0.0f, 0.0f,
+0.5f, -0.5f, +0.0f, 0.0f, 1.0f, 0.0f,
+0.5f, +0.5f, +0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, +0.5f, +0.0f, 1.0f, 1.0f, 0.0f,
};
// 索引
GLuint indices[] = {
0, 1, 3,
1, 2, 3
};
// 绑定 VAO
glBindVertexArray(vao);
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 绑定 EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
// 设置 EBO 数据
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, (GLsizei)sizeof(GLfloat) * 6, 0);
// 设置 1 索引顶点属性 VBO 格式
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, (GLsizei)sizeof(GLfloat) * 6, (void*)(sizeof(GLfloat) * 3));
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
// 启用 1 索引顶点属性 VBO 格式
glEnableVertexAttribArray(1);
// 绘制 EBO 内容,当前我们绑定了 VAO 的,所以使用的是 VAO 内的 EBO
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// 禁用 0 索引顶点属性 VBO 格式
glDisableVertexAttribArray(0);
// 禁用 1 索引顶点属性 VBO 格式
glDisableVertexAttribArray(1);
// 取消绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 取消绑定 EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// 取消绑定 VAO
glBindVertexArray(0);
// 删除 EBO
glDeleteBuffers(1, &ebo);
// 删除 VBO
glDeleteBuffers(1, &vbo);
// 删除 VAO
glDeleteVertexArrays(1, &vao);
}
void testMultiVAO() {
GLuint vao[2];
// 生成 VAO
glGenVertexArrays(2, vao);
if (vao[0] == 0 || vao[1] == 0) {
std::cout << "Generate VAO Buffer Failure : [0]=" << vao[0] << " [1]=" << vao[1] << "\n";
exit(EXIT_FAILURE);
}
GLuint vbo[2];
// 生成 VBO
glGenBuffers(2, vbo);
if (vbo[0] == 0 || vbo[1] == 0) {
std::cout << "Generate VBO Buffer Failure : [0]=" << vbo[0] << " [1]=" << vbo[1] << "\n";
exit(EXIT_FAILURE);
}
GLuint ebo[2];
// 生成 EBO
glGenBuffers(2, ebo);
if (ebo[0] == 0 || ebo[1] == 0) {
std::cout << "Generate EBO Buffer Failure : [0]=" << ebo[0] << " [1]=" << ebo[1] << "\n";
exit(EXIT_FAILURE);
}
//
// 第一个 VAO 的设置
//
// 顶点
GLfloat vertices_0[24] = {
// x y z r g b
-0.5f, -0.5f, +0.0f, 1.0f, 0.0f, 0.0f,
+0.5f, -0.5f, +0.0f, 0.0f, 1.0f, 0.0f,
+0.5f, +0.5f, +0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, +0.5f, +0.0f, 1.0f, 1.0f, 0.0f,
};
// 索引
GLuint indices_0[] = {
0, 1, 3,
1, 2, 3
};
// 绑定 VAO[0]
glBindVertexArray(vao[0]);
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_0), vertices_0, GL_STATIC_DRAW);
// 绑定 EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo[0]);
// 设置 EBO 数据
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_0), indices_0, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, (GLsizei)sizeof(GLfloat) * 6, 0);
// 设置 1 索引顶点属性 VBO 格式
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, (GLsizei)sizeof(GLfloat) * 6, (void*)(sizeof(GLfloat) * 3));
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
// 启用 1 索引顶点属性 VBO 格式
glEnableVertexAttribArray(1);
//
// 第二个 VAO 的设置
//
// 顶点
GLfloat vertices_1[18] = {
// x y z r g b
-0.5f, -0.5f, +0.0f, 1.0f, 0.0f, 0.0f,
+0.5f, -0.5f, +0.0f, 0.0f, 1.0f, 0.0f,
+0.5f, +0.5f, +0.0f, 0.0f, 0.0f, 1.0f,
};
// 索引
GLuint indices_1[] = {
0, 1, 2
};
// 绑定 VAO[0]
glBindVertexArray(vao[1]);
// 绑定 VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
// 设置 VBO 数据
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_1), vertices_1, GL_STATIC_DRAW);
// 绑定 EBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo[1]);
// 设置 EBO 数据
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_1), indices_1, GL_STATIC_DRAW);
// 设置 0 索引顶点属性 VBO 格式
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, (GLsizei)sizeof(GLfloat) * 6, 0);
// 设置 1 索引顶点属性 VBO 格式
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, (GLsizei)sizeof(GLfloat) * 6, (void*)(sizeof(GLfloat) * 3));
// 启用 0 索引顶点属性 VBO 格式
glEnableVertexAttribArray(0);
// 启用 1 索引顶点属性 VBO 格式
glEnableVertexAttribArray(1);
//
// 开始绘制
//
// 绘制第一个 VAO
glBindVertexArray(vao[0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// 绘制第二个 VAO
glBindVertexArray(vao[1]);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
// 取消绑定 VAO
glBindVertexArray(0);
// 删除 EBO
glDeleteBuffers(2, ebo);
// 删除 VBO
glDeleteBuffers(2, vbo);
// 删除 VAO
glDeleteVertexArrays(2, vao);
}
int main() {
GLuint context;
if (!CreateContext(4, 6, &context)) {
std::cout << "Create Context Failure\n";
exit(EXIT_FAILURE);
}
MakeCurrentContext(context);
std::cout << " === Testing [testDrawTriangleByOnlyVBO_2FloatComponent] START ===\n";
testDrawTriangleByOnlyVBO_2FloatComponent();
std::cout << " === Testing [testDrawTriangleByOnlyVBO_2FloatComponent] END ===\n\n";
std::cout << " === Testing [testDrawTriangleByOnlyVBO] START ===\n";
testDrawTriangleByOnlyVBO();
std::cout << " === Testing [testDrawTriangleByOnlyVBO] END ===\n\n";
std::cout << " === Testing [testDrawQuadByOnlyVBO] START ===\n";
testDrawQuadByOnlyVBO();
std::cout << " === Testing [testDrawQuadByOnlyVBO] END ===\n\n";
std::cout << " === Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_inSingleVBO] START ===\n";
testDrawQuadByOnlyVBO_2Attribute_Pos_Col_inSingleVBO();
std::cout << " === Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_inSingleVBO] END ===\n\n";
std::cout << " === Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_TwoVBO] START ===\n";
testDrawQuadByOnlyVBO_2Attribute_Pos_Col_TwoVBO();
std::cout << " === Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_TwoVBO] END ===\n\n";
std::cout << " === Testing [testVAO_VBO_EBO_vertex_single_buff] START ===\n";
testVAO_VBO_EBO_vertex_single_buff();
std::cout << " === Testing [testVAO_VBO_EBO_vertex_single_buff] END ===\n\n";
std::cout << " === Testing [testMultiVAO] START ===\n";
testMultiVAO();
std::cout << " === Testing [testMultiVAO] END ===\n\n";
// 实现分开的 VBO
Terminate();
PrintGlobalError();
return 0;
}
运行效果
=== Testing [testDrawTriangleByOnlyVBO_2FloatComponent] START ===
glDrawArray mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:2 TypeOfComponent:5126 Normalized:false Strid:8 Pointer(Offset):0
vec2( -0.5, -0.5 )
VertexID:1 Location:0 NumOfComponent:2 TypeOfComponent:5126 Normalized:false Strid:8 Pointer(Offset):0
vec2( 0.5, -0.5 )
VertexID:2 Location:0 NumOfComponent:2 TypeOfComponent:5126 Normalized:false Strid:8 Pointer(Offset):0
vec2( 0, 0.5 )
=== Testing [testDrawTriangleByOnlyVBO_2FloatComponent] END ===
=== Testing [testDrawTriangleByOnlyVBO] START ===
glDrawArray mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( -0.5, -0.5, 0 )
VertexID:1 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:2 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0, 0.5, 0 )
=== Testing [testDrawTriangleByOnlyVBO] END ===
=== Testing [testDrawQuadByOnlyVBO] START ===
glDrawArray mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( -0.5, -0.5, 0 )
VertexID:1 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:2 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:3 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:4 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0.5, 0.5, 0 )
VertexID:5 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
=== Testing [testDrawQuadByOnlyVBO] END ===
=== Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_inSingleVBO] START ===
glDrawArray mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):0
vec3( -0.5, -0.5, 0 )
VertexID:0 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):12
vec3( 1, 0, 0 )
VertexID:1 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:1 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):12
vec3( 0, 1, 0 )
VertexID:2 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:2 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):12
vec3( 0, 0, 1 )
VertexID:3 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:3 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):12
vec3( 0, 1, 0 )
VertexID:4 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):0
vec3( 0.5, 0.5, 0 )
VertexID:4 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):12
vec3( 1, 1, 0 )
VertexID:5 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:5 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:24 Pointer(Offset):12
vec3( 0, 0, 1 )
=== Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_inSingleVBO] END ===
=== Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_TwoVBO] START ===
glDrawArray mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( -0.5, -0.5, 0 )
VertexID:0 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 1, 0, 0 )
VertexID:1 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:1 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0, 1, 0 )
VertexID:2 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:2 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0, 0, 1 )
VertexID:3 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:3 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0, 1, 0 )
VertexID:4 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0.5, 0.5, 0 )
VertexID:4 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 1, 1, 0 )
VertexID:5 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:5 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:false Strid:12 Pointer(Offset):0
vec3( 0, 0, 1 )
=== Testing [testDrawQuadByOnlyVBO_2Attribute_Pos_Col_TwoVBO] END ===
=== Testing [testVAO_VBO_EBO_vertex_single_buff] START ===
glDrawElements mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( -0.5, -0.5, 0 )
VertexID:0 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 1, 0, 0 )
VertexID:1 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:1 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 1, 0 )
VertexID:2 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:2 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 1, 1, 0 )
VertexID:3 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:3 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 1, 0 )
VertexID:4 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, 0.5, 0 )
VertexID:4 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 0, 1 )
VertexID:5 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:5 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 1, 1, 0 )
=== Testing [testVAO_VBO_EBO_vertex_single_buff] END ===
=== Testing [testMultiVAO] START ===
glDrawElements mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( -0.5, -0.5, 0 )
VertexID:0 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 1, 0, 0 )
VertexID:1 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:1 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 1, 0 )
VertexID:2 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:2 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 1, 1, 0 )
VertexID:3 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:3 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 1, 0 )
VertexID:4 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, 0.5, 0 )
VertexID:4 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 0, 1 )
VertexID:5 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( -0.5, 0.5, 0 )
VertexID:5 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 1, 1, 0 )
glDrawElements mode : GL_TRIANGLES
VertexID:0 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( -0.5, -0.5, 0 )
VertexID:0 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 1, 0, 0 )
VertexID:1 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, -0.5, 0 )
VertexID:1 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 1, 0 )
VertexID:2 Location:0 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):0
vec3( 0.5, 0.5, 0 )
VertexID:2 Location:1 NumOfComponent:3 TypeOfComponent:5126 Normalized:true Strid:24 Pointer(Offset):12
vec3( 0, 0, 1 )
=== Testing [testMultiVAO] END ===