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

简介: 《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 );
}

效果图:

image.png

目录
相关文章
|
2月前
|
XML 小程序 Java
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
77 0
|
缓存 C++
Opengl ES之FBO
Opengl ES连载系列
105 0
|
存储 编解码 算法
Opengl ES之LUT滤镜(上)
Opengl ES之连载系列
378 0
|
数据安全/隐私保护 开发者
OpenGL ES 多目标渲染(MRT)
Opengl ES连载系列
257 0
|
数据安全/隐私保护 索引
Opengl ES之纹理数组
Opengl ES连载系列
218 0
|
数据安全/隐私保护
Opengl ES之水印贴图
Opengl ES之连载系列
114 0
|
Java 数据安全/隐私保护 Android开发
Opengl ES之矩阵变换(下)
Opengl ES连载系列
99 0
|
Java API 数据安全/隐私保护
Opengl ES之矩阵变换(上)
Opengl ES连载系列
105 0
|
存储
Opengl ES之踩坑记
Opengl ES之连载系列
107 0
|
存储 编解码 算法
Opengl ES之RGB转NV21
Opengl ES连载系列
126 0