《OpenGL ES 2.0 Programming Guide》第8章 “最简单的Vertex Buffer Object”示例代码【C语言版】

本文提供了一个OpenGLES2.0中使用顶点缓冲对象(VBO)的C语言示例代码,通过创建并绘制一个带有颜色的三角形来演示VBO的基本用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于《OpenGL ES 2.0 Programming Guide》原书并没有提供第8章的关于VBO的示例代码,书上的代码也只提到关键的步骤,网上的例子大都不够精简,为了加深理解,遂自己实现了一份最简单的C语言版本,希望能够帮助到同样喜欢OpenGL ES 2.0的同学。

废话不多说,直接上代码:

#include "esUtil.h"

typedef struct
{
	// Handle to a program object
	GLuint programObject;

	GLint positionLoc;
	GLint colorLoc; 

	// VertexBufferObject Ids
	GLuint vboIds[3];

} UserData;


#define VERTEX_POS_SIZE       3 // x, y and z
#define VERTEX_COLOR_SIZE     4 // r, g, b, and a


int Init ( ESContext *esContext )
{
	UserData *userData = esContext->userData;
	const char vShaderStr[] =
		"attribute vec3 a_position;					\n"
		"attribute vec4 a_color;					\n"
		"varying vec4 v_color;						\n"
		"void main()								\n"
		"{											\n"
		"    v_color = a_color;						\n"
		"    gl_Position = vec4(a_position, 1.0);	\n"
		"}											\n";


	const char fShaderStr[] =
		"precision mediump float;						\n"
		"varying vec4 v_color;							\n"
		"void main()									\n"
		"{												\n"
		"    gl_FragColor = v_color;					\n"
		"}												\n" ;

	GLuint programObject;

	// Create the program object
	programObject = esLoadProgram ( vShaderStr, fShaderStr );

	if ( programObject == 0 )
	{
		return GL_FALSE;
	}

	// Store the program object
	userData->programObject = programObject;
	userData->vboIds[0] = 0;// pos
	userData->vboIds[1] = 0;// color
	userData->vboIds[2] = 0;// index

	userData->positionLoc = glGetAttribLocation(userData->programObject, "a_position");
	userData->colorLoc = glGetAttribLocation(userData->programObject, "a_color");


	glClearColor ( 1.0f, 1.0f, 1.0f, 0.0f );
	return GL_TRUE;
}

void DrawPrimitiveWithVBOs ( ESContext *esContext,
				GLint numVertices, GLfloat *vertexPosBuf, GLfloat *vertexColorBuf,
				GLint *vtxStrides, GLint numIndices,
				GLushort *indices )
{
	UserData *userData = esContext->userData;

	// vboIds[0] - used to store vertex position
	// vboIds[1] - used to store vertex color
	// vboIds[2] - used to store element indices
	// run only once
	if ( userData->vboIds[0] == 0 && userData->vboIds[1] == 0 &&
		userData->vboIds[2] == 0 )
	{
		// Only allocate on the first draw
		glGenBuffers ( 3, userData->vboIds );

		glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[0] );
		glBufferData ( GL_ARRAY_BUFFER, vtxStrides[0] * numVertices,
			vertexPosBuf, GL_STATIC_DRAW );

		glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[1] );
		glBufferData ( GL_ARRAY_BUFFER, vtxStrides[1] * numVertices,
			vertexColorBuf, GL_STATIC_DRAW );

		glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->vboIds[2] );
		glBufferData ( GL_ELEMENT_ARRAY_BUFFER,
			sizeof ( GLushort ) * numIndices,
			indices, GL_STATIC_DRAW );
	}

	glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[0] );
	glVertexAttribPointer ( userData->positionLoc, 
		VERTEX_POS_SIZE,
		GL_FLOAT, GL_FALSE, vtxStrides[0], 0 );
	glEnableVertexAttribArray ( userData->positionLoc );

	glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[1] );
	glVertexAttribPointer ( userData->colorLoc,
		VERTEX_COLOR_SIZE,
		GL_FLOAT, GL_FALSE, vtxStrides[1], 0 );
	glEnableVertexAttribArray ( userData->colorLoc );

	glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->vboIds[2] );

	glDrawElements ( GL_TRIANGLES, numIndices,
		GL_UNSIGNED_SHORT, 0 );

	eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );	// ☆

	// ---------------------------------------------------
	glDisableVertexAttribArray ( userData->positionLoc );
	glDisableVertexAttribArray ( userData->colorLoc );

	glBindBuffer ( GL_ARRAY_BUFFER, 0 );
	glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

void Draw ( ESContext *esContext )
{
	UserData *userData = esContext->userData;

	// 3 vertices, with (x,y,z) ,(r, g, b, a) per-vertex
	GLfloat vertexPos[3 * VERTEX_POS_SIZE] =
	{
		0.0f,  0.5f, 0.0f,         // v0
		-0.5f, -0.5f, 0.0f,        // v1
		0.5f, -0.5f, 0.0f          // v2
	};
	GLfloat color[4 * VERTEX_COLOR_SIZE] =
	{
		1.0f, 0.0f, 0.0f, 1.0f,   // c0
		0.0f, 1.0f, 0.0f, 1.0f,   // c1
		0.0f, 0.0f, 1.0f, 1.0f    // c2
	};
	GLint vtxStrides[2] =
	{
		VERTEX_POS_SIZE * sizeof ( GLfloat ),
		VERTEX_COLOR_SIZE * sizeof ( GLfloat )
	};

	// Index buffer data
	GLushort indices[3] = { 0, 1, 2 };
	//GLfloat *vtxBuf[2] = { vertexPos, color };

	glViewport ( 0, 0, esContext->width, esContext->height );
	glClear ( GL_COLOR_BUFFER_BIT );
	glUseProgram ( userData->programObject );

	DrawPrimitiveWithVBOs ( esContext, 3, vertexPos, color,
		vtxStrides, 3, indices );
}

void ShutDown ( ESContext *esContext )
{
	UserData *userData = esContext->userData;

	glDeleteProgram ( userData->programObject );
	glDeleteBuffers ( 3, userData->vboIds );
}

int main ( int argc, char *argv[] )
{
	ESContext esContext;
	UserData  userData;

	esInitContext ( &esContext );
	esContext.userData = &userData;

	esCreateWindow ( &esContext, "SimpleVBO", 320, 240, ES_WINDOW_RGB );

	if ( !Init ( &esContext ) )
	{
		return GL_FALSE;
	}

	esRegisterDrawFunc ( &esContext, Draw );
	esMainLoop ( &esContext );
	ShutDown ( &esContext );

	return GL_TRUE;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ShaderJoy

您的打赏是我继续写博客的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值