Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Creating ColorBuffer with Pixel Data (transcribing some SDL)  (Read 1783 times)

0 Members and 1 Guest are viewing this topic.

SFMLNewGuy

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Creating ColorBuffer with Pixel Data (transcribing some SDL)
« on: October 04, 2020, 09:06:30 am »
Hello,

I was hoping someone could help me out with this bit of code and its SDL equivalent? I'm learning about RayCasting, unfortunately, it's in SDL and this part hasn't been as easy as I thought it would be. I'll show the basic code and what I did to emulate it in SFML. Also, he did the format as ARGB8888 is that going to be a problem and can I convert that for SFML? Because I've always thought SFML took it as RGBA.

const int TILE_SIZE 64;
constexpr int MAP_NUM_ROWS = 13;
constexpr int MAP_NUM_COLS = 20;
#define WINDOW_WIDTH  (MAP_NUM_COLS * TILE_SIZE)
#define WINDOW_HEIGHT (MAP_NUM_ROWS * TILE_SIZE)

// SDL CODE                                   //  SFML CODE
// globals
Uint32* = colorBuffer = NULL;         //  sf::Uint8* colorBuffer = nullptr;
SDL_Texture* colorBufferTexture;    // sf::Texture* colorBufferTexture = nullptr;

// init()
colorBuffer =
(Uint32*)malloc(sizeof(Uint32) * WINDOW_WIDTH * WINDOW_HEIGHT);
 colorBufferTexture = SDL_CreateTexture(
        renderer,
        SDL_PIXELFORMAT_ARGB8888,
        SDL_TEXTUREACCESS_STREAMING,
        WINDOW_WIDTH,
        WINDOW_HEIGHT
    );

/*  SFML
colorBuffer = new sf::Uint8[WINDOW_WIDTH * WINDOW_HEIGHT * 4];
colorBufferTexture = new sf::Texture();
colorBufferTexture.create(WINDOW_WIDTH, WINDOW_HEIGHT);
*/


// simple functions in class
void clearColorBuffer(Uint32 color) {
    for (int x = 0; x < WINDOW_WIDTH; x++)
        for (int y = 0; y < WINDOW_HEIGHT; y++)
            colorBuffer[(WINDOW_WIDTH * y) + x] = color;
}

/* SFML
        void clearColorBuffer(sf::Uint8 color) {
                for (int x = 0; x < WINDOW_WIDTH; ++x) {
                        for (int y = 0; y < WINDOW_HEIGHT; ++y) {
                                 /* I thought the 1D code should be MapWidth * X + Y here instead the way the loop is
                                    constructed. Guess not. because both ways give me an write access error
                                    "color = 48 '0'
                                     colorBUffer = 0x0a9ed088 "0yyyyyyyyy uuG'"  0yy-uuG has little ' on top of it
                                    "
                                colorBuffer[(WINDOW_WIDTH * y) + x] = color;   // tried putting * 4 in there as well
                        }
                }
        }
*/


void renderColorBuffer() {
    SDL_UpdateTexture(
        colorBufferTexture,
        NULL,
        colorBuffer,
        (int)(WINDOW_WIDTH * sizeof(Uint32))
    );
    SDL_RenderCopy(renderer, colorBufferTexture, NULL, NULL);
}

/* SFML
void renderColorBuffer() {     
                colorBufferTexture->update(colorBuffer);
                const sf::Sprite sprite(*colorBufferTexture);
                window.draw(sprite);
        }

*/


void draw()
        {
                window.clear();

                clearColorBuffer(0xFF00EE30); // I believe in SFML I'm suppose to make this 0x00EE30FF
                renderColorBuffer();

                // display mini-map
                renderMap();
                renderRays();
                renderPlayer();

                window.display();
        }

 

Any help would be appreciated. I'm shutting down for the night and will take a crack tomorrow. This was just a "see if it's working thus far" run before moving further and I'm putting it on hold until I get this down correctly. The example down the road involves using something called 'uPNG' which is why I want to get at least feeding it the correct data correctly. My hunch is how he is using the Uin32 and I can't cast a Uint32 to a Uint8, which is why I've used sf::Uint8 since update() takes a pointer to sf::Uint8 data. But I've been all sorts of wrong during this example.  :-X

I hope this makes sense. Thank you and you all be safe now!

fallahn

  • Sr. Member
  • ****
  • Posts: 492
  • Buns.
    • View Profile
    • Trederia
Re: Creating ColorBuffer with Pixel Data (transcribing some SDL)
« Reply #1 on: October 04, 2020, 01:56:42 pm »
Setting up a pixel buffer with SFML is quite easy using the built in classes. Instead of an array  you can use sf::Image which has functions for setting the colours for individual pixels. Once you finish updating the pixels for a frame, copy it to a texture using sf::Texture::update(). You can draw this texture as you normally would using sf::Sprite

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");

    //this is your pixel buffer
    sf::Image img;
    img.create(50,50);

    sf::Texture tex;
    tex.create(50, 50);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        //do ALL pixel buffer operations
        for(auto y = 10; y < 20; ++y)
        {
            for(auto x = 10; x < 20; ++x)
            {
                img.setPixel(x, y, sf::Color::Green);
            }
        }

        //update the texture from the pixel buffer
        tex.update(img);

        window.clear();
        window.draw(sf::Sprite(tex));
        window.display();
    }

    return 0;
}

You can of course use an array instead of an Image and use that to update the texture. In this case a std::vector<sf::Uint8> would do - no need to 'new' anything, the vector takes care of memory management.

The problem here is, as you point out, the pixel format. The reason the SDL code uses Uint32 is that it represents the 4 colour channels packed into a single value. SFML uses a byte for each channel which is why just a simple cast will not work. This also affects how you calculate the size of the buffer. WIDTH x HEIGHT is fine for Uint32, but when creating a buffer of Uint8 values you will need WIDTH x HEIGHT x 4.

 sf::Color will take a uint32 value and convert it to bytes automatically, but as you also point out SFML expects RGBA not ARGB values. You could potentially convert these but they will be very slow operations if done on EVERY pixel, especially at higher resolutions.

sf::Uint8 r = (pixel & 0x00ff0000) >> 16;
sf::Uint8 g = (pixel & 0x0000ff00) >> 8
sf::Uint8 b = (pixel & 0x000000ff);
sf::Uint8 a = (pixel & 0xff000000) >> 24;
 

or to an RGBA uint32:

sf::Uint32 rgbaPixel = ((pixel & 0xff000000) >> 24) | ((pixel & 0x00ffffff) << 8);
 

Another tack would be to use OpenGL directly to modify the sf::Texture to accept ARGB - this would save performing any pixel conversions but would considerably complicate the setup of the pixel buffer. It would also prevent using an sf::Image.

Utlimately (as you're converting the code anyway) the best bet is to find where the pixel values are actually generated and modify the code to create RGBA output, either as packed uint32 or individual uint8 channels.

SFMLNewGuy

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Re: Creating ColorBuffer with Pixel Data (transcribing some SDL)
« Reply #2 on: October 13, 2020, 03:47:05 am »
Hey! Sorry for getting back SO late. I sort of forgot about this and have been ridiculously busy. I greatly appreciate the help! I'll give it a shot tonight!

Thanks!

EDIT: It works! And it's 10x easier! Thanks  ;D 
« Last Edit: October 13, 2020, 04:25:52 am by SFMLNewGuy »