bool TScene::CreateFBO(const char* name, int resX, int resY, GLuint tex, int fbo_mode)
{
    GLuint depth, buffer;

    if( fbo_mode > NO_DEPTH )
    {
        //create renderbuffers
        glGenRenderbuffers(1, &depth);
        glBindRenderbuffer(GL_RENDERBUFFER, depth);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, resX, resY);
    }

    glGenFramebuffers(1, &buffer);
    glBindFramebuffer(GL_FRAMEBUFFER, buffer);

    //attach texture to the frame buffer
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
    if( fbo_mode > NO_DEPTH )
        glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, depth);

    //check FBO creation
    if(!CheckFBO())
    {
        ShowMessage("ERROR: FBO creation failed!",false);
        return false;
    }

    m_fbos[name] = buffer;

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    return true;
}
Beispiel #2
0
void
OpenGL::SetupContext()
{
#if defined(HAVE_EGL) && defined(ANDROID)
  egl = EGLInit();
#endif

  texture_non_power_of_two = SupportsNonPowerOfTwoTextures();

#ifdef ANDROID
  native_view->SetTexturePowerOfTwo(texture_non_power_of_two);

  vertex_buffer_object = EnableVBO();
#endif

  frame_buffer_object = CheckFBO() && FBO::Initialise();
  if (frame_buffer_object) {
    render_buffer_depth_stencil = CheckDepthStencil();

    render_buffer_stencil = CheckStencil();
    if (!render_buffer_stencil)
      /* fall back to a packed depth+stencil format */
      render_buffer_stencil = render_buffer_depth_stencil;
  }

  glDisable(GL_DEPTH_TEST);
  glDisable(GL_DITHER);
  glDisable(GL_LIGHTING);

  glEnableClientState(GL_VERTEX_ARRAY);

  InitShapes();
}
Beispiel #3
0
void NLightSystem::Draw()
{
    CheckFBO();
    if (Shader == NULL)
    {
        glEnableClientState(GL_VERTEX_ARRAY);
        glBindBuffer(GL_ARRAY_BUFFER,VertexBuffers[0]);
        glVertexPointer(2,GL_FLOAT,0,NULL);

        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glBindBuffer(GL_ARRAY_BUFFER,VertexBuffers[1]);
        glTexCoordPointer(2,GL_FLOAT,0,NULL);

        glBindTexture(GL_TEXTURE_2D,FrameBufferTexture);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_DST_COLOR, GL_ZERO);
        glDrawArrays(GL_QUADS,0,Verts.size());
        glDisable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        return;
    }
    glEnable(GL_TEXTURE_2D);
    glUseProgram(Shader->GetID());
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D,FrameBufferTexture);
    glUniform1i(TextureLoc,0);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER,VertexBuffers[0]);
    glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,NULL);
    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER,VertexBuffers[1]);
    glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,0,NULL);

    glEnable(GL_BLEND);
    glBlendFunc(GL_DST_COLOR, GL_ZERO);
    glEnable(GL_TEXTURE_2D);
    glDrawArrays(GL_QUADS,0,Verts.size());
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glUseProgram(0);
}
Beispiel #4
0
void
OpenGL::SetupContext()
{
#if defined(HAVE_DYNAMIC_EGL)
  egl = EGLInit();
#endif

  texture_non_power_of_two = SupportsNonPowerOfTwoTextures();

#ifdef HAVE_OES_DRAW_TEXTURE
  oes_draw_texture = CheckOESDrawTexture();
#endif

#ifdef ANDROID
  native_view->SetTexturePowerOfTwo(texture_non_power_of_two);

  vertex_buffer_object = EnableVBO();
#endif

#ifdef HAVE_OES_MAPBUFFER
  mapbuffer = IsExtensionSupported("GL_OES_mapbuffer");
#endif

#ifdef HAVE_DYNAMIC_MAPBUFFER
  if (mapbuffer) {
    GLExt::map_buffer = (PFNGLMAPBUFFEROESPROC)
      eglGetProcAddress("glMapBufferOES");
    GLExt::unmap_buffer = (PFNGLUNMAPBUFFEROESPROC)
      eglGetProcAddress("glUnmapBufferOES");
    if (GLExt::map_buffer == nullptr || GLExt::unmap_buffer == nullptr)
      mapbuffer = false;
  }
#endif

#ifdef HAVE_DYNAMIC_MULTI_DRAW_ARRAYS
  if (IsExtensionSupported("GL_EXT_multi_draw_arrays")) {
    GLExt::multi_draw_arrays = (PFNGLMULTIDRAWARRAYSEXTPROC)
      dlsym(RTLD_DEFAULT, "glMultiDrawArraysEXT");
    GLExt::multi_draw_elements = (PFNGLMULTIDRAWELEMENTSEXTPROC)
      dlsym(RTLD_DEFAULT, "glMultiDrawElementsEXT");
  } else {
    GLExt::multi_draw_arrays = nullptr;
    GLExt::multi_draw_elements = nullptr;
  }
#endif

  frame_buffer_object = CheckFBO() && FBO::Initialise();
  if (frame_buffer_object) {
    render_buffer_depth_stencil = CheckDepthStencil();

    render_buffer_stencil = CheckStencil();
    if (!render_buffer_stencil)
      /* fall back to a packed depth+stencil format */
      render_buffer_stencil = render_buffer_depth_stencil;
  }

  GLfloat lineWidthRange[2] = {0.0f, 0.0f};
  glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange);
  max_line_width = lineWidthRange[1];

  glDisable(GL_DEPTH_TEST);
  glDisable(GL_DITHER);
#ifndef HAVE_GLES2
  glDisable(GL_LIGHTING);
#endif

#ifndef USE_GLSL
  glEnableClientState(GL_VERTEX_ARRAY);
#endif

  InitShapes();

#ifdef USE_GLSL
  InitShaders();
#endif

#ifndef HAVE_GLES
  ::glGetIntegerv(GL_MAX_ATTRIB_STACK_DEPTH, &max_attrib_stack_depth);
#endif
}
Beispiel #5
0
vsSurface::vsSurface( const Settings& settings, bool depthOnly, bool multisample ):
	m_width(settings.width),
	m_height(settings.height),
	m_texture(0),
	m_textureCount(settings.buffers),
	m_depth(0),
	m_stencil(0),
	m_fbo(0),
	m_isRenderbuffer(false)
{
	CheckGLError("vsSurface");

	GLint maxSamples = 0;
	if ( multisample )
		glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);

	GLenum internalFormat = GL_RGBA8;
	GLenum pixelFormat = GL_RGBA;
	GLenum type = GL_UNSIGNED_INT_8_8_8_8_REV;
	GLenum filter = settings.linear ? GL_LINEAR : GL_NEAREST;

	vsAssert( !( multisample && settings.mipMaps ), "Can't do both multisample and mipmaps!" );
	glActiveTexture(GL_TEXTURE0);

	// create FBO
	glGenFramebuffers(1, &m_fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);

	m_texture = new GLuint[m_textureCount];

	if ( depthOnly )
	{
		glDrawBuffer(GL_NONE);
		glReadBuffer(GL_NONE);
	}
	else
	{
		for ( int i = 0; i < m_textureCount; i++ )
		{
			if (multisample)
			{
				glGenRenderbuffers(1, &m_texture[i]);
				glBindRenderbuffer( GL_RENDERBUFFER, m_texture[i] );
				glRenderbufferStorageMultisample( GL_RENDERBUFFER, maxSamples, pixelFormat, m_width, m_height );
				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, m_texture[i]);
				m_isRenderbuffer = true;
			}
			else
			{
				glGenTextures(1, &m_texture[i]);
				glBindTexture(GL_TEXTURE_2D, m_texture[i]);
				m_isRenderbuffer = false;
				glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_width, m_height, 0, pixelFormat, type, 0);
				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_TEXTURE_2D, m_texture[i], 0);
				if ( settings.mipMaps )
				{
					glGenerateMipmap(GL_TEXTURE_2D);
				}
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
				glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
				glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
				glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
				glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f );
				glBindTexture(GL_TEXTURE_2D, 0);
			}
		}
	}

	if (settings.depth || depthOnly)
	{
		if ( multisample )
		{
			glGenRenderbuffers(1, &m_depth);
			glBindRenderbuffer(GL_RENDERBUFFER, m_depth);
			if ( settings.stencil )
			{
				glRenderbufferStorageMultisample( GL_RENDERBUFFER, maxSamples, GL_DEPTH24_STENCIL8, m_width, m_height );
				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depth);
			}
			else
			{
				glRenderbufferStorageMultisample( GL_RENDERBUFFER, maxSamples, GL_DEPTH_COMPONENT24, m_width, m_height );
			}
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth);
		}
		else
		{
			glGenTextures(1, &m_depth);
			glBindTexture(GL_TEXTURE_2D, m_depth);
			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			//glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
			//glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
			//glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);

			//if ( stencil )
			//{
			//glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
			//}
			//else
			{
				glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_width, m_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
			}
			glBindTexture(GL_TEXTURE_2D, 0);
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depth, 0);
		}
	}

	CheckFBO();
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	CheckGLError("vsSurface");
}
/**
****************************************************************************************************
@brief Create render target using framebuffer and attached texture
@param resX X-size of framebuffer texture
@param resY Y-size of framebuffer texture
@param tex_format OpenGL texture format (can be GL_RGBA, GL_RGBA16F or GL_RGBA32F)
@param tex_type internal data format (can be GL_UNSIGNED_BYTE or GL_FLOAT)
@param normal_buffer should we create another render target for normal and depth buffer?
***************************************************************************************************/
void TScene::CreateHDRRenderTarget(int resX, int resY, GLint tex_format, GLenum tex_type, bool normal_buffer)
{
    //if no resolution given, use current scene resolution
    if(resX == -1 || resY == -1)
    {
        resX = m_resx;
        resY = m_resy;
    }
    //force use of normal buffer if SSAO or IPSM is enabled
    if(m_useSSAO || m_dpshadow_method >= IPSM) 
        normal_buffer = true;
    m_useNormalBuffer = normal_buffer;

    //save render target size
    m_RT_resX = resX;
    m_RT_resY = resY;

    //create texture - for original image
    CreateDataTexture("render_texture", resX, resY, tex_format, tex_type, GL_TEXTURE_2D);
    //create texture - for bloom effect
    CreateDataTexture("bloom_texture", resX, resY, tex_format, tex_type, GL_TEXTURE_2D);
    //create texture - for blur
    CreateDataTexture("blur_texture", resX, resY, tex_format, tex_type, GL_TEXTURE_2D);
    //create texture - for store normal values
    if(m_useNormalBuffer)
        CreateDataTexture("normal_texture", resX, resY, tex_format, tex_type, GL_TEXTURE_2D);

    //create renderbuffers
    glGenRenderbuffers(1, &m_r_buffer_depth);
    glBindRenderbuffer(GL_RENDERBUFFER, m_r_buffer_depth);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT,resX, resY);

    //if MSAA enabled, create also multisampled framebuffer (only when platform supports it)
    if(m_msamples > 1 && GLEW_EXT_framebuffer_multisample)
    {
        //Create multisampled color renderbuffer
        glGenRenderbuffers(1, &m_r_buffer_colorMSAA);
        glBindRenderbuffer(GL_RENDERBUFFER, m_r_buffer_colorMSAA);
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msamples, tex_format, resX, resY);

        //Create multisampled normal renderbuffer
        if(m_useNormalBuffer)
        {
            glGenRenderbuffers(1, &m_r_buffer_normalMSAA);
            glBindRenderbuffer(GL_RENDERBUFFER, m_r_buffer_normalMSAA);
            glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msamples, tex_format, resX, resY);
        }

        //Create multisampled depth renderbuffer
        glGenRenderbuffers(1, &m_r_buffer_depthMSAA);
        glBindRenderbuffer(GL_RENDERBUFFER, m_r_buffer_depthMSAA);
        glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msamples, GL_DEPTH_COMPONENT,resX, resY);

        //Attach to multisampled framebuffer
        glGenFramebuffers(1, &m_f_bufferMSAA);
        glBindFramebuffer(GL_FRAMEBUFFER, m_f_bufferMSAA);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_r_buffer_colorMSAA);
        if(m_useNormalBuffer)
            glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, m_r_buffer_normalMSAA);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_r_buffer_depthMSAA);

        //check FBO creation
        if(!CheckFBO())
        {
            cout<<"WARNING: Multisampled FBO creation failed, falling back to regular FBO.\n";
            m_msamples = 1;
        }
    }

    //Finally, create framebuffer
    glGenFramebuffers(1, &m_f_buffer);
    glBindFramebuffer(GL_FRAMEBUFFER, m_f_buffer);

    //attach texture to the frame buffer
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, m_tex_cache["render_texture"], 0);
    //attach also normal texture if desired (e.g. for SSAO)
    if(m_useNormalBuffer)
        glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT1,GL_TEXTURE_2D, m_tex_cache["normal_texture"], 0);
    //attach render buffers
    glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER, m_r_buffer_depth);


    //check FBO creation
    if(!CheckFBO())
    {
        m_useHDR = m_useSSAO = m_useNormalBuffer = false;
        throw ERR;
    }

    // Go back to regular frame buffer rendering
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    //update load list
    UpdateLoadList(34);

    //HDR passes - render to texture, bloom effect, SSAO and tonemapping
    AddMaterial("mat_bloom_hdr_ssao",white,white,white,0.0,0.0,0.0,SCREEN_SPACE);
    
    //various defines depending if we want HDR only, SSAO only or both together
    string defines = "#define BLOOM\n";
    if(m_useSSAO)       //SSAO only
    {
        defines = "#define SSAO\n";        
        AddTexture("mat_bloom_hdr_ssao","normal_texture",RENDER_TEXTURE);   //add normal texture
        if(m_useHDR)    //HDR + SSAO
            defines = "#define BLOOM\n#define SSAO\n";
    }
    AddTexture("mat_bloom_hdr_ssao","render_texture",RENDER_TEXTURE);
    AddTexture("mat_bloom_hdr_ssao","data/tex/random.tga");
    CustomShader("mat_bloom_hdr_ssao","data/shaders/quad.vert", "data/shaders/bloom_ssao.frag", " ",defines.c_str());

    //tonemapping
    AddMaterial("mat_tonemap",white,white,white,0.0,0.0,0.0,SCREEN_SPACE);
    AddTexture("mat_tonemap","render_texture",RENDER_TEXTURE);
    AddTexture("mat_tonemap","blur_texture",RENDER_TEXTURE);
    if(m_useNormalBuffer)
        AddTexture("mat_tonemap","normal_texture",RENDER_TEXTURE);
    CustomShader("mat_tonemap","data/shaders/quad.vert","data/shaders/tonemap.frag");

    //blur
    AddMaterial("mat_blur_horiz",white,white,white,0.0,0.0,0.0,SCREEN_SPACE);
    AddTexture("mat_blur_horiz","bloom_texture",RENDER_TEXTURE);
    CustomShader("mat_blur_horiz","data/shaders/quad.vert","data/shaders/blur.frag", " ","#define HORIZONTAL\n");
    SetUniform("mat_blur_horiz", "texsize", glm::ivec2(resX, resY));       //send texture size info

    AddMaterial("mat_blur_vert",white,white,white,0.0,0.0,0.0,SCREEN_SPACE);
    AddTexture("mat_blur_vert","bloom_texture",RENDER_TEXTURE);
    CustomShader("mat_blur_vert","data/shaders/quad.vert","data/shaders/blur.frag", " ", "#define VERTICAL\n");
    SetUniform("mat_blur_vert", "texsize", glm::ivec2(resX, resY));       //send texture size info
}
Beispiel #7
0
	void CreateBuffers(int screen_width, int screen_height) {
		width = screen_width;
		height = screen_height;
		glGenFramebuffersEXT(1, &halfsizeFb);
		glGenTextures(1, &halfsizeTex);
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, halfsizeFb);
		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, halfsizeTex);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB, width>>1, height>>1, 0, GL_RGB, GL_HALF_FLOAT_ARB, NULL);
		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, halfsizeTex, 0);
		if (!CheckFBO()) {
			DeleteBuffers();
			return;
		}
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

		glGenFramebuffersEXT(1, &luminanceFb);
		glGenTextures(1, &luminanceTex);
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, luminanceFb);
		glBindTexture(GL_TEXTURE_2D, luminanceTex);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F_ARB, 128, 128, 0, GL_RGB, GL_FLOAT, NULL);
		glGenerateMipmapEXT(GL_TEXTURE_2D);
		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, luminanceTex, 0);
		if (!CheckFBO()) {
			DeleteBuffers();
			return;
		}
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
		glError();

		glGenFramebuffersEXT(1, &bloomFb1);
		glGenTextures(1, &bloomTex1);
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bloomFb1);
		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, bloomTex1);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB, width>>2, height>>2, 0, GL_RGB, GL_HALF_FLOAT_ARB, NULL);
		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, bloomTex1, 0);
		if (!CheckFBO()) {
			DeleteBuffers();
			return;
		}
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

		glGenFramebuffersEXT(1, &bloomFb2);
		glGenTextures(1, &bloomTex2);
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, bloomFb2);
		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, bloomTex2);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB, width>>2, height>>2, 0, GL_RGB, GL_HALF_FLOAT_ARB, NULL);
		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, bloomTex2, 0);
		if (!CheckFBO()) {
			DeleteBuffers();
			return;
		}
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

		glGenFramebuffersEXT(1, &fb);
		glGenTextures(1, &tex);
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB16F_ARB, width, height, 0, GL_RGB, GL_HALF_FLOAT_ARB, NULL);
		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
		glError();
		
		glGenRenderbuffersEXT(1, &depthbuffer);
		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthbuffer);
		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthbuffer);
		glError();
		if (!CheckFBO()) {
			DeleteBuffers();
			return;
		}

		postprocessBloom1Downsample = new PostprocessDownsampleShader("postprocessBloom1Downsample", "#extension GL_ARB_texture_rectangle : enable\n");
		postprocessBloom2Downsample = new PostprocessShader("postprocessBloom2Downsample", "#extension GL_ARB_texture_rectangle : enable\n");
		postprocessBloom3VBlur = new PostprocessShader("postprocessBloom3VBlur");
		postprocessBloom4HBlur = new PostprocessShader("postprocessBloom4HBlur");
		postprocessCompose = new PostprocessComposeShader("postprocessCompose", "#extension GL_ARB_texture_rectangle : enable\n");
		postprocessLuminance = new PostprocessShader("postprocessLuminance", "#extension GL_ARB_texture_rectangle : enable\n");

		glError();
	}