Attempt to fix sprite sheet pixel bleeding in OpenGL 2D causing sprite distortion

While working on a project, I encountered the common problem of pixel bleeding when trying to draw subregions of my sprite sheet. This caused sort of "seams" to appear at the edges of my sprites. You can see the issue here, on the right and top of the sprite .

Doing some searching, I found others with a similar problem, and a suggested solution (here, and here for example) was to offset my texture coordinates by a bit, such as 0.5. I tried this, and it seemed to work. But I have noticed that sometimes, depending on where the sprite or camera is, I get a bit of distortion on the sprites. Here, the left side appears to be cut off, and here, the bottom seems to have expanded. (I should note, the distortion happens on all sides, I just happened to take screenshots of it happening on the bottom and left.) It may be a little difficult to see in screenshots, but it is definitely noticeable in motion. For reference, here is the part of the sprite sheet that is being displayed here

Does anybody have any idea what is going on here? I didn’t actually notice this issue until recently. I originally set out to resolve the pixel bleeding when I saw it occurring between my tile sprites. This new issue does not occur with them using my current half-pixel offset solution (or if it does, it’s not noticeable).


Texture parameters


Texture coordinate calculation

std::vector<glm::vec4> Texture2D::GetUVs(int w, int h) { std::vector<glm::vec4> uvs; int rows = Width/ w; int columns = Height / h;  for(int c = 0; c < columns; c ++) {     for(int i = 0; i < rows; i ++)     {         float offset = 0.5;         uvs.emplace_back(glm::vec4(float(((i) * w + offset))/Width,                               float(((1 + i) * w - offset))/Width,                               float(((c) * h + offset))/Height,                               float(((1 + c) * h - offset))/Height));     } } return uvs; 

Where Width and Height are the dimensions of the sprite sheet, and w and h are the dimensions of the subregion, in this case 32 and 32.

How I pass the uvs to the shader

GLfloat verticies[] = {     uv.x, uv.w,     uv.y, uv.z,     uv.x, uv.z,      uv.x, uv.w,     uv.y, uv.w,     uv.y, uv.z };  this->shader.Use().SetVector2fv("uvs", 12, verticies); 

Where uv is the uv at an index in the uvs vector that was returned above in the GetUVs function.

Vertex shader

#version 330 core layout (location = 0) in vec2 vertex;   out vec2 TextureCoordinates;  uniform vec2 uvs[6]; uniform mat4 model; uniform mat4 projection;  void main() {     const vec2 position [6] = vec2[]     (         vec2(0.0f, 1.0f),         vec2(1.0f, 0.0f),         vec2(0.0f, 0.0f),          vec2(0.0f, 1.0f),         vec2(1.0f, 1.0f),         vec2(1.0f, 0.0f)     );     TextureCoordinates = uvs[gl_VertexID];    gl_Position = projection * model * vec4(position[gl_VertexID], 0.0, 1.0); } 

Fragment shader

#version 330 core in vec2 TextureCoordinates; out vec4 color;  uniform sampler2D image; uniform vec4 spriteColor;  void main() {         color = vec4(spriteColor) * texture(image, TextureCoordinates); }   

Thanks for reading. I have asked this question a few places and not gotten any response, so any help is greatly appreciated.