0
\$\begingroup\$

I got this weird issue with my block texture,it gets botched after loading the block, the issue though doesn't affect other textures as the the paddle texture gets rendered properly: scene display

I tried debugging it in render doc and it seems like it gets loaded in botched, my loading process looks something like this: Resource_Manager -> Texture_Generator -> Sprite_Renderer

game.cpp

//texture loading
void Game::init_game()
{

    Resource_Manager::load_shader("resources/shaders/sprite.vs",
                                  "resources/shaders/sprite.frag",
                                  "sprite");

    glm::mat4 projection = glm::ortho(0.0f,
                                      static_cast<float>(this->width),
                                      static_cast<float>(this->height),
                                      0.0f,
                                      -1.0f,
                                      1.0f);
    Resource_Manager::get_shader("sprite").use_current_shader().set_integer(
        "image", 0);
    Resource_Manager::get_shader("sprite").set_matrix4("projection",
                                                       projection);

    renderer = new Sprite_Renderer(Resource_Manager::get_shader("sprite"));

    
    Resource_Manager::load_texture("resources/textures/block.png", true, "block");
    Game_Level level_1;
    level_1.load("resources/levels/one.lvl", this->width, this->height / 2);

    this->levels.push_back(level_1);

    this->current_level = 0;
}

//texture rendering
void Game::render()
{

    if (this->State == GAME_ACTIVE)
    {
        this->levels[this->current_level].draw(*renderer);
    }
}

texture.cpp

void Texture::generate(GLuint width, GLuint height, unsigned char* data)
{
    this->width  = width;
    this->height = height;

    glBindTexture(GL_TEXTURE_2D, this->ID);
    glTexImage2D(GL_TEXTURE_2D,
                 0,
                 this->internal_format,
                 width,
                 height,
                 0,
                 this->image_format,
                 GL_UNSIGNED_BYTE,
                 data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, this->wrap_s);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, this->wrap_t);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, this->filter_min);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, this->filter_max);

    glBindTexture(GL_TEXTURE_2D, 0);
}

game-level.cpp

void Game_Level::init(std::vector<std::vector<unsigned int>> tile_data,
                      unsigned int                           level_width,
                      unsigned int                           level_height)
{
    unsigned int height     = tile_data.size();
    unsigned int width      = tile_data[0].size();
    float        unit_width = level_width / static_cast<float>(width),
          unit_height       = level_height / height;

    for (unsigned int y = 0; y < height; y++)
    {
        for (unsigned int x = 0; x < width; x++)
        {
            if (tile_data[y][x] == 1)
            {
                glm::vec2   pos(unit_height * x, unit_height * y);
                glm::vec2   size(unit_width, unit_height);

                Game_Object obj(pos,
                                size,
                                Resource_Manager::get_texture(
                                    "block"),
                                glm::vec3(0.8f, 0.8f, 0.7f));
                this->bricks.push_back(obj);
            }
        }
    }
}

resource-manager.cpp(shows use of texture.generate())

Texture Resource_Manager::load_texture_from_file(const char* file, bool alpha)
{

    Texture texture;
    if (alpha)
    {
        texture.internal_format = GL_RGBA;
        texture.image_format    = GL_RGBA;
    }

    int            width, height, nrChannels;
    unsigned char* data = stbi_load(file, &width, &height, &nrChannels, 0);

    texture.generate(width, height, data);

    stbi_image_free(data);
    return texture;
}

The image is taken from JoeyDeVrieses github repository:link

Debugging

Running block.png through debugger I get these results:

  1. width - 128 pixels
  2. height - 128 pixels
  3. nr channels - 3 data
  4. 0x555555e23240 'G' <repeats 200 times>

Running paddle.png I get these results:

  1. width - 166 pixels
  2. height - 25 pixels
  3. nr channels - 4
  4. data - 0x555555e1dc60 ""

Difference: the paddle has four nr channels and a single memory pointer while the block has three nr channels and 200 memory pointers?

\$\endgroup\$
7
  • \$\begingroup\$ This looks like the texture has been loaded with the wrong stride. Try reducing your code to a Minimal Complete Verifiable Example: just the code needed to load and draw one copy of the texture. \$\endgroup\$
    – DMGregory
    Jun 18, 2023 at 20:37
  • \$\begingroup\$ Could you please explain what a stride is in this context? A line? Also if the rendering is Ok, I will update the question with information regarding the loading of the texture rather than rendering. \$\endgroup\$
    – koogel
    Jun 18, 2023 at 20:39
  • \$\begingroup\$ This is something that can happen when you load an image with a mismatched width, you you don't count the correct number of bytes per texel. You write a full row into the loaded texture after reading only half a row from the file. Then the next half row from the file becomes the next whole row, leading to the tall skinny appearance and horizontal stripes you see. I can't see where Texture::generate is called, so it's not clear what parameter values it's getting, making it hard to spot the exact cause. \$\endgroup\$
    – DMGregory
    Jun 18, 2023 at 20:54
  • \$\begingroup\$ Ok, I've ran the texture from a debugger and in the texture it says this in data 0x555555e23240 'G' <repeats 200 times> this doesn't happen in paddle.png. \$\endgroup\$
    – koogel
    Jun 18, 2023 at 21:15
  • \$\begingroup\$ I'm not sure what you mean. Want to edit your question to walk us through those debugging steps in detail? \$\endgroup\$
    – DMGregory
    Jun 18, 2023 at 21:37

1 Answer 1

2
\$\begingroup\$

It looks to me as if at least some of the problem is that you're ignoring the nrChannels value returned by stbi_load().

I think it makes sense to use that to choose an image format for the texture, instead of using the bool alpha parameter to do that. Something like this:

Texture Resource_Manager::load_texture_from_file(const char* file)
{
    Texture texture;

    int            width, height, nrChannels;
    unsigned char* data = stbi_load(file, &width, &height, &nrChannels, 0);

    if (data == nullptr)
    {
        // TODO: Better error handling
        assert(false);
        return texture;
    }

    switch (nrChannels)
    {
        case 1: texture.internal_format = texture.image_format = GL_RED; break;
        case 2: texture.internal_format = texture.image_format = GL_RG; break;
        case 3: texture.internal_format = texture.image_format = GL_RGB; break;
        case 4: texture.internal_format = texture.image_format = GL_RGBA; break;
        default: assert(false); return texture; // TODO: Better error handling
    }

    texture.generate(width, height, data);

    stbi_image_free(data);
    return texture;
}
\$\endgroup\$
1
  • \$\begingroup\$ Thank you, the jittering is gone and the paddle texture is unaffected, everything is smooth and works as expected. \$\endgroup\$
    – koogel
    Jun 19, 2023 at 7:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .