Hello,
Recently i was making something using sfml, and i had to draw lots ( 1000 + ) of little shapes ( 1 - 5 pixels).
When i tried to do this with sprites or lines of length 1, it was super laggy.
After a bit of searching on the forums, I found out that the best way to do something like this, is to render them to a pixelarray, and then loading the complete array to the video memory at once. It was indeed much faster.
So I wrote a simple class which could render induvidual pixels to a buffer. A bit later i added lines, then circles and rectangles.
I noticed quite a lot of people need something like this, so I'm releasing my class to the public
I'm not claiming this is the best/fastest way of doing this, neither is this code very optimized, but nonetheless i think a lot of people will find this useful.
If you have suggestions, or found a bug, feel free to tell me !
NOTE: the buffer is meant to cover the whole screen !
If you want to draw anything else, first draw this, then draw your sprites or whatever after it.
usage example :
//initialization
sf::RenderWindow Window(sf::VideoMode(WIDTH, HEIGHT, 32), "Example");
CRenderer Renderer( WIDTH, HEIGHT );
//-------------------------------------
//inside renderer loop
//clear window
Window.Clear();
//clear buffer (optional: choose a color )
Renderer.Clear();
//draw everything you want
Renderer.DrawCircle( 100, 150, 10, sf::Color( 255 ), 0, 0 ), true );
Renderer.DrawPixel( 100, 150, sf::Color( 255 ), 0, 0 ), true );
//draw the buffer to the screen
Renderer.DrawToWindow( Window );
//draw everything else: sprites, images, text, ...
//display window
Window.Display();
full class:
class CRenderer {
public:
sf::Uint8* pixelArray;
int width;
int height;
sf::Image ScreenImage;
CRenderer( int _width, int _height)
{
width = _width;
height = _height;
pixelArray = new sf::Uint8[ width * height * 4 ];
for( int i = 0 ; i < width * height * 4 ; i++ )
{
pixelArray[i] = 0x00;
}
}
~CRenderer()
{
delete[] pixelArray;
}
void DrawToWindow( sf::RenderWindow& Screen, bool smooth = false ){
ScreenImage.LoadFromPixels( width , height, pixelArray );
ScreenImage.SetSmooth( smooth );
sf::Sprite ScreenSprite( ScreenImage );
Screen.Draw( ScreenSprite );
}
void DrawPixel( int x, int y, sf::Color color ){
if( ( x >= 0 ) && ( x < width ) && ( y >= 0 ) && ( y < height ) )
{
pixelArray[ (y * width + x)*4 ] = color.r;
pixelArray[ (y * width + x)*4 + 1 ] = color.g;
pixelArray[ (y * width + x)*4 + 2 ] = color.b;
pixelArray[ (y * width + x)*4 + 3 ] = color.a;
}
}
void DrawLine( int x0, int y0, int x1, int y1, sf::Color color ){
int dx = abs( x1 - x0 );
int dy = abs( y1 - y0 );
int sx = 0;
int sy = 0;
if( x0 < x1 ) { sx = 1; }else{ sx = -1; }
if( y0 < y1 ) { sy = 1; }else{ sy = -1; }
int error = dx - dy;
while(1)
{
DrawPixel(x0,y0, color);
if( x0 == x1 && y0 == y1){ break; }
int e2 = 2*error;
if( e2 > -dy ){ error = error - dy; x0 = x0 + sx; }
if( e2 < dx){ error = error + dx; y0 = y0 + sy; }
}
}
void DrawCircle( int x0, int y0, int r, sf::Color color, bool filled = true )
{
int f = 1 - r;
int ddF_x = 1;
int ddF_y = -2 * r;
int x = 0;
int y = r;
DrawPixel(x0, y0 + r, color);
DrawPixel(x0, y0 - r, color);
if( filled )
{
DrawLine(x0 - r, y0, x0 + r, y0, color);
}
else
{
DrawPixel(x0 + r, y0, color);
DrawPixel(x0 - r, y0, color);
}
while(x < y)
{
if(f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if( filled )
{
DrawLine(x0 + x, y0 + y, x0 - x, y0 + y, color);
DrawLine(x0 + y, y0 + x, x0 - y, y0 + x, color);
DrawLine(x0 + x, y0 - y, x0 - x, y0 - y, color);
DrawLine(x0 + y, y0 - x, x0 - y, y0 - x, color);
}
else
{
DrawPixel(x0 + x, y0 + y, color);
DrawPixel(x0 - x, y0 + y, color);
DrawPixel(x0 + x, y0 - y, color);
DrawPixel(x0 - x, y0 - y, color);
DrawPixel(x0 + y, y0 + x, color);
DrawPixel(x0 - y, y0 + x, color);
DrawPixel(x0 + y, y0 - x, color);
DrawPixel(x0 - y, y0 - x, color);
}
}
}
void DrawRectangle( int x1, int y1, int x2, int y2, sf::Color color, bool filled = true ){
if( x1 > x2 ){
int temp = x1;
x1 = x2;
x2 = temp;
}
if( y1 > y2 ){
int temp = y1;
y1 = y2;
y2 = temp;
}
for( int x = x1 ; x < x2 ; x++ )
{
for( int y = y1 ; y < y2 ; y++ )
{
DrawPixel( x, y, color );
}
}
}
void Clear( sf::Color color ){
for( int i = 0 ; i < width * height ; i++ )
{
pixelArray[ i * 4 ] = color.r;
pixelArray[ i * 4 + 1 ] = color.g;
pixelArray[ i * 4 + 2 ] = color.b;
pixelArray[ i * 4 + 3 ] = color.a;
}
}
};