void Renderer::RemovePrimitive( const Primitive::Ptr& primitive ) { std::vector<Primitive::Ptr>::iterator iter( std::find( m_primitives.begin(), m_primitives.end(), primitive ) ); if( iter != m_primitives.end() ) { m_primitives.erase( iter ); } InvalidateVBO(); }
void VertexBuffer::InnerDispose() { InvalidateVBO(); vector<VertexAttribute> attribs = GetAttributes(); for(unsigned int i = 0; i < attribs.size(); ++i) RemoveAttribute(attribs[i].name); SetNumVerts(0); }
void VertexBuffer::BuildVBO() { GLDEBUG(); vector<VertexAttribute> attribs = GetAttributes(); int total_size = GetVertexSize(); InvalidateVBO(); // just in case... // generate a vbo glGenBuffers(1, &vbo_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_id); // set the total size (based on the value we computed earlier) glBufferData(GL_ARRAY_BUFFER, total_size * num_verts, NULL, GL_STATIC_DRAW); int offset = 0; for(unsigned int i = 0; i < attribs.size(); ++i) { VertexAttribute attrib = attribs[i]; int attrib_size = 0; if(attrib.type == Float) attrib_size = sizeof(float) * attrib.n_per_vertex; if(attrib_size > 0) { if(attrib.type == Float) glBufferSubData(GL_ARRAY_BUFFER, offset * num_verts, attrib_size * num_verts, attribute_data[attrib.name].floats); offset += attrib_size; } } glBindBuffer(GL_ARRAY_BUFFER, 0); // don't leave hardware vbo on GLDEBUG(); }
void Renderer::AddPrimitive( const Primitive::Ptr& primitive ) { m_primitives.push_back( primitive ); InvalidateVBO(); }
sf::Vector2f Renderer::LoadImage( const sf::Image& image, sf::Color background_color_hint, sf::Color foreground_color_hint, bool force_insert ) { const sf::Uint8* pixels_ptr = image.getPixelsPtr(); if( !force_insert ) { std::map<const sf::Uint8*, sf::Vector2f>::iterator iter( m_atlas_offsets.find( pixels_ptr ) ); if( iter != m_atlas_offsets.end() ) { return iter->second; } } sf::Image preblended_image; preblended_image.create( image.getWidth(), image.getHeight(), image.getPixelsPtr() ); // If we get a proper background color hint and preblend is enabled, // precompute blended color with ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ). if( m_preblend ) { if( background_color_hint.a == 255 ) { float foreground_r_factor = 1.f; float foreground_g_factor = 1.f; float foreground_b_factor = 1.f; if( foreground_color_hint.a == 255 ) { foreground_r_factor = static_cast<float>( foreground_color_hint.r ) / 255.f; foreground_g_factor = static_cast<float>( foreground_color_hint.g ) / 255.f; foreground_b_factor = static_cast<float>( foreground_color_hint.b ) / 255.f; } std::size_t pixel_count = preblended_image.getWidth() * preblended_image.getHeight(); sf::Uint8* bytes = new sf::Uint8[pixel_count * 4]; memcpy( bytes, preblended_image.getPixelsPtr(), pixel_count * 4 ); for( std::size_t index = 0; index < pixel_count; ++index ) { // Alpha float alpha = static_cast<float>( bytes[index * 4 + 3] ) / 255.f; // Red bytes[index * 4 + 0] = static_cast<sf::Uint8>( static_cast<float>( bytes[index * 4 + 0] ) * foreground_r_factor * alpha + static_cast<float>( background_color_hint.r ) * ( 1.f - alpha ) ); // Green bytes[index * 4 + 1] = static_cast<sf::Uint8>( static_cast<float>( bytes[index * 4 + 1] ) * foreground_g_factor * alpha + static_cast<float>( background_color_hint.g ) * ( 1.f - alpha ) ); // Blue bytes[index * 4 + 2] = static_cast<sf::Uint8>( static_cast<float>( bytes[index * 4 + 2] ) * foreground_b_factor * alpha + static_cast<float>( background_color_hint.b ) * ( 1.f - alpha ) ); } preblended_image.create( preblended_image.getWidth(), preblended_image.getHeight(), bytes ); delete[] bytes; } else { m_preblend = false; #ifdef SFGUI_DEBUG std::cerr << "Detected alpha value " << static_cast<int>( background_color_hint.a ) << " in background color hint. Disabling preblend.\n"; #endif } } const sf::Uint8* bytes = preblended_image.getPixelsPtr(); std::size_t byte_count = preblended_image.getWidth() * preblended_image.getHeight() * 4; // Disable this check for now. static sf::Uint8 alpha_threshold = 255; for ( ; byte_count; --byte_count ) { // Check if the image makes intentional use of the alpha channel. if( m_depth_clear_strategy && !( byte_count % 4 ) && ( bytes[ byte_count - 1 ] > alpha_threshold ) && ( bytes[ byte_count - 1 ] < 255 ) ) { #ifdef SFGUI_DEBUG std::cerr << "Detected alpha value " << static_cast<int>( bytes[ byte_count - 1 ] ) << " in texture, disabling depth test.\n"; #endif m_depth_clear_strategy = NO_DEPTH; } } // Image needs to be loaded into atlas. sf::Image old_image = m_texture_atlas.copyToImage(); sf::Image new_image; // We insert padding between atlas elements to prevent // texture filtering from screwing up our images. // If 1 pixel isn't enough, increase. const static unsigned int padding = 1; new_image.create( std::max( old_image.getWidth(), preblended_image.getWidth() ), old_image.getHeight() + preblended_image.getHeight() + padding, sf::Color::White ); new_image.copy( old_image, 0, 0 ); new_image.copy( preblended_image, 0, old_image.getHeight() + padding ); m_texture_atlas.loadFromImage( new_image ); sf::Vector2f offset = sf::Vector2f( 0.f, static_cast<float>( old_image.getHeight() + padding ) ); InvalidateVBO(); if( !force_insert ) { m_atlas_offsets[pixels_ptr] = offset; } return offset; }