void Fbo::init() { bool useAA = m_impl->m_format.m_num_samples > 0; // allocate the framebuffer itself glGenFramebuffers(1, &m_impl->m_id); glBindFramebuffer(GL_FRAMEBUFFER, m_impl->m_id); Texture::Format textureFormat; textureFormat.set_target(target()); auto col_fmt = format().color_internal_format(); textureFormat.set_internal_format(col_fmt); #if !defined(KINSKI_GLES) GLint float_types[] = {GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F}; GLint one_comp_types[] = {GL_RED, GL_GREEN, GL_BLUE, GL_R32F}; if(contains(float_types, col_fmt)){ textureFormat.set_data_type(GL_FLOAT); } #endif textureFormat.set_wrap(m_impl->m_format.m_wrap_s, m_impl->m_format.m_wrap_t); textureFormat.set_min_filter(m_impl->m_format.m_min_filter); textureFormat.set_mag_filter(m_impl->m_format.m_mag_filter); textureFormat.set_mipmapping(format().has_mipmapping()); // allocate the color buffers for(int c = 0; c < m_impl->m_format.m_num_color_buffers; ++c) { auto tex = Texture(m_impl->m_width, m_impl->m_height, textureFormat); #if !defined(KINSKI_GLES) if(contains(one_comp_types, col_fmt)){ tex.set_swizzle(GL_RED, GL_RED, GL_RED, GL_ONE); } #endif m_impl->m_color_textures.push_back(tex); } #if !defined(KINSKI_GLES) if(m_impl->m_format.m_num_color_buffers == 0) { // no color glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); } #endif if(useAA){ useAA = init_multisample(); } if(!useAA) { // if we don't need any variety of multisampling or it failed to initialize // attach all the textures to the framebuffer vector<GLenum> drawBuffers; for(size_t c = 0; c < m_impl->m_color_textures.size(); ++c) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + c, target(), m_impl->m_color_textures[c].id(), 0); drawBuffers.push_back(GL_COLOR_ATTACHMENT0 + c); } #if ! defined(KINSKI_GLES) if(!drawBuffers.empty()){ glDrawBuffers(drawBuffers.size(), &drawBuffers[0]); } #endif // allocate and attach depth texture if(m_impl->m_format.m_depth_buffer) { if(m_impl->m_format.m_depth_buffer_texture) { #if ! defined(KINSKI_GLES) GLuint depthTextureId; glGenTextures(1, &depthTextureId); glBindTexture(target(), depthTextureId); glTexImage2D(target(), 0, format().depth_internal_format(), m_impl->m_width, m_impl->m_height, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, nullptr); // glTexImage2D(target(), 0, getFormat().getDepthInternalFormat(), // m_impl->m_width, m_impl->m_height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); glTexParameteri(target(), GL_TEXTURE_MIN_FILTER, m_impl->m_format.m_min_filter); glTexParameteri(target(), GL_TEXTURE_MAG_FILTER, m_impl->m_format.m_mag_filter); glTexParameteri(target(), GL_TEXTURE_WRAP_S, m_impl->m_format.m_wrap_s); glTexParameteri(target(), GL_TEXTURE_WRAP_T, m_impl->m_format.m_wrap_t); m_impl->m_depth_texture = Texture(target(), depthTextureId, m_impl->m_width, m_impl->m_height, false); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target(), m_impl->m_depth_texture.id(), 0); if(m_impl->m_format.has_stencil_buffer()) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, target(), m_impl->m_depth_texture.id(), 0); } #endif } // implement depth buffer as RenderBuffer else if(m_impl->m_format.m_depth_buffer) { m_impl->m_depthRenderbuffer = Renderbuffer(m_impl->m_width, m_impl->m_height, m_impl->m_format.depth_internal_format()); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_impl->m_depthRenderbuffer.id()); if(m_impl->m_format.has_stencil_buffer()) { glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_impl->m_depthRenderbuffer.id()); } } } FboExceptionInvalidSpecification exc; // failed creation; throw if(!check_status(&exc)) { throw exc; } } m_impl->m_needs_resolve = false; m_impl->m_needs_mipmap_update = false; glBindFramebuffer(GL_FRAMEBUFFER, 0); }