背景
学完《Learn OpenGL》之后,又开始看安卓端的OpenGLES,发现有如下代码:
// 这是用于GLES
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
// Load the vertex data
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
glEnableVertexAttribArray (0);
第一次看这段代码我困惑于为什么不用创建对应的VAO和VBO,而是直接使用glVertexAttribPointer
,后来查阅发现《Learn OpenGL》使用OpenGL3.3 core和OpenGLES3.0虽然语法很像,但是具体略有区别。
glVertexAttribPointer的差别
单看glVertexAttribPointer
的文档可以发现,首先两者的签名是相同的:
void glVertexAttribPointer( GLuint index,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
const GLvoid * pointer);
但是在对于pointer参数的解释上,两者存在不同:
对于OpenGLES
pointer
Specifies a pointer to the first generic vertex attribute in the array. If a non-zero buffer is currently bound to the GL_ARRAY_BUFFER
target, pointer
specifies an offset of into the array in the data store of that buffer. The initial value is 0.
If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER
target (see glBindBuffer), pointer
is treated as a byte offset into the buffer object’s data store and the buffer object binding (GL_ARRAY_BUFFER_BINDING
) is saved as generic vertex attribute array state (GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
) for index index
.
Client vertex arrays (a binding of zero to the GL_ARRAY_BUFFER
target) are only valid in conjunction with the zero named vertex array object. This is provided for backwards compatibility with OpenGL ES 2.0.
对于OpenGL 3.3
pointer
Specifies a offset of the first component of the first generic vertex attribute in the array in the data store of the buffer currently bound to the GL_ARRAY_BUFFER
target. The initial value is 0.
If pointer
is not NULL
, a non-zero named buffer object must be bound to the GL_ARRAY_BUFFER
target (see glBindBuffer), otherwise an error is generated.
总结
简单来说:对于OpenGLES,glVertexAttribPointer
的pointer可以作为指向数组的指针,也可以作为偏移量,这取决于是否有buffer(VBO) 绑定在上面。而对于OpenGL3.3,pointer只能作为偏移量,如果pointer不为NULL并且没有绑定VBO,则会报错。
代码示例
OpenGLES3.0
由于GLES3.0对于GLES2.0的兼容性设计,以下三种使用顶点数据的方式均可:
假设这是顶点数据
LOGCATE("TriangleSample::Draw");
GLfloat vVertices[] = {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
};
不使用VAO及VBO
// =============================================
// Load the vertex data without VAO and VBO
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );
glEnableVertexAttribArray (0);
只用VBO不用VAO
// Using VBO only
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL );
glEnableVertexAttribArray (0);
同时使用VAO和VBO
// Using VAO and VBO
GLuint vao;
GLuint vbo;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vVertices), vVertices, GL_STATIC_DRAW);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL );
glEnableVertexAttribArray (0);
OpenGL 3.3 Core
只能使用VBO+VAO的模式