Home | History | Annotate | Download | only in MultipleRenderTargets
      1 //
      2 // Modified from Simple_Texture2D, found in:
      3 //
      4 // Book:      OpenGL(R) ES 2.0 Programming Guide
      5 // Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
      6 // ISBN-10:   0321502795
      7 // ISBN-13:   9780321502797
      8 // Publisher: Addison-Wesley Professional
      9 // URLs:      http://safari.informit.com/9780321563835
     10 //            http://www.opengles-book.com
     11 //
     12 
     13 // MultipleRenderTargets.c
     14 //
     15 //    This is a simple example that shows how to use multiple render
     16 //    targets in GLES 2.0 using EXT_draw_buffers. The example
     17 //    draws to three render targets and displays
     18 //    them together in a final pass.
     19 //
     20 #include <stdlib.h>
     21 #include "esUtil.h"
     22 
     23 PFNGLDRAWBUFFERSEXTPROC glDrawBuffersEXT;
     24 
     25 typedef struct
     26 {
     27    // Handle to a program object
     28    GLuint programObjectMRT;
     29    GLuint programObject;
     30 
     31    // Attribute locations
     32    GLint  positionLoc;
     33    GLint  texCoordLoc;
     34 
     35    // Sampler location
     36    GLint samplerLoc;
     37 
     38    // Texture handle
     39    GLuint textureId;
     40 
     41    // Framebuffer object handle
     42    GLuint framebuffer;
     43 
     44    // Framebuffer color attachments
     45    GLuint framebufferTextures[4];
     46 
     47 } UserData;
     48 
     49 ///
     50 // Create a simple 2x2 texture image with four different colors
     51 //
     52 GLuint CreateSimpleTexture2D( )
     53 {
     54    // Texture object handle
     55    GLuint textureId;
     56 
     57    // 2x2 Image, 3 bytes per pixel (R, G, B)
     58    GLubyte pixels[4 * 3] =
     59    {
     60       255,   0,   0, // Red
     61         0, 255,   0, // Green
     62         0,   0, 255, // Blue
     63       255, 255,   0  // Yellow
     64    };
     65 
     66    // Use tightly packed data
     67    glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
     68 
     69    // Generate a texture object
     70    glGenTextures ( 1, &textureId );
     71 
     72    // Bind the texture object
     73    glBindTexture ( GL_TEXTURE_2D, textureId );
     74 
     75    // Load the texture
     76    glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
     77 
     78    // Set the filtering mode
     79    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
     80    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
     81 
     82    return textureId;
     83 
     84 }
     85 
     86 
     87 ///
     88 // Initialize the shader and program object
     89 //
     90 int Init ( ESContext *esContext )
     91 {
     92    UserData *userData = (UserData*)esContext->userData;
     93    GLbyte vShaderStr[] =
     94       "attribute vec4 a_position;   \n"
     95       "attribute vec2 a_texCoord;   \n"
     96       "varying vec2 v_texCoord;     \n"
     97       "void main()                  \n"
     98       "{                            \n"
     99       "   gl_Position = a_position; \n"
    100       "   v_texCoord = a_texCoord;  \n"
    101       "}                            \n";
    102 
    103    GLbyte fMultiShaderStr[] =
    104       "#extension GL_EXT_draw_buffers : enable             \n"
    105       "precision mediump float;                            \n"
    106       "varying vec2 v_texCoord;                            \n"
    107       "uniform sampler2D s_texture;                        \n"
    108       "void main()                                         \n"
    109       "{                                                   \n"
    110       "  vec4 color = texture2D( s_texture, v_texCoord );  \n"
    111       "  gl_FragData[0] = color;                           \n"
    112       "  gl_FragData[1] = vec4(1.0, 1.0, 1.0, 1.0) - color.brga;\n"
    113       "  gl_FragData[2] = vec4(0.2, 1.0, 0.5, 1.0) * color.gbra;\n"
    114       "  gl_FragData[3] = color.rrra;                      \n"
    115       "}                                                   \n";
    116 
    117    GLbyte fShaderStr[] =
    118       "precision mediump float;                            \n"
    119       "varying vec2 v_texCoord;                            \n"
    120       "uniform sampler2D s_texture;                        \n"
    121       "void main()                                         \n"
    122       "{                                                   \n"
    123       "  vec4 color = texture2D( s_texture, v_texCoord );  \n"
    124       "  gl_FragColor = color;                             \n"
    125       "}                                                   \n";
    126 
    127    int i;
    128 
    129    // Check EXT_draw_buffers is supported
    130    if (strstr(glGetString(GL_EXTENSIONS), "GL_EXT_draw_buffers") == 0)
    131    {
    132        return FALSE;
    133    }
    134 
    135    // Retrieve the address of glDrawBuffersEXT from EGL
    136    glDrawBuffersEXT = (PFNGLDRAWBUFFERSEXTPROC)eglGetProcAddress("glDrawBuffersEXT");
    137 
    138    // Load the shaders and get a linked program object
    139    userData->programObject = esLoadProgram ( (const char*)vShaderStr, (const char*)fShaderStr );
    140 
    141    userData->programObjectMRT = esLoadProgram ( (const char*)vShaderStr, (const char*)fMultiShaderStr );
    142 
    143    // Get the attribute locations
    144    userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" );
    145    userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" );
    146 
    147    // Get the sampler location
    148    userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
    149 
    150    // Load the texture
    151    userData->textureId = CreateSimpleTexture2D ();
    152 
    153    glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f );
    154 
    155    // Initialize the user framebuffer
    156    glGenFramebuffers(1, &userData->framebuffer);
    157    glGenTextures(4, userData->framebufferTextures);
    158 
    159    glBindFramebuffer(GL_FRAMEBUFFER, userData->framebuffer);
    160 
    161    for (i = 0; i < 4; i++)
    162    {
    163        // Create textures for the four color attachments
    164        glBindTexture(GL_TEXTURE_2D, userData->framebufferTextures[i]);
    165        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, esContext->width, esContext->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    166        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    167        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    168        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    169        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    170        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, userData->framebufferTextures[i], 0);
    171    }
    172 
    173    glBindTexture(GL_TEXTURE_2D, 0);
    174 
    175    return TRUE;
    176 }
    177 
    178 ///
    179 // Draw a triangle using the shader pair created in Init()
    180 //
    181 void Draw ( ESContext *esContext )
    182 {
    183    UserData *userData = (UserData*)esContext->userData;
    184    GLfloat vVertices[] = { -0.8f,  0.8f, 0.0f,  // Position 0
    185                             0.0f,  0.0f,        // TexCoord 0
    186                            -0.8f, -0.8f, 0.0f,  // Position 1
    187                             0.0f,  1.0f,        // TexCoord 1
    188                             0.8f, -0.8f, 0.0f,  // Position 2
    189                             1.0f,  1.0f,        // TexCoord 2
    190                             0.8f,  0.8f, 0.0f,  // Position 3
    191                             1.0f,  0.0f         // TexCoord 3
    192                          };
    193    GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
    194 
    195    GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT };
    196 
    197    // Enable drawing to the four color attachments of the user framebuffer
    198    glBindFramebuffer(GL_FRAMEBUFFER, userData->framebuffer);
    199    glDrawBuffersEXT(4, drawBuffers);
    200 
    201    // Set the viewport
    202    glViewport ( 0, 0, esContext->width, esContext->height );
    203 
    204    // Clear the color buffer
    205    glClear ( GL_COLOR_BUFFER_BIT );
    206 
    207    // Use the program object
    208    glUseProgram ( userData->programObjectMRT );
    209 
    210    // Load the vertex position
    211    glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT,
    212                            GL_FALSE, 5 * sizeof(GLfloat), vVertices );
    213    // Load the texture coordinate
    214    glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT,
    215                            GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] );
    216 
    217    glEnableVertexAttribArray ( userData->positionLoc );
    218    glEnableVertexAttribArray ( userData->texCoordLoc );
    219 
    220    // Bind the texture
    221    glActiveTexture ( GL_TEXTURE0 );
    222    glBindTexture ( GL_TEXTURE_2D, userData->textureId );
    223 
    224    // Set the sampler texture unit to 0
    225    glUniform1i ( userData->samplerLoc, 0 );
    226 
    227    // Draw the textured quad to the four render targets
    228    glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
    229 
    230    // Enable the default framebuffer and single textured drawing
    231    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    232    glUseProgram ( userData->programObject );
    233 
    234    // Draw the four textured quads to a separate region in the viewport
    235    glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[0]);
    236    glViewport ( 0, 0, esContext->width/2, esContext->height/2 );
    237    glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
    238 
    239    glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[1]);
    240    glViewport ( esContext->width/2, 0, esContext->width/2, esContext->height/2 );
    241    glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
    242 
    243    glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[2]);
    244    glViewport ( 0, esContext->height/2, esContext->width/2, esContext->height/2 );
    245    glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
    246 
    247    glBindTexture( GL_TEXTURE_2D, userData->framebufferTextures[3]);
    248    glViewport ( esContext->width/2, esContext->height/2, esContext->width/2, esContext->height/2 );
    249    glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
    250 
    251    eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
    252 }
    253 
    254 ///
    255 // Cleanup
    256 //
    257 void ShutDown ( ESContext *esContext )
    258 {
    259    UserData *userData = (UserData*)esContext->userData;
    260 
    261    glDeleteTextures(4, userData->framebufferTextures);
    262 
    263    glDeleteFramebuffers(1, &userData->framebuffer);
    264 
    265    // Delete texture object
    266    glDeleteTextures ( 1, &userData->textureId );
    267 
    268    // Delete program object
    269    glDeleteProgram ( userData->programObject );
    270 
    271    eglDestroyContext(esContext->eglDisplay, esContext->eglContext);
    272    eglDestroySurface(esContext->eglDisplay, esContext->eglSurface);
    273    eglTerminate(esContext->eglDisplay);
    274 }
    275 
    276 
    277 int main ( int argc, char *argv[] )
    278 {
    279    ESContext esContext;
    280    UserData  userData;
    281 
    282    esInitContext ( &esContext );
    283    esContext.userData = &userData;
    284 
    285    esCreateWindow ( &esContext, TEXT("Multiple Render Targets"), 320, 240, ES_WINDOW_RGB );
    286 
    287    if ( !Init ( &esContext ) )
    288       return 0;
    289 
    290    esRegisterDrawFunc ( &esContext, Draw );
    291 
    292    esMainLoop ( &esContext );
    293 
    294    ShutDown ( &esContext );
    295 }
    296