Пример #1
0
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);
}