| Index: third_party/gles_book_examples/Chapter_13/ParticleSystem/ParticleSystem.c
|
| ===================================================================
|
| --- third_party/gles_book_examples/Chapter_13/ParticleSystem/ParticleSystem.c (revision 35873)
|
| +++ third_party/gles_book_examples/Chapter_13/ParticleSystem/ParticleSystem.c (working copy)
|
| @@ -1,294 +0,0 @@
|
| -//
|
| -// Book: OpenGL(R) ES 2.0 Programming Guide
|
| -// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
|
| -// ISBN-10: 0321502795
|
| -// ISBN-13: 9780321502797
|
| -// Publisher: Addison-Wesley Professional
|
| -// URLs: http://safari.informit.com/9780321563835
|
| -// http://www.opengles-book.com
|
| -//
|
| -
|
| -// ParticleSystem.c
|
| -//
|
| -// This is an example that demonstrates rendering a particle system
|
| -// using a vertex shader and point sprites.
|
| -//
|
| -#include <stdlib.h>
|
| -#include <math.h>
|
| -#include "esUtil.h"
|
| -
|
| -#define NUM_PARTICLES 1000
|
| -#define PARTICLE_SIZE 7
|
| -
|
| -typedef struct
|
| -{
|
| - // Handle to a program object
|
| - GLuint programObject;
|
| -
|
| - // Attribute locations
|
| - GLint lifetimeLoc;
|
| - GLint startPositionLoc;
|
| - GLint endPositionLoc;
|
| -
|
| - // Uniform location
|
| - GLint timeLoc;
|
| - GLint colorLoc;
|
| - GLint centerPositionLoc;
|
| - GLint samplerLoc;
|
| -
|
| - // Texture handle
|
| - GLuint textureId;
|
| -
|
| - // Particle vertex data
|
| - float particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
|
| -
|
| - // Current time
|
| - float time;
|
| -
|
| -} 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 )
|
| -{
|
| - UserData *userData = esContext->userData;
|
| - int i;
|
| -
|
| - GLbyte vShaderStr[] =
|
| - "uniform float u_time; \n"
|
| - "uniform vec3 u_centerPosition; \n"
|
| - "attribute float a_lifetime; \n"
|
| - "attribute vec3 a_startPosition; \n"
|
| - "attribute vec3 a_endPosition; \n"
|
| - "varying float v_lifetime; \n"
|
| - "void main() \n"
|
| - "{ \n"
|
| - " if ( u_time <= a_lifetime ) \n"
|
| - " { \n"
|
| - " gl_Position.xyz = a_startPosition + \n"
|
| - " (u_time * a_endPosition); \n"
|
| - " gl_Position.xyz += u_centerPosition; \n"
|
| - " gl_Position.w = 1.0; \n"
|
| - " } \n"
|
| - " else \n"
|
| - " gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
|
| - " v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
|
| - " v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
|
| - " gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
|
| - "}";
|
| -
|
| - GLbyte fShaderStr[] =
|
| - "precision mediump float; \n"
|
| - "uniform vec4 u_color; \n"
|
| - "varying float v_lifetime; \n"
|
| - "uniform sampler2D s_texture; \n"
|
| - "void main() \n"
|
| - "{ \n"
|
| - " vec4 texColor; \n"
|
| - " texColor = texture2D( s_texture, gl_PointCoord ); \n"
|
| - " gl_FragColor = vec4( u_color ) * texColor; \n"
|
| - " gl_FragColor.a *= v_lifetime; \n"
|
| - "} \n";
|
| -
|
| - // Load the shaders and get a linked program object
|
| - userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
|
| -
|
| - // Get the attribute locations
|
| - userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
|
| - userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
|
| - userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
|
| -
|
| - // Get the uniform locations
|
| - userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
|
| - userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
|
| - userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
|
| - userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
|
| -
|
| - glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
|
| -
|
| - // Fill in particle data array
|
| - srand ( 0 );
|
| - for ( i = 0; i < NUM_PARTICLES; i++ )
|
| - {
|
| - float *particleData = &userData->particleData[i * PARTICLE_SIZE];
|
| -
|
| - // Lifetime of particle
|
| - (*particleData++) = ( (float)(rand() % 10000) / 10000.0f );
|
| -
|
| - // End position of particle
|
| - (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
|
| - (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
|
| - (*particleData++) = ( (float)(rand() % 10000) / 5000.0f ) - 1.0f;
|
| -
|
| - // Start position of particle
|
| - (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
|
| - (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
|
| - (*particleData++) = ( (float)(rand() % 10000) / 40000.0f ) - 0.125f;
|
| -
|
| - }
|
| -
|
| - // Initialize time to cause reset on first update
|
| - userData->time = 1.0f;
|
| -
|
| - userData->textureId = LoadTexture ( "smoke.tga" );
|
| - if ( userData->textureId <= 0 )
|
| - {
|
| - return FALSE;
|
| - }
|
| -
|
| - return TRUE;
|
| -}
|
| -
|
| -///
|
| -// Update time-based variables
|
| -//
|
| -void Update ( ESContext *esContext, float deltaTime )
|
| -{
|
| - UserData *userData = esContext->userData;
|
| -
|
| - userData->time += deltaTime;
|
| -
|
| - if ( userData->time >= 1.0f )
|
| - {
|
| - float centerPos[3];
|
| - float color[4];
|
| -
|
| - userData->time = 0.0f;
|
| -
|
| - // Pick a new start location and color
|
| - centerPos[0] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
|
| - centerPos[1] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
|
| - centerPos[2] = ( (float)(rand() % 10000) / 10000.0f ) - 0.5f;
|
| -
|
| - glUniform3fv ( userData->centerPositionLoc, 1, ¢erPos[0] );
|
| -
|
| - // Random color
|
| - color[0] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
|
| - color[1] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
|
| - color[2] = ( (float)(rand() % 10000) / 20000.0f ) + 0.5f;
|
| - color[3] = 0.5;
|
| -
|
| - glUniform4fv ( userData->colorLoc, 1, &color[0] );
|
| - }
|
| -
|
| - // Load uniform time variable
|
| - glUniform1f ( userData->timeLoc, userData->time );
|
| -}
|
| -
|
| -///
|
| -// Draw a triangle using the shader pair created in Init()
|
| -//
|
| -void Draw ( ESContext *esContext )
|
| -{
|
| - UserData *userData = esContext->userData;
|
| -
|
| - // 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 attributes
|
| - glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
|
| - GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
|
| - userData->particleData );
|
| -
|
| - glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
|
| - GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
|
| - &userData->particleData[1] );
|
| -
|
| - glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
|
| - GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
|
| - &userData->particleData[4] );
|
| -
|
| -
|
| - glEnableVertexAttribArray ( userData->lifetimeLoc );
|
| - glEnableVertexAttribArray ( userData->endPositionLoc );
|
| - glEnableVertexAttribArray ( userData->startPositionLoc );
|
| - // Blend particles
|
| - glEnable ( GL_BLEND );
|
| - glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
|
| -
|
| - // Bind the texture
|
| - glActiveTexture ( GL_TEXTURE0 );
|
| - glBindTexture ( GL_TEXTURE_2D, userData->textureId );
|
| - glEnable ( GL_TEXTURE_2D );
|
| -
|
| - // Set the sampler texture unit to 0
|
| - glUniform1i ( userData->samplerLoc, 0 );
|
| -
|
| - glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
|
| -
|
| - eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
|
| -}
|
| -
|
| -///
|
| -// Cleanup
|
| -//
|
| -void ShutDown ( ESContext *esContext )
|
| -{
|
| - UserData *userData = esContext->userData;
|
| -
|
| - // 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, "ParticleSystem", 640, 480, ES_WINDOW_RGB );
|
| -
|
| - if ( !Init ( &esContext ) )
|
| - return 0;
|
| -
|
| - esRegisterDrawFunc ( &esContext, Draw );
|
| - esRegisterUpdateFunc ( &esContext, Update );
|
| -
|
| - esMainLoop ( &esContext );
|
| -
|
| - ShutDown ( &esContext );
|
| -}
|
|
|