SFML community forums
Help => Graphics => Topic started by: LakySimi1 on April 15, 2022, 09:49:58 am
-
Hi everyone!
I'm making a game and i'm questioning if my drawing method is right enough or can be improved.
I really like to draw a pixel at a time.
I pick the color of the pixel i want to draw from and image and than i transfer the RGB data on a 'pixels' array. Then i transfer this 'pixels' array into a Texture, then it into a Sprite and then i display the final Window, this last part (last 3 rows) are a mistery to me, i've seen it online ^^
CODE
int main()
{
//CREATING WINDOW
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "GAME");
window.create(sf::VideoMode(WindowHeight, WindowWidth), "GAME", sf::Style::Fullscreen);
window.setFramerateLimit(30); //i use this to impose the game speed
//SEEN THIS ONLINE: i draw 'WindowTexture' in window to show render the game
sf::Texture WindowTexture;
WindowTexture.create(width, height);
sf::Sprite WindowSprite(WindowTexture);
sf::Image GameTextures; //Textures of the game
sf::Uint8* pixels = new sf::Uint8[(WindowHeigh * WindowWidth * 4]; //All pixels of the window (4 =
RGBA); This is a pseudo-2D array
for (int i = 0; i < WindowHeigh*WindowWidth*4; i+=4){pixels[i+3] = 255;} //SETTING ALPHA TO 255
sf::Color SFcolor; //"Brush" used for draw a pixel
//LOAD GAME TEXTURES
GameTextures.loadFromFile("GameTextures.bmp"); //Pseudo-large image with all game textures (walls,
floors, ceilings,..)
//GAME LOGIC
...
///RENDERING///
while (not every 'pixels' pixel is drawn)
//SCROLLING TROUGH EVERY PIXEL AND COLORING THEM
{
//GET TARGETED PIXEL COLOR
SFcolor = GameTextures.getPixel (xCoordinate, yCoordinate); //x and y is the coordinate of the big
GameTextures image with all textures (walls, floors,..)
//PAINTING THAT COLOR IN 'pixels' ARRAY
pixels[(Y*WindowWidth + X)*4] = Sfcolor.r; //'Y*WindowWidth' is for the Pseudo-2D array
pixels[(Y*WindowWidth + X)*4 +1] = SFcolor.g;
pixels[(Y*WindowWidth + X)*4 +2] = SFcolor.b;
}
//DRAW ON SCREEN
WindowTexture.update(pixels);
window.draw(WindowSprite);
window.display();
}
EDIT
What's 'better': use a pixel array and transfer to a Texture OR using an Image and then transfer it to a Texture?
I provide two full code which show that the PixelArray solution is faster but maybe is also stressful for the PC?
//PIXEL ARRAY
#include <SFML/Graphics.hpp>
int main()
{
const int H = 720;
const int W = 1280;
sf::RenderWindow window(sf::VideoMode(W, 800), "SFML works!");
sf::RectangleShape shape(sf::Vector2f(W, 800));
shape.setFillColor(sf::Color::Green);
window.setFramerateLimit(0);
sf::Texture texture;
texture.create(W, H);
sf::Sprite sprite(texture);
sf::Uint8* pixels = new sf::Uint8[W * 800 * 4];
for (int ir = 0; ir < W*H * 4; ir++)
pixels[ir] = 255;
int ix = 0;
while (window.isOpen())
{
for (int ir = 0; ir < H; ir++)
{
for (int ic = 0; ic < W; ic++)
{
pixels[(ir * W + ic) * 4] = ir%255+ix; //red
pixels[(ir * W + ic) * 4 + 1] = ic%255-ix; //green
pixels[(ir * W + ic) * 4 + 2] = ix; //blue
}
}
ix++;
texture.update(pixels);
window.draw(sprite);
window.display();
}
return 0;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//IMAGE
#include <SFML/Graphics.hpp>
#include <stdlib.h>
int main()
{
const int H = 720;
const int W = 1280;
sf::RenderWindow window(sf::VideoMode(W, H), "SFML works!");
sf::RectangleShape shape(sf::Vector2f(W, H));
shape.setFillColor(sf::Color::Green);
window.setFramerateLimit(0);
sf::Texture texture; texture.create(W, H);
sf::Image image; image.create(W, H);
sf::Sprite sprite(texture);
int ix = 0;
while (window.isOpen())
{
for (int ir = 0; ir < H; ir++)
{
for (int ic = 0; ic < W; ic++)
{
image.setPixel(ic, ir, sf::Color(ir%255+ix, ic%255-ix, ix));
}
}
ix++;
texture.update(image);
sprite.setTexture(texture);
window.draw(sprite);
window.display();
}
return 0;
}
-
Another approach is to use graphical objects rather than updating a texture every frame.
For example, you can simply draw a vertex for each pixel you want to colour. All of them if you wish. To do this, you could use a vector of vertices - one for each pixel - and either draw them all each frame, or draw them all to a render texture and then draw that as a sprite/quad; this reduces the number of vertices needed to draw if they don't constantly change.
Another example is to to cover the window with a tile-like object that you can colour each tile individually. If those tiles are pixel sized, you have your pixel control. If they are larger, than the "resolution" appears lower. e.g. if the tiles are 2x2, the "resolution" could seem slightly pixelated but if they are 16x16, they definitely will.
If you decide to try out the latter suggest I gave, you could also try out Selba Ward (https://github.com/Hapaxia/SelbaWard/wiki)'s Pixel Display (https://github.com/Hapaxia/SelbaWard/wiki/Pixel-Display), designed to simplify this sort of thing. It's technically designed for lower resolution/colour-paletted display emulation but it's up to you whether or not it's a good approach for actual pixel-by-pixel manipulation.
-
Another approach is to use graphical objects rather than updating a texture every frame.
For example, you can simply draw a vertex for each pixel you want to colour. All of them if you wish. To do this, you could use a vector of vertices - one for each pixel - and either draw them all each frame, or draw them all to a render texture and then draw that as a sprite/quad; this reduces the number of vertices needed to draw if they don't constantly change.
Another example is to to cover the window with a tile-like object that you can colour each tile individually. If those tiles are pixel sized, you have your pixel control. If they are larger, than the "resolution" appears lower. e.g. if the tiles are 2x2, the "resolution" could seem slightly pixelated but if they are 16x16, they definitely will.
If you decide to try out the latter suggest I gave, you could also try out Selba Ward (https://github.com/Hapaxia/SelbaWard/wiki)'s Pixel Display (https://github.com/Hapaxia/SelbaWard/wiki/Pixel-Display), designed to simplify this sort of thing. It's technically designed for lower resolution/colour-paletted display emulation but it's up to you whether or not it's a good approach for actual pixel-by-pixel manipulation.
But what do you think about my method? Is it enough right? Is somehow wrong and sloppy or inefficient (slow)?
I'm intersted in both of your methods, do they speed up a little the rendering confronted to mine?
If you can please provide a simple code to test them it would be great!
Uh you've made your own function library, nice!