您的位置:首页 > 编程语言 > C语言/C++

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

2016-09-03 20:23 686 查看
由于《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 );
}


效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OpenGL
相关文章推荐