《OpenGL ES 2.0 Programming Guide》第9章 “最简单的本地纹理+VBO”示例代码【C语言版】

由于《OpenGL ES 2.0 Programming Guide》原书第9章并没有提供相关的示例,为了加深理解,遂自己实现了一份C语言版本作为练习,希望能够帮助到同样喜欢OpenGL ES 2.0的同学。

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


#include <stdlib.h>
#include "esUtil.h"

#define VERTEX_POS_SIZE     3 // x, y and z
#define TEXCOORD_SIZE		2 // u,v
#define INDICES_SIZE		6 
typedef struct
{
	// Handle to a program object
	GLuint programObject;

	// Attribute locations
	GLint  positionLoc;
	GLint  texCoordLoc;

	// Sampler location
	GLint samplerLoc;

	// Texture handle
	GLuint textureId;

	// VertexBufferObject Ids ☆
	GLuint vboIds[2];

} UserData;

///
// Load texture from disk
//
GLuint LoadTexture ( char *fileName )
{
	int width, height;

	char *buffer = esLoadTGA ( fileName, &width, &height );
	GLuint texId;

	if ( buffer == NULL )
	{
		esLogMessage ( "Error loading (%s) image.\n", fileName );
		return 0;
	}

	glGenTextures ( 1, &texId );
	glBindTexture ( GL_TEXTURE_2D, texId );

	glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

	free ( buffer );

	return texId;
}

///
// Initialize the shader and program object
//
int Init ( ESContext *esContext )
{
	char *fileName = "../Fieldstone.tga";

	UserData *userData = (UserData *)esContext->userData;
	const char vShaderStr[] =
		"attribute vec4 a_position;   \n"
		"attribute vec2 a_texCoord;   \n"
		"varying vec2 v_texCoord;     \n"
		"void main()                  \n"
		"{                            \n"
		"   gl_Position = a_position; \n"
		"   v_texCoord = a_texCoord;  \n"
		"}                            \n";

	const char fShaderStr[] =
		"precision mediump float;                            \n"
		"varying vec2 v_texCoord;                            \n"
		"uniform sampler2D s_texture;                        \n"
		"void main()                                         \n"
		"{                                                   \n"
		"  gl_FragColor = texture2D( s_texture, v_texCoord );\n"
		"}                                                   \n";

	// Load the shaders and get a linked program object
	userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );

	// Get the attribute locations
	userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
	userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );

	// Get the sampler location
	userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );

	// Load the texture ☆
	userData->textureId = LoadTexture(fileName);

	// Init VBO ids ☆
	userData->vboIds[0] = 0;
	userData->vboIds[1] = 0;

	glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
	return TRUE;
}

///
// Draw a triangle using the shader pair created in Init()
//
void Draw ( ESContext *esContext )
{
	UserData *userData = (UserData *)esContext->userData;
	GLfloat vVertices[] = { -1.f,  1.f, 0.0f,  // Position 0
		0.0f,  0.0f,        // TexCoord 0
		-1.f, -1.f, 0.0f,  // Position 1
		0.0f,  1.0f,        // TexCoord 1
		1.f, -1.f, 0.0f,  // Position 2
		1.0f,  1.0f,        // TexCoord 2
		1.f,  1.f, 0.0f,  // Position 3
		1.0f,  0.0f         // TexCoord 3
	};
	GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
	int numVertices = 4;

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

		glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[0] );
		glBufferData ( GL_ARRAY_BUFFER, (VERTEX_POS_SIZE + TEXCOORD_SIZE) * sizeof(GLfloat) * numVertices,
			vVertices, GL_STATIC_DRAW );

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

	// Set the viewport
	glViewport ( 0, 0, esContext->width, esContext->height );

	// Clear the color buffer
	glClear ( GL_COLOR_BUFFER_BIT );

	// Use the program object
	glUseProgram ( userData->programObject );

	// Load the vertex position
	glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[0] );
	glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
		GL_FALSE, (VERTEX_POS_SIZE + TEXCOORD_SIZE) * sizeof(GLfloat), 0 );

	// Load the texture coordinate
	glBindBuffer ( GL_ARRAY_BUFFER, userData->vboIds[0] );
	glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
		GL_FALSE, (VERTEX_POS_SIZE + TEXCOORD_SIZE) * sizeof(GLfloat), (void*)(VERTEX_POS_SIZE * sizeof(GLfloat)));

	glEnableVertexAttribArray ( userData->positionLoc );
	glEnableVertexAttribArray ( userData->texCoordLoc );

	// Bind the texture
	glActiveTexture ( GL_TEXTURE0 );
	glBindTexture ( GL_TEXTURE_2D, userData->textureId );

	// Set the sampler texture unit to 0
	glUniform1i ( userData->samplerLoc, 0 );

	glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, userData->vboIds[1] );
	glDrawElements ( GL_TRIANGLES, INDICES_SIZE, GL_UNSIGNED_SHORT, 0);

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

	glDisableVertexAttribArray ( userData->positionLoc );
	glDisableVertexAttribArray ( userData->texCoordLoc );
	glBindBuffer ( GL_ARRAY_BUFFER, 0 );
	glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, 0 );
}

///
// Cleanup
//
void ShutDown ( ESContext *esContext )
{
	UserData *userData = (UserData *)esContext->userData;
<span style="white-space:pre">	// Delete Buffers
	glDeleteBuffers ( 2, userData->vboIds );</span>
	// Delete texture object
	glDeleteTextures ( 1, &userData->textureId );

	// Delete program object
	glDeleteProgram ( userData->programObject );
}


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

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

	esCreateWindow ( &esContext, "Simple VBO Texture 2D", 512, 512, ES_WINDOW_RGB );

	if ( !Init ( &esContext ) )
		return 0;

	esRegisterDrawFunc ( &esContext, Draw );

	esMainLoop ( &esContext );

	ShutDown ( &esContext );
}



效果图:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ShaderJoy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值