Tuesday, June 14, 2011

glGenRenderbuffers example c c++ java objc

Name

glGenRenderbuffers — generate renderbuffer object names

C Specification

void glGenRenderbuffers(GLsizei  n,
GLuint * renderbuffers);

Parameters

n
Specifies the number of renderbuffer object names to generate.
renderbuffers
Specifies an array in which the generated renderbuffer object names are stored.

Description

glGenRenderbuffers returns n renderbuffer object names in renderbuffers. There is no guarantee that the names form a contiguous set of integers; however, it is guaranteed that none of the returned names was in use immediately before the call to glGenRenderbuffers.
Renderbuffer object names returned by a call to glGenRenderbuffers are not returned by subsequent calls, unless they are first deleted with glDeleteRenderbuffers.
The names returned in renderbuffers are marked as used, for the purposes of glGenRenderbuffers only, but they acquire state and type only when they are first bound.

Errors

GL_INVALID_VALUE is generated if n is negative.

Copyright

Copyright © 2010 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.

Example of glGenRenderbuffers

// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{
    fprintf(stdout, "FBO Draw Buffers Demo\n\n");

    // Make sure required functionality is available: cube maps, auto mip gen, etc.
    if (!GLEE_VERSION_1_4)
    {
        fprintf(stderr, "OpenGL 1.4 is not available!\n");
        Sleep(2000);
        exit(0);
    }

    if (GLEE_ARB_texture_non_power_of_two)
    {
        npotTexturesAvailable = GL_TRUE;
    }
    else
    {
        fprintf(stderr, "GL_ARB_texture_non_power_of_two extension is not available!\n");
        fprintf(stderr, "Framebuffer effects will be lower resolution (lower quality).\n\n");
    }

    if (!GLEE_EXT_framebuffer_object)
    {
        fprintf(stderr, "GL_EXT_framebuffer_object extension is unavailable!\n");
        Sleep(2000);
        exit(0);
    }

    // we'll use up to 4 render targets if they're available
    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments);
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTexUnits);
    maxDrawBuffers = (maxDrawBuffers > maxColorAttachments) ? maxColorAttachments : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > (maxTexUnits-1)) ? (maxTexUnits-1) : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > 4) ? 4 : maxDrawBuffers;
    if (((!GLEE_ARB_draw_buffers || !GLEE_ARB_fragment_shader || !GLEE_ARB_shader_objects) 
        && !GLEE_VERSION_2_0) || (maxDrawBuffers != 4))
    {
        fprintf(stderr, "Support for at least 4 draw buffers is unavailable!\n");
        Sleep(2000);
        exit(0);
    }

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxRenderbufferSize);
    maxTexSize = (maxRenderbufferSize > maxTexSize) ? maxTexSize : maxRenderbufferSize;

    fprintf(stdout, "Controls:\n");
    fprintf(stdout, "\tRight-click for menu\n\n");
    fprintf(stdout, "\tx/X\t\tMove +/- in x direction\n");
    fprintf(stdout, "\ty/Y\t\tMove +/- in y direction\n");
    fprintf(stdout, "\tz/Z\t\tMove +/- in z direction\n\n");
    fprintf(stdout, "\td/D\t\tToggle use of draw buffers\n\n");
    fprintf(stdout, "\tq\t\tExit demo\n\n");
    
    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // Hidden surface removal
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // Set up some lighting state that never changes
    glShadeModel(GL_SMOOTH);
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    glMaterialfv(GL_FRONT, GL_SPECULAR, specularLight);
    glMateriali(GL_FRONT, GL_SHININESS, 128);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_NORMALIZE);
    glEnable(GL_LIGHT0);

    // Set up textures & shaders
    SetupTextures();
    SetupShaders();

    // Set up some renderbuffer state
    glGenRenderbuffersEXT(1, &renderbufferID);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbufferID);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, fboWidth, fboHeight);

    glGenFramebuffersEXT(2, framebufferID);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[0]);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbufferID);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, renderTextureID[0], 0);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[1]);
    for (int i = 0; i < maxDrawBuffers; i++)
    {
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, renderTextureID[i+1], 0);
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

glFramebufferRenderbuffer example c c++ java objc

Name

glFramebufferRenderbuffer — attach a renderbuffer as a logical buffer to the currently bound framebuffer object

C Specification

GLsync glFramebufferRenderbuffer(GLenum  target,
GLenum  attachment,
GLenum  renderbuffertarget,
GLuint  renderbuffer);

Parameters

target
Specifies the framebuffer target. target must be GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER, or GL_FRAMEBUFFER. GL_FRAMEBUFFER is equivalent to GL_DRAW_FRAMEBUFFER.
attachment
Specifies the attachment point of the framebuffer.
renderbuffertarget
Specifies the renderbuffer target and must be GL_RENDERBUFFER.
renderbuffer
Specifies the name of an existing renderbuffer object of type renderbuffertarget to attach.

Description

glFramebufferRenderbuffer attaches a renderbuffer as one of the logical buffers of the currently bound framebuffer object. renderbuffer is the name of the renderbuffer object to attach and must be either zero, or the name of an existing renderbuffer object of type renderbuffertarget. If renderbuffer is not zero and if glFramebufferRenderbuffer is successful, then the renderbuffer name renderbufferwill be used as the logical buffer identified by attachment of the framebuffer currently bound to target.
The value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE for the specified attachment point is set to GL_RENDERBUFFER and the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME is set torenderbuffer. All other state values of the attachment point specified by attachment are set to their default values. No change is made to the state of the renderbuuffer object and any previous attachment to theattachment logical buffer of the framebuffer target is broken.
Calling glFramebufferRenderbuffer with the renderbuffer name zero will detach the image, if any, identified by attachment, in the framebuffer currently bound to target. All state values of the attachment point specified by attachment in the object bound to target are set to their default values.
Setting attachment to the value GL_DEPTH_STENCIL_ATTACHMENT is a special case causing both the depth and stencil attachments of the framebuffer object to be set to renderbuffer, which should have the base internal format GL_DEPTH_STENCIL.

Errors

GL_INVALID_ENUM is generated if target is not one of the accepted tokens.
GL_INVALID_ENUM is generated if renderbuffertarget is not GL_RENDERBUFFER.
GL_INVALID_OPERATION is generated if zero is bound to target.

Copyright

Copyright © 2010 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.

Example of glFramebufferRenderbuffer

// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{
    fprintf(stdout, "FBO Draw Buffers Demo\n\n");

    // Make sure required functionality is available: cube maps, auto mip gen, etc.
    if (!GLEE_VERSION_1_4)
    {
        fprintf(stderr, "OpenGL 1.4 is not available!\n");
        Sleep(2000);
        exit(0);
    }

    if (GLEE_ARB_texture_non_power_of_two)
    {
        npotTexturesAvailable = GL_TRUE;
    }
    else
    {
        fprintf(stderr, "GL_ARB_texture_non_power_of_two extension is not available!\n");
        fprintf(stderr, "Framebuffer effects will be lower resolution (lower quality).\n\n");
    }

    if (!GLEE_EXT_framebuffer_object)
    {
        fprintf(stderr, "GL_EXT_framebuffer_object extension is unavailable!\n");
        Sleep(2000);
        exit(0);
    }

    // we'll use up to 4 render targets if they're available
    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments);
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTexUnits);
    maxDrawBuffers = (maxDrawBuffers > maxColorAttachments) ? maxColorAttachments : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > (maxTexUnits-1)) ? (maxTexUnits-1) : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > 4) ? 4 : maxDrawBuffers;
    if (((!GLEE_ARB_draw_buffers || !GLEE_ARB_fragment_shader || !GLEE_ARB_shader_objects) 
        && !GLEE_VERSION_2_0) || (maxDrawBuffers != 4))
    {
        fprintf(stderr, "Support for at least 4 draw buffers is unavailable!\n");
        Sleep(2000);
        exit(0);
    }

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxRenderbufferSize);
    maxTexSize = (maxRenderbufferSize > maxTexSize) ? maxTexSize : maxRenderbufferSize;

    fprintf(stdout, "Controls:\n");
    fprintf(stdout, "\tRight-click for menu\n\n");
    fprintf(stdout, "\tx/X\t\tMove +/- in x direction\n");
    fprintf(stdout, "\ty/Y\t\tMove +/- in y direction\n");
    fprintf(stdout, "\tz/Z\t\tMove +/- in z direction\n\n");
    fprintf(stdout, "\td/D\t\tToggle use of draw buffers\n\n");
    fprintf(stdout, "\tq\t\tExit demo\n\n");
    
    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // Hidden surface removal
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // Set up some lighting state that never changes
    glShadeModel(GL_SMOOTH);
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    glMaterialfv(GL_FRONT, GL_SPECULAR, specularLight);
    glMateriali(GL_FRONT, GL_SHININESS, 128);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_NORMALIZE);
    glEnable(GL_LIGHT0);

    // Set up textures & shaders
    SetupTextures();
    SetupShaders();

    // Set up some renderbuffer state
    glGenRenderbuffersEXT(1, &renderbufferID);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbufferID);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, fboWidth, fboHeight);

    glGenFramebuffersEXT(2, framebufferID);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[0]);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbufferID);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, renderTextureID[0], 0);

    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[1]);
    for (int i = 0; i < maxDrawBuffers; i++)
    {
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, renderTextureID[i+1], 0);
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

glBindFramebuffer example c c++ java objc

Name

glBindFramebuffer — bind a framebuffer to a framebuffer target

C Specification

void glBindFramebuffer(GLenum  target,
GLuint  framebuffer);

Parameters

target
Specifies the framebuffer target of the binding operation.
framebuffer
Specifies the name of the framebuffer object to bind.

Description

glBindFramebuffer binds the framebuffer object with name framebuffer to the framebuffer target specified by target. target must be either GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER. If a framebuffer object is bound to GL_DRAW_FRAMEBUFFER or GL_READ_FRAMEBUFFER, it becomes the target for rendering or readback operations, respectively, until it is deleted or another framebuffer is bound to the corresponding bind point. Calling glBindFramebuffer with target set to GL_FRAMEBUFFER binds framebuffer to both the read and draw framebuffer targets. framebuffer is the name of a framebuffer object previously returned from a call to glGenFramebuffers, or zero to break the existing binding of a framebuffer object to target.

Errors

GL_INVALID_ENUM is generated if target is not GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER.
GL_INVALID_OPERATION is generated if framebuffer is not zero or the name of a framebuffer previously returned from a call to glGenFramebuffers.

Copyright

Copyright © 2010 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.

Example of glBindFramebuffer

// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{
    fprintf(stdout, "FBO Draw Buffers Demo\n\n");

    // Make sure required functionality is available: cube maps, auto mip gen, etc.
    if (!GLEE_VERSION_1_4)
    {
        fprintf(stderr, "OpenGL 1.4 is not available!\n");
        Sleep(2000);
        exit(0);
    }

    if (GLEE_ARB_texture_non_power_of_two)
    {
        npotTexturesAvailable = GL_TRUE;
    }
    else
    {
        fprintf(stderr, "GL_ARB_texture_non_power_of_two extension is not available!\n");
        fprintf(stderr, "Framebuffer effects will be lower resolution (lower quality).\n\n");
    }

    if (!GLEE_EXT_framebuffer_object)
    {
        fprintf(stderr, "GL_EXT_framebuffer_object extension is unavailable!\n");
        Sleep(2000);
        exit(0);
    }

    // we'll use up to 4 render targets if they're available
    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments);
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTexUnits);
    maxDrawBuffers = (maxDrawBuffers > maxColorAttachments) ? maxColorAttachments : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > (maxTexUnits-1)) ? (maxTexUnits-1) : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > 4) ? 4 : maxDrawBuffers;
    if (((!GLEE_ARB_draw_buffers || !GLEE_ARB_fragment_shader || !GLEE_ARB_shader_objects) 
        && !GLEE_VERSION_2_0) || (maxDrawBuffers != 4))
    {
        fprintf(stderr, "Support for at least 4 draw buffers is unavailable!\n");
        Sleep(2000);
        exit(0);
    }

    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxRenderbufferSize);
    maxTexSize = (maxRenderbufferSize > maxTexSize) ? maxTexSize : maxRenderbufferSize;

    fprintf(stdout, "Controls:\n");
    fprintf(stdout, "\tRight-click for menu\n\n");
    fprintf(stdout, "\tx/X\t\tMove +/- in x direction\n");
    fprintf(stdout, "\ty/Y\t\tMove +/- in y direction\n");
    fprintf(stdout, "\tz/Z\t\tMove +/- in z direction\n\n");
    fprintf(stdout, "\td/D\t\tToggle use of draw buffers\n\n");
    fprintf(stdout, "\tq\t\tExit demo\n\n");
    
    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );

    // Hidden surface removal
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    // Set up some lighting state that never changes
    glShadeModel(GL_SMOOTH);
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    glMaterialfv(GL_FRONT, GL_SPECULAR, specularLight);
    glMateriali(GL_FRONT, GL_SHININESS, 128);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_NORMALIZE);
    glEnable(GL_LIGHT0);

    // Set up textures & shaders
    SetupTextures();
    SetupShaders();

    // Set up some renderbuffer state
    glGenRenderbuffersEXT(1, &renderbufferID);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbufferID);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, fboWidth, fboHeight);

    glGenFramebuffersEXT(2, framebufferID);
    // glBindFramebuffer(GL_FRAMEBUFFER, framebufferID[0]);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[0]);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbufferID);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, renderTextureID[0], 0);

    // glBindFramebuffer(GL_FRAMEBUFFER, framebufferID[1]);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[1]);
    for (int i = 0; i < maxDrawBuffers; i++)
    {
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, renderTextureID[i+1], 0);
    }
    //glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

glGenFramebuffers example c c++ java objc

Name

glGenFramebuffers — generate framebuffer object names

C Specification

void glGenFramebuffers(GLsizei  n,
GLuint * ids);

Parameters

n
Specifies the number of framebuffer object names to generate.
ids
Specifies an array in which the generated framebuffer object names are stored.

Description

glGenFramebuffers returns n framebuffer object names in ids. There is no guarantee that the names form a contiguous set of integers; however, it is guaranteed that none of the returned names was in use immediately before the call to glGenFramebuffers.
Framebuffer object names returned by a call to glGenFramebuffers are not returned by subsequent calls, unless they are first deleted with glDeleteFramebuffers.
The names returned in ids are marked as used, for the purposes of glGenFramebuffers only, but they acquire state and type only when they are first bound.

Errors

GL_INVALID_VALUE is generated if n is negative.

Copyright

Copyright © 2010 Khronos Group. This material may be distributed subject to the terms and conditions set forth in the Open Publication License, v 1.0, 8 June 1999. http://opencontent.org/openpub/.

Example of glGenFramebuffers

// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{
    fprintf(stdout, "FBO Draw Buffers Demo\n\n");


    // Make sure required functionality is available: cube maps, auto mip gen, etc.
    if (!GLEE_VERSION_1_4)
    {
        fprintf(stderr, "OpenGL 1.4 is not available!\n");
        Sleep(2000);
        exit(0);
    }


    if (GLEE_ARB_texture_non_power_of_two)
    {
        npotTexturesAvailable = GL_TRUE;
    }
    else
    {
        fprintf(stderr, "GL_ARB_texture_non_power_of_two extension is not available!\n");
        fprintf(stderr, "Framebuffer effects will be lower resolution (lower quality).\n\n");
    }


    if (!GLEE_EXT_framebuffer_object)
    {
        fprintf(stderr, "GL_EXT_framebuffer_object extension is unavailable!\n");
        Sleep(2000);
        exit(0);
    }


    // we'll use up to 4 render targets if they're available
    glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
    glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &maxColorAttachments);
    glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTexUnits);
    maxDrawBuffers = (maxDrawBuffers > maxColorAttachments) ? maxColorAttachments : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > (maxTexUnits-1)) ? (maxTexUnits-1) : maxDrawBuffers;
    maxDrawBuffers = (maxDrawBuffers > 4) ? 4 : maxDrawBuffers;
    if (((!GLEE_ARB_draw_buffers || !GLEE_ARB_fragment_shader || !GLEE_ARB_shader_objects) 
        && !GLEE_VERSION_2_0) || (maxDrawBuffers != 4))
    {
        fprintf(stderr, "Support for at least 4 draw buffers is unavailable!\n");
        Sleep(2000);
        exit(0);
    }


    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
    glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE_EXT, &maxRenderbufferSize);
    maxTexSize = (maxRenderbufferSize > maxTexSize) ? maxTexSize : maxRenderbufferSize;


    fprintf(stdout, "Controls:\n");
    fprintf(stdout, "\tRight-click for menu\n\n");
    fprintf(stdout, "\tx/X\t\tMove +/- in x direction\n");
    fprintf(stdout, "\ty/Y\t\tMove +/- in y direction\n");
    fprintf(stdout, "\tz/Z\t\tMove +/- in z direction\n\n");
    fprintf(stdout, "\td/D\t\tToggle use of draw buffers\n\n");
    fprintf(stdout, "\tq\t\tExit demo\n\n");
    
    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );


    // Hidden surface removal
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);


    // Set up some lighting state that never changes
    glShadeModel(GL_SMOOTH);
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
    glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
    glMaterialfv(GL_FRONT, GL_SPECULAR, specularLight);
    glMateriali(GL_FRONT, GL_SHININESS, 128);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_NORMALIZE);
    glEnable(GL_LIGHT0);


    // Set up textures & shaders
    SetupTextures();
    SetupShaders();


    // Set up some renderbuffer state
    glGenRenderbuffersEXT(1, &renderbufferID);
    glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbufferID);
    glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT32, fboWidth, fboHeight);


    // glGenFramebuffers(2, framebufferID);
    glGenFramebuffersEXT(2, framebufferID);
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[0]);
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, renderbufferID);
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, renderTextureID[0], 0);


    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID[1]);
    for (int i = 0; i < maxDrawBuffers; i++)
    {
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + i, GL_TEXTURE_2D, renderTextureID[i+1], 0);
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}