<p>Briefly, modify the stb_load as follows and everything should work.</p>

<pre><code>unsigned char* data = stbi_load(file_path, &amp;width, &amp;height, &amp;nrChannels, 4);
nrChannels = 4;
</code></pre>

<p><em>Details:</em>
Okay, after a lot of heartache trying and failing to get libpng to work, I finally decided to have a look at the stbi implementation that I'm using to load the texture files. This is where the problem comes in from. </p>

<p>@wychmaster was right when he suspected that there was an incorrect stride used. The problem, though, is in the reading of the image. Apparently, this has something to do with alignment of pixel data which is set by glPixelStorei. </p>

<p>Someone posted the same problem in <a href="https://github.com/nothings/stb/issues/335" rel="nofollow noreferrer">https://github.com/nothings/stb/issues/335</a> and determined that this was solution (it works!).</p>

<p>The solution is to set the number of desired channels to 4 in the loading function and read the image as an RGBA instead of whatever the image format actually is. This works and all the misaligned images are now perfect. The images that worked before continue to work too. </p>

<p>But, I do not completely understand why nothing else is affected. This seems strange to me... If someone can explain why this works, that would be very helpful. In the event this is a niche question, I'll likely return to make a more detailed post on it. </p>

CC BY-SA 4.0
2020-04-07T05:47:35.727Z
Usually textures need to be aligned such that the total bytes in a line is divisible by 4. With RGB format your have 3 bytes per pixel so it's easier to misalign. You can also avoid this in RGB format by making sure that image width divisible by 4.
PaulHK
CC BY-SA 4.0
2020-04-08T02:23:31.033Z
That makes sense, all the images that were skewed were not a multiple of 4 in width. Does this mean that the texture input by default expects RGBA values?
speed_of_light
CC BY-SA 4.0
2020-04-06T06:38:58.347Z
2020-04-09T14:08:56.907Z
2020-04-09T14:08:56.907Z
speed_of_light
<p>I'm a noob to the OpenGL world and am picking up ideas through practice. I've been writing some code to build retro-arcade games recently and need to load textures to provide the graphic interface. I'm using OpenGL v4.6 with GLFW3 and the stb library to load images. </p>

<p>To load textures, I draw a box and define the texture coordinates of the image on the box. Only some of the png's that I use have loaded properly- often, the image is blurred and distorted. There were two things I tried so far-</p>

<ol>
<li><p>Look exclusively for jpg files as these were loading properly. But most of the textures that I download of google are exclusively png</p></li>
<li><p>Convert the png into a jpg file. Since I was converting, I decided to use other file formats as well, cropping some of the images if need be. I used GIMP to export them in jpg format. However, when I try to load it OpenGL, I still get bad-poor results.</p></li>
</ol>

<p>Another possible approach I'm considering is to convert them into dxt formats and see if that does the trick. However, this seems a tad too tedious and something I'd only go for if nothing else works. </p>

<p>Below is the code that I'm using to load the image. </p>

<pre><code>int width, height, nrChannels;
unsigned char* data = stbi_load(file_path, &amp;width, &amp;height, &amp;nrChannels, 0);
GLenum format{};
if (data)
{
    if (nrChannels == 1)
        format = GL_RED;
    else if (nrChannels == 3)
        format = GL_RGB;
    else if (nrChannels == 4)
        format = GL_RGBA;
    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}
</code></pre>

<p>I'm starting to spend a significant amount of time looking for images that will load properly and less time learning/implementing; this is quite concerning. Can someone please point out where I'm going wrong or a better way of skirting around this issue?</p>

<p><a href="https://i.sstatic.net/p5Zz9.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/p5Zz9.png" alt="The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL"></a>
The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL</p>

<p><a href="https://i.sstatic.net/jORfg.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/jORfg.png" alt="Example 2"></a>
Again, the image to the left is the output from Opengl while the one to the right is the original image. Note the inclination of the render and lack of colour in it. </p>

<hr>

<p>Edit: Here are some of the implementation details-</p>

<p>I'm believe this portion should be correct because the render is perfect for .jpg files. <em>rect</em> is a vector to hold the box and texture coordinates and <em>ind</em> is a vector that holds the indices that are used by the element buffer to avoid repeat drawing. Both are initialised as arrays and converted into a vector (loop through array and push_back into vector). </p>

<p>PS. Apologies for the verbosity. I was trying to couch the drawing inside a class and this was my first attempt at it. So, please bear with me.</p>

<pre><code>// Box container to hold images
//             x      y   tex-x   tex-y    
const float rect[] = {
            -0.2f, -0.2f, 0.0f, 0.0f,
             0.2f, -0.2f, 1.0f, 0.0f,
             0.2f,  0.2f, 1.0f, 1.0f,
            -0.2f,  0.2f, 0.0f, 1.0f
    };

int ind[] = {
        0,1,2,
        0,2,3
    };
</code></pre>

<p>_num_attr_ is the number of attributes given to the vao, which in this case is 2. <em>cumsum</em> contains the sum of the number of attributes and is used to assign the stride and size of each attribute.</p>

<pre><code>sizes = {2,2}; // initialized 
cumsum = 0;
for (int i = 0; i &lt; num_attr; ++i)
{
    attr_num_cumsum.push_back(cumsum);
    cumsum += sizes[i];
    attr_size.push_back(sizes[i]);  
}
attr_num_cumsum.push_back(cumsum);
</code></pre>

<p>At the end of this block, <em>cumsum</em> has a value of 4 and _attr_num_cumsum_ = {0,2,4} and _attr_size_ = {2,2}.</p>

<p>_vbo_data_ contains the values in <em>rect</em> while _ebo_data_ contains the values in <em>ind</em> Here is the buffer set-up for drawing-</p>

<pre><code>glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vbo_data.size()*sizeof(GL_FLOAT), &amp;vbo_data[0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ebo_data.size()*sizeof(GL_INT), &amp;ebo_data[0], GL_DYNAMIC_DRAW);
for (int i = 0; i &lt; num_attr; ++i)
{
    glVertexAttribPointer(i, attr_size[i], GL_FLOAT, GL_FALSE, attr_num_cumsum[num_attr] * sizeof(GL_FLOAT), (void*)(attr_num_cumsum[i] * sizeof(GL_FLOAT)));
    glEnableVertexAttribArray(i);
}
</code></pre>

<p>And the actual drawing</p>

<pre><code>glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, num_vertices, GL_UNSIGNED_INT, 0);
</code></pre>

<p>Vertex Shader</p>

<pre><code>#version 460 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 tex;
out float C;
out vec2 Tex;
uniform mat4 model;
uniform float col;
void main()
{
    gl_Position = model*vec4(aPos.x,aPos.y,0.0f, 1.0f);
    C=col;
    Tex=tex;
}
</code></pre>

<p>Fragment Shader</p>

<pre><code>#version 460 core
out vec4 Fragcolor;
in float C;
in vec2 Tex;
uniform sampler2D texture1;
void main()
{
    Fragcolor = texture(texture1,Tex);
}
</code></pre>

CC BY-SA 4.0
2020-03-31T09:50:45.157Z
Please provide more information (code if possible). How do you define your box (vertex attributes)? How do you populate the buffers? How do your shaders look like? To me, it looks as if your texture coordinates are not set correctly, but I can't tell for sure without the corresponding code.
wychmaster
CC BY-SA 4.0
2020-03-31T22:38:56.900Z
Which version of OpenGL are you using? The second issue (skewed texture) tends to be the result of an image dimension mismatch when uploading (glTexImage2D(...)). Double check you are specifying the correct dimensions when uploading texture to OpenGL. Also maybe check you can use NPOT (non-power of two) textures which depends on the OpenGL context version you create.
lfgtm
CC BY-SA 4.0
2020-04-01T07:34:30.333Z
@lfgtm He is using OpenGL v4.6 as mentioned at the beginning. That's why I don't think that NPOT textures are the problem. Additionally, if there is a dimension mismatch, wouldn't there be parts missing? To me, it just looks like the textures are shifted to the right with increasing y value.
wychmaster
CC BY-SA 4.0
2020-04-01T13:30:37.597Z
@wychmaster It's not texture coordinates. The skew and lack of colour is a dead giveaway that the texel "stride" is incorrect. If the dims and number of channels are correct, the input image is probably not aligned as GL expects it to be. `glPixelStorei` would probably be the fix, but without knowing more details about the input texture, impossible to say what arguments `glPixelStorei` should take.
lfgtm
CC BY-SA 4.0
2020-04-01T15:15:11.027Z
@wychmaster I doubt there is a shift in the coordinates because the same code was used to display the multiple roads image. Also, just to be safe, I tested the render on this (also jpg) and it works- https://imgur.com/Sm3zuMy
speed_of_light
CC BY-SA 4.0
2020-04-01T15:18:29.097Z
@lfgtm I'm looking up what npot textures are. Never came across them on my tutorials. 

Btw, I was doing a bit of reading on the .png files.. It seems they also contain other details like gamma correction. Would these be represented in a simple RGBA value? Presently, I'm trying to set-up the libpng library to see if the problem persists.
speed_of_light
CC BY-SA 4.0
2020-04-01T15:25:20.453Z
Btw, this is a render of a png with the same code- https://imgur.com/oc4fRBt
speed_of_light
<opengl><texture>
Texture loading- erratic working
speed_of_light
# Texture loading- erratic working

(Asked by: username_0 on 2020-03-28)

I'm a noob to the OpenGL world and am picking up ideas through practice. I've been writing some code to build retro-arcade games recently and need to load textures to provide the graphic interface. I'm using OpenGL v4.6 with GLFW3 and the stb library to load images.

To load textures, I draw a box and define the texture coordinates of the image on the box. Only some of the png's that I use have loaded properly- often, the image is blurred and distorted. There were two things I tried so far-

1. Look exclusively for jpg files as these were loading properly. But most of the textures that I download of google are exclusively png
2. Convert the png into a jpg file. Since I was converting, I decided to use other file formats as well, cropping some of the images if need be. I used GIMP to export them in jpg format. However, when I try to load it OpenGL, I still get bad-poor results.

Another possible approach I'm considering is to convert them into dxt formats and see if that does the trick. However, this seems a tad too tedious and something I'd only go for if nothing else works.

Below is the code that I'm using to load the image.

```
int width, height, nrChannels;
unsigned char* data = stbi_load(file_path, &width, &height, &nrChannels, 0);
GLenum format{};
if (data)
{
    if (nrChannels == 1)
        format = GL_RED;
    else if (nrChannels == 3)
        format = GL_RGB;
    else if (nrChannels == 4)
        format = GL_RGBA;
    glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}

```

I'm starting to spend a significant amount of time looking for images that will load properly and less time learning/implementing; this is quite concerning. Can someone please point out where I'm going wrong or a better way of skirting around this issue?

[![The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL](https://i.sstatic.net/p5Zz9.png)](https://i.sstatic.net/p5Zz9.png)
The image to the left is the original as loaded by OpenGL (jfif file format). The one to the bottom is the edited version (made with Gimp, stored as jpg). The image to the right is the render of the bottom image in OpenGL

[![Example 2](https://i.sstatic.net/jORfg.png)](https://i.sstatic.net/jORfg.png)
Again, the image to the left is the output from Opengl while the one to the right is the original image. Note the inclination of the render and lack of colour in it.

---

Edit: Here are some of the implementation details-

I'm believe this portion should be correct because the render is perfect for .jpg files. *rect* is a vector to hold the box and texture coordinates and *ind* is a vector that holds the indices that are used by the element buffer to avoid repeat drawing. Both are initialised as arrays and converted into a vector (loop through array and push\_back into vector).

PS. Apologies for the verbosity. I was trying to couch the drawing inside a class and this was my first attempt at it. So, please bear with me.

```
// Box container to hold images
//             x      y   tex-x   tex-y    
const float rect[] = {
            -0.2f, -0.2f, 0.0f, 0.0f,
             0.2f, -0.2f, 1.0f, 0.0f,
             0.2f,  0.2f, 1.0f, 1.0f,
            -0.2f,  0.2f, 0.0f, 1.0f
    };

int ind[] = {
        0,1,2,
        0,2,3
    };

```

\_num\_attr\_ is the number of attributes given to the vao, which in this case is 2. *cumsum* contains the sum of the number of attributes and is used to assign the stride and size of each attribute.

```
sizes = {2,2}; // initialized 
cumsum = 0;
for (int i = 0; i < num_attr; ++i)
{
    attr_num_cumsum.push_back(cumsum);
    cumsum += sizes[i];
    attr_size.push_back(sizes[i]);  
}
attr_num_cumsum.push_back(cumsum);

```

At the end of this block, *cumsum* has a value of 4 and \_attr\_num\_cumsum\_ = {0,2,4} and \_attr\_size\_ = {2,2}.

\_vbo\_data\_ contains the values in *rect* while \_ebo\_data\_ contains the values in *ind* Here is the buffer set-up for drawing-

```
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vbo_data.size()*sizeof(GL_FLOAT), &vbo_data[0], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ebo_data.size()*sizeof(GL_INT), &ebo_data[0], GL_DYNAMIC_DRAW);
for (int i = 0; i < num_attr; ++i)
{
    glVertexAttribPointer(i, attr_size[i], GL_FLOAT, GL_FALSE, attr_num_cumsum[num_attr] * sizeof(GL_FLOAT), (void*)(attr_num_cumsum[i] * sizeof(GL_FLOAT)));
    glEnableVertexAttribArray(i);
}

```

And the actual drawing

```
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, num_vertices, GL_UNSIGNED_INT, 0);

```

Vertex Shader

```
#version 460 core
layout(location = 0) in vec2 aPos;
layout(location = 1) in vec2 tex;
out float C;
out vec2 Tex;
uniform mat4 model;
uniform float col;
void main()
{
    gl_Position = model*vec4(aPos.x,aPos.y,0.0f, 1.0f);
    C=col;
    Tex=tex;
}

```

Fragment Shader

```
#version 460 core
out vec4 Fragcolor;
in float C;
in vec2 Tex;
uniform sampler2D texture1;
void main()
{
    Fragcolor = texture(texture1,Tex);
}

```

**Tags:** opengl, texture

> **Comments:**
> **username_1**: Please provide more information (code if possible). How do you define your box (vertex attributes)? How do you populate the buffers? How do your shaders look like? To me, it looks as if your texture coordinates are not set correctly, but I can't tell for sure without the corresponding code.  
> **username_2**: Which version of OpenGL are you using? The second issue (skewed texture) tends to be the result of an image dimension mismatch when uploading (glTexImage2D(...)). Double check you are specifying the correct dimensions when uploading texture to OpenGL. Also maybe check you can use NPOT (non-power of two) textures which depends on the OpenGL context version you create.  
> **username_1**: @username_2 He is using OpenGL v4.6 as mentioned at the beginning. That's why I don't think that NPOT textures are the problem. Additionally, if there is a dimension mismatch, wouldn't there be parts missing? To me, it just looks like the textures are shifted to the right with increasing y value.  
> **username_2**: @username_1 It's not texture coordinates. The skew and lack of colour is a dead giveaway that the texel "stride" is incorrect. If the dims and number of channels are correct, the input image is probably not aligned as GL expects it to be. `glPixelStorei` would probably be the fix, but without knowing more details about the input texture, impossible to say what arguments `glPixelStorei` should take.  
> **username_0**: @username_1 I doubt there is a shift in the coordinates because the same code was used to display the multiple roads image. Also, just to be safe, I tested the render on this (also jpg) and it works- https://imgur.com/Sm3zuMy  
> **username_0**: @username_2 I'm looking up what npot textures are. Never came across them on my tutorials.   Btw, I was doing a bit of reading on the .png files.. It seems they also contain other details like gamma correction. Would these be represented in a simple RGBA value? Presently, I'm trying to set-up the libpng library to see if the problem persists.  
> **username_0**: Btw, this is a render of a png with the same code- https://imgur.com/oc4fRBt  

---

## 1 answers

### Answer by username_0 on 2020-04-06. Score: 1 | Accepted answer

Briefly, modify the stb\_load as follows and everything should work.

```
unsigned char* data = stbi_load(file_path, &width, &height, &nrChannels, 4);
nrChannels = 4;

```

*Details:*
Okay, after a lot of heartache trying and failing to get libpng to work, I finally decided to have a look at the stbi implementation that I'm using to load the texture files. This is where the problem comes in from.

@username_1 was right when he suspected that there was an incorrect stride used. The problem, though, is in the reading of the image. Apparently, this has something to do with alignment of pixel data which is set by glPixelStorei.

Someone posted the same problem in <https://github.com/nothings/stb/issues/335> and determined that this was solution (it works!).

The solution is to set the number of desired channels to 4 in the loading function and read the image as an RGBA instead of whatever the image format actually is. This works and all the misaligned images are now perfect. The images that worked before continue to work too.

But, I do not completely understand why nothing else is affected. This seems strange to me... If someone can explain why this works, that would be very helpful. In the event this is a niche question, I'll likely return to make a more detailed post on it.

> **Comments:**
> **username_3**: Usually textures need to be aligned such that the total bytes in a line is divisible by 4. With RGB format your have 3 bytes per pixel so it's easier to misalign. You can also avoid this in RGB format by making sure that image width divisible by 4.  
> **username_0**: That makes sense, all the images that were skewed were not a multiple of 4 in width. Does this mean that the texture input by default expects RGBA values?  

---

