Texture create_texture_from_image(const ImagePtr& the_img, bool mipmap, bool compress, GLfloat anisotropic_filter_lvl) { Texture ret; if(!the_img){ return ret; } GLenum format = 0, internal_format = 0; switch(the_img->bytes_per_pixel) { #ifdef KINSKI_GLES case 1: internal_format = format = GL_LUMINANCE; break; case 2: internal_format = format = GL_LUMINANCE_ALPHA; break; case 3: internal_format = format = GL_RGB; // needs precompressed image and call to glCompressedTexImage2D // internal_format = compress ? GL_ETC1_RGB8_OES : GL_RGB; break; case 4: internal_format = format = GL_RGBA; default: break; #else case 1: format = GL_RED; internal_format = compress? GL_COMPRESSED_RED_RGTC1 : GL_RGBA; break; case 2: format = GL_RG; internal_format = compress? GL_COMPRESSED_RG_RGTC2 : GL_RGBA; break; case 3: format = GL_RGB; internal_format = compress? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_RGBA; break; case 4: format = GL_RGBA; internal_format = compress? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_RGBA; default: break; #endif } Texture::Format fmt; fmt.set_internal_format(internal_format); if(mipmap) { fmt.set_mipmapping(); fmt.set_min_filter(GL_LINEAR_MIPMAP_NEAREST); } uint8_t *data = the_img->data; #if !defined(KINSKI_GLES) gl::Buffer pixel_buf; pixel_buf.set_data(the_img->data, the_img->num_bytes()); pixel_buf.bind(GL_PIXEL_UNPACK_BUFFER); data = nullptr; #endif ret = Texture(data, format, the_img->width, the_img->height, fmt); ret.set_flipped(); KINSKI_CHECK_GL_ERRORS(); ret.set_anisotropic_filter(anisotropic_filter_lvl); return ret; }
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); }