/// // Update time-based variables // void Update(Example *example, KDfloat32 deltaTime) { UserData *userData = (UserData *)example->userptr; userData->time += deltaTime; if(userData->time >= 1.0f) { KDfloat32 centerPos[3]; KDfloat32 color[4]; userData->time = 0.0f; KDuint8 buffer[6] = {0}; kdCryptoRandom(buffer, 6); // Pick a new start location and color centerPos[0] = ((KDfloat32)((buffer[0] * 128) % 10000) / 10000.0f) - 0.5f; centerPos[1] = ((KDfloat32)((buffer[1] * 128) % 10000) / 10000.0f) - 0.5f; centerPos[2] = ((KDfloat32)((buffer[2] * 128) % 10000) / 10000.0f) - 0.5f; glUniform3fv(userData->centerPositionLoc, 1, ¢erPos[0]); // Random color color[0] = ((KDfloat32)((buffer[3] * 128) % 10000) / 20000.0f) + 0.5f; color[1] = ((KDfloat32)((buffer[4] * 128) % 10000) / 20000.0f) + 0.5f; color[2] = ((KDfloat32)((buffer[5] * 128) % 10000) / 20000.0f) + 0.5f; color[3] = 0.5; glUniform4fv(userData->colorLoc, 1, &color[0]); } // Load uniform time variable glUniform1f(userData->timeLoc, userData->time); }
/// // Initialize the shader and program object // KDboolean Init(Example *example) { UserData *userData = (UserData *)example->userptr; const KDchar *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" "}"; const KDchar *fShaderStr = "#ifdef GL_FRAGMENT_PRECISION_HIGH \n" " precision highp float; \n" "#else \n" " precision mediump float; \n" "#endif \n" " \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"; // Store the program object userData->programObject = exampleCreateProgram(vShaderStr, fShaderStr, KD_TRUE); // Use the program object glUseProgram(userData->programObject); // 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, 1.0f); // Fill in particle data array for(KDint i = 0; i < NUM_PARTICLES; i++) { GLfloat *particleData = &userData->particleData[i * PARTICLE_SIZE]; KDuint8 buffer[7] = {0}; kdCryptoRandom(buffer, 7); // Lifetime of particle (*particleData++) = ((KDfloat32)((buffer[0] * 128) % 10000) / 10000.0f); // End position of particle (*particleData++) = ((KDfloat32)((buffer[1] * 128) % 10000) / 5000.0f) - 1.0f; (*particleData++) = ((KDfloat32)((buffer[2] * 128) % 10000) / 5000.0f) - 1.0f; (*particleData++) = ((KDfloat32)((buffer[3] * 128) % 10000) / 5000.0f) - 1.0f; // Start position of particle (*particleData++) = ((KDfloat32)((buffer[4] * 128) % 10000) / 40000.0f) - 0.125f; (*particleData++) = ((KDfloat32)((buffer[5] * 128) % 10000) / 40000.0f) - 0.125f; (*particleData++) = ((KDfloat32)((buffer[6] * 128) % 10000) / 40000.0f) - 0.125f; } glGenBuffers(1, &userData->vertexObject); glBindBuffer(GL_ARRAY_BUFFER, userData->vertexObject); glBufferData(GL_ARRAY_BUFFER, NUM_PARTICLES * PARTICLE_SIZE * 4, userData->particleData, GL_STATIC_DRAW); // Initialize time to cause reset on first update userData->time = 1.0f; userData->textureId = exampleLoadTexture("data/smoke.png"); if(userData->textureId <= 0) { return KD_FALSE; } return KD_TRUE; }
/*! * \brief Render the OpenGL ES scene. * \param time Current time in milliseconds * \note Renders the OpenGL ES scene *//*-------------------------------------------------------------------*/ void renderGLESScene(unsigned int time) { int width = 0; int height = 0; #if defined(TEST_LOCKSURFACE) KDuint16 *fb = KD_NULL; int y = 0; EGLint pitch = 0; EGLint origin = 0; EGLint r, g, b; #else /* Time needed for the rotation */ const KDfloat32 effectTime = kdFmodf(time / 4000.0f, 360.0f); #endif /* Query the current window surface size from EGL */ eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_WIDTH, (EGLint *)&width); eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_HEIGHT, (EGLint *)&height); #if !defined(TEST_LOCKSURFACE) /* Update the GLES state */ updateOpenGLESState (width, height); glClear (GL_COLOR_BUFFER_BIT); /* Rotate the world matrix and translate it on the z-axis */ glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glTranslatex (F2F(0.f), F2F(0.f), F2F(-30.f)); glRotatex (F2F((float)(effectTime*29.77f)), F2F(1.0f), F2F(2.0f), F2F(0.0f)); glRotatex (F2F((float)(effectTime*22.311f)), F2F(-0.1f), F2F(0.0f), -F2F(5.0f)); glBindTexture(GL_TEXTURE_2D, GLOBALS->tex); /* Set the pointer to the arrays containing the cube vertices, normals and texture coordinates */ glVertexPointer (3, GL_BYTE, 0, s_cubeVertices); glNormalPointer (GL_BYTE, 0, s_cubeNormals); glTexCoordPointer (2, GL_BYTE, 0, s_cubeTexCoords); /* Draw the cube one face at a time in the same order thay have been defined in the s_cubeVertices array */ glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); glDrawArrays (GL_TRIANGLE_STRIP, 4, 4); glDrawArrays (GL_TRIANGLE_STRIP, 8, 4); glDrawArrays (GL_TRIANGLE_STRIP, 12, 4); glDrawArrays (GL_TRIANGLE_STRIP, 16, 4); glDrawArrays (GL_TRIANGLE_STRIP, 20, 4); #else /* Lock the surface and query for the properties */ eglLockSurfaceKHR(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, KD_NULL); eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_BITMAP_POINTER_KHR, (EGLint *)&fb); eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_BITMAP_PITCH_KHR, &pitch); eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_BITMAP_ORIGIN_KHR, &origin); eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_BITMAP_PIXEL_RED_OFFSET_KHR, &r); eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR, &g); eglQuerySurface(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface, EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR, &b); /* Fill the surface with random noise */ for(y = 0; y < height; y++) { kdCryptoRandom((KDuint8 *)fb, width * 2); fb += pitch / 2; } eglUnlockSurfaceKHR(GLOBALS->eglDisplay, GLOBALS->eglWindowSurface); #endif /* Display the result on the screen */ eglSwapBuffers (GLOBALS->eglDisplay, GLOBALS->eglWindowSurface); }