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; }
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(); }
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); }
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 }
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 }
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(); }