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

Author Topic: creating a texture through code  (Read 5600 times)

0 Members and 1 Guest are viewing this topic.

JonnyLaw

  • Newbie
  • *
  • Posts: 2
    • View Profile
creating a texture through code
« on: January 13, 2021, 04:44:04 am »
is there a way to create a blank texture with a set size, then access the pixels in the texture to set them?

something similar to the fallowing. (I specifically need the texture to be a pointer)

sf::Texture* texture;
texture = new sf::Texture;
texture->setSize(100, 100);

for (int y = 0; y < 100; y++)
{
    for (int x = 0; x < 100; x++)
    {
        texture->setPixel(sf::Color(127, 127, 127);
    }
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: creating a texture through code
« Reply #1 on: January 13, 2021, 09:17:37 am »
No, SFML doesn't allow direct access to the texture pixels. A better solution is to work on a local pixel buffer, stored in system RAM, and then update the entire texture in a single call with the Texture::update function.
Laurent Gomila - SFML developer

jacmoe

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: creating a texture through code
« Reply #2 on: January 13, 2021, 02:16:49 pm »
sf::Image is in many ways just a pixel buffer, so use that to update the texture as Laurent says.

A sf::Texture is just a sf::Image that lives on the graphics card.
Too many projects; too much time

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: creating a texture through code
« Reply #3 on: January 13, 2021, 04:06:44 pm »
Quote
sf::Image is in many ways just a pixel buffer, so use that to update the texture as Laurent says.
If the texture is filled in real-time (ie. every frame), that's not what we advise, as pixel access in sf::Image is quite unoptimized. A raw array of sf::Uint8 is preferred in this case.
Laurent Gomila - SFML developer

JonnyLaw

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: creating a texture through code
« Reply #4 on: January 14, 2021, 07:41:16 am »
how would i work on a local pixel buffer? would you be able to give a short code example of it? thanks for the reply

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: creating a texture through code
« Reply #5 on: January 14, 2021, 07:49:38 am »
std::vector<sf::Uint8> image(width * height * 4);

// set pixel (x, y):
image[(x + y * width) * 4 + 0] = color.r;
image[(x + y * width) * 4 + 1] = color.g;
image[(x + y * width) * 4 + 2] = color.b;
image[(x + y * width) * 4 + 3] = color.a;

// update texture:
texture.update(image.data());
Laurent Gomila - SFML developer

r4gTime

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • Email
Re: creating a texture through code
« Reply #6 on: January 14, 2021, 12:18:22 pm »
Thanks for your reply, Laurent.

I'm trying yo optimize fps in my game and realized my entire minimap took more than 16300 microseconds to draw with this code :
void Application::DrawMiniMap(){
    sf::RectangleShape rs;
    for(int i = 0; i < 100; i++) {
        for(int j = 0; j < 100; j++) {
                    rs.setPosition(2 * i, 2 * j);
                    rs.setSize(sf::Vector2f(2,2));
                    rs.setFillColor(img.tuile[game.carte.terrainType[i][j]].GetColor());
                    window.draw(rs);
        }
    }
}

I tried this code and it only takes about 300 microseconds now, but.. it doesn't work  ;D
void Application::DrawMiniMap(){

    sf::Texture tx;
    tx.create(100,100);
    std::vector<sf::Uint8> image(100 * 100 * 4);

    for(int x = 0; x < 100; x++) {
        for(int y = 0; y < 100; y++) {
            image[(x + y * 100) * 4 + 0] = img.tuile[game.carte.terrainType[x][y]].GetColor().r;
            image[(x + y * 100) * 4 + 1] = img.tuile[game.carte.terrainType[x][y]].GetColor().g;
            image[(x + y * 100) * 4 + 2] = img.tuile[game.carte.terrainType[x][y]].GetColor().b;
            image[(x + y * 100) * 4 + 3] = img.tuile[game.carte.terrainType[x][y]].GetColor().a;
        }
    }

    // update texture:
    tx.update(image.data());
    sf::Sprite spt;
    spt.setPosition(576,24);
    spt.setTexture(tx);
    window.draw(spt);
}

EDIT : I forgot to texture.create() and now it perfectly works with only ~350 microseconds, thanks a lot Laurent :)

EDIT 2: As my minimap is 200x200 and not 100, it actually takes 1250 microseconds to draw the minimap this way. Do you know a way to optimize even more ?
« Last Edit: January 14, 2021, 12:37:01 pm by r4gTime »

jacmoe

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: creating a texture through code
« Reply #7 on: January 14, 2021, 01:12:03 pm »
Does your map change each frame? Then you probably should create an sf::Image from the pixels and dump it to disk. You can then draw player and other things in a separate pixel array each frame and overlay it on top of the minimap.
Or at least move the map drawing code into a startup function so that it doesn't run each frame :)
Too many projects; too much time

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: creating a texture through code
« Reply #8 on: January 14, 2021, 01:29:25 pm »
Indeed, all that stuff seems to be static, there's really no need to do it every frame. Even if the map was changing dynamically, you could make it much more efficient by creating the texture and allocating the pixel buffer once at init.
Laurent Gomila - SFML developer

r4gTime

  • Newbie
  • *
  • Posts: 14
    • View Profile
    • Email
Re: creating a texture through code
« Reply #9 on: January 14, 2021, 02:31:52 pm »
Indeed...

Thanks for your help jacmoe !