SFML Drawing Pixel Array

user2779815 picture user2779815 · Sep 14, 2013 · Viewed 12.9k times · Source

I found this (http://lodev.org/cgtutor/raycasting.html) tutorial on the Internet and was interested and wanted to make my own. I wanted to do it in SFML though, and I wanted to extend it, and make a 3D version, so there could be different levels the player can walk on. Thus, you would need 1 ray for every pixel, and thus each pixel would have to be drawn independently. I found this (http://www.sfml-dev.org/tutorials/2.1/graphics-vertex-array.php) tutorial, and it seemed easy enough to have the array be of individual vertices. To start, I figured the best thing to do would be to create a class that could read the pixels returned by the rays, and draw them to the screen. I used the VertexArray, but things were not working for some reason. I tried to isolate the problem, but I've had little success. I wrote a simple vertex array of just green pixels that should fill up part of the screen, and still there are problems. The pixels only show my code and the pic. of what I mean.

#include "SFML/Graphics.hpp"  
int main() {
sf::RenderWindow window(sf::VideoMode(400, 240), "Test Window");
window.setFramerateLimit(30);
sf::VertexArray pointmap(sf::Points, 400 * 10);
for(register int a = 0;a < 400 * 10;a++) {
    pointmap[a].position = sf::Vector2f(a % 400,a / 400);
    pointmap[a].color = sf::Color::Green;
}
while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        if (event.type == sf::Event::Closed)
        window.close();
    }
    window.clear();
    window.draw(pointmap);
    //</debug>
    window.display();
}
return 0;

}

http://oi43.tinypic.com/s5d9aw.jpg

I meant for this to just fill in the top 10 rows with Green, but apparently that is not what I did... I think if I can figure out what is causing this not to work, I can probably fix the main problem. Also if you think there is a better way to do this instead, you could let me know :)

Thanks!

Answer

I think you misused the vertex array. Take a look at the sf::Quads primitive in the tutorial's table : you need to define 4 points (coordinates) to draw a quad, and a pixel is just a quad of side lenght 1.

So what you need is to create a vertex array of size 400*10*4, and set the same position to every following four vertices.

You can also use another method provided by SFML : draw directly a texture pixel by pixel and display it. It may not be the most efficient thing to do (you'll have to compare with vertices) but it has the advantage of being rather simple.

const unsigned int W = 400;
const unsigned int H = 10; // you can change this to full window size later

sf::UInt8* pixels = new sf::UInt8[W*H*4];

sf::Texture texture;
texture.create(W, H); 

sf::Sprite sprite(texture); // needed to draw the texture on screen

// ...

for(register int i = 0; i < W*H*4; i += 4) {
    pixels[i] = r; // obviously, assign the values you need here to form your color
    pixels[i+1] = g;
    pixels[i+2] = b;
    pixels[i+3] = a;
}

texture.update(pixels);

// ...

window.draw(sprite);

The sf::Texture::update function accepts an array of sf::UInt8. They represent the color of each pixel of the texture. But as the pixels need to be 32bit RGBA, 4 following sf::UInt8 are the RGBA composants of the pixel.