2
votes

I wrote a simple app that load model using OpenGL, Assimp and Boost.GIL.

My model contains a PNG texture. When I load it using GIL and render it through OPENGL I got a wrong result. Thank of powel of codeXL, I found my texture loaded in OpenglGL is completely different from the image itself.

Here is a similar question and I followed its steps but still got same mistake.

Here are my codes:

// --------- image loading
std::experimental::filesystem::path path(pathstr);
gil::rgb8_image_t img;
if (path.extension() == ".jpg" || path.extension() == ".jpeg" || path.extension() == ".png")
{
    if (path.extension() == ".png")
        gil::png_read_and_convert_image(path.string(), img);
    else
        gil::jpeg_read_and_convert_image(path.string(), img);

    _width = static_cast<int>(img.width());
    _height = static_cast<int>(img.height());

    typedef decltype(img)::value_type pixel;

    auto srcView = gil::view(img);
    //auto view = gil::interleaved_view(
    //  img.width(), img.height(), &*gil::view(img).pixels(), img.width() * sizeof pixel);

    auto pixeldata = new pixel[_width * _height];

    auto dstView = gil::interleaved_view(
        img.width(), img.height(), pixeldata, img.width() * sizeof pixel);

    gil::copy_pixels(srcView, dstView);
}

// ---------- texture loading
{
    glBindTexture(GL_TEXTURE_2D, handle());
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
        image.width(), image.height(),
        0, GL_RGB, GL_UNSIGNED_BYTE,
        reinterpret_cast<const void*>(image.data()));
    glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);
}

And my texture is: original texture

When it runs, my codeXL debugger reports me that the texture became: texture in opengl

all other textures of this model went wrong too.

1

1 Answers

3
votes

Technically this is a FAQ, asked already several times. Essentially you're running into an alignment issue. By default (you can change it) OpenGL expects image rows to be aligned on 4 byte boundaries. If your image data doesn't match this, you get this skewed result. Adding a call to glPixelStorei(GL_UNPACK_ALIGNMENT, 1); right before the call to glTexImage… will do the trick for you. Of course you should retrieve the actual alignment from the image metadata.

The image being "upside down" is caused by OpenGL putting the origin of textures into the lower left (if all transformation matrices are left at default or have positive determinant). That is unlike most image file formats (but not all) which have it in the upper left. Just flip the vertical texture coordinate and you're golden.