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

举报
ShaderJoy 发表于 2021/12/30 00:35:01 2021/12/30
【摘要】 由于《OpenGL ES 2.0 Programming Guide》原书第9章并没有提供相关的示例,为了加深理解,遂自己实现了一份C语言版本作为练习,希望能够帮助到同样喜欢OpenGL ES 2.0的同学。 废话不多说,直接上代码: #include <stdlib.h>#include "esUtil.h...

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



      #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 );
      }
  
 





文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/52425155

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。