1
\$\begingroup\$

I am having a strange issue with my sprites, which is kind of difficult to describe, but hopefully the attached images will illustrate. I have drawn two 1 pixel lines on my sprite to help with this, one at the far edge, and one a few pixels in. When drawn at its native scale everything looks how you would expect it to. enter image description here

However, if I try to scale up or zoom into my sprite, things start to get weird. Zooming in by 2 times, you can see the inner line is now 2 pixels wide, but the far one remains 1 pixel. enter image description here

If I zoom in by 4 times, the inner is now 4 pixels, but the far is only 2. enter image description here

So what is going on here, and how can I resolve it? This is giving my sprites a much different look than I want when I try to zoom in, resize the window, or broadly try to upscale them at all. My texture parameters are as follows:

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

My camera matrix:

    orthographicMatrix = glm::ortho(0.0f , float(screenWidth),
        float(screenHeight) , 0.0f , -1.0f, 1.0f);
    ...
    glm::vec3 translate(floor(-position.x) + halfWidth, floor(-position.y) + halfHeight, 0.0f);

    glm::vec3 scale(cameraScale, cameraScale, 0.0f);

    cameraMatrix = glm::translate(orthographicMatrix, translate);
    cameraMatrix = glm::scale(glm::mat4(1.0f), scale) * cameraMatrix;

My 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);
}  

I'm not exactly sure if the attached code is relevant to the issue, but they are the areas I've been looking.

Running some additional tests, the issue appears to be in how I am calculating my UV coordinates, so here is my code for that.

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;
}

The offset value is to prevent pixel bleeding, though now I'm thinking it might be causing issues. Setting it to 0 resolves the issue, but then I obviously have pixel bleeding again. So I guess I'm doing that part wrong.

\$\endgroup\$
2
  • \$\begingroup\$ Could it be that your vertices' texture coordinates are picking the center of each texel, instead of the outer corners? \$\endgroup\$
    – DMGregory
    Commented Jul 18 at 16:51
  • 1
    \$\begingroup\$ Running some quick tests, I think you've got it. I tried this same line test on a texture where I just set the UVs to (0,1,0,1) and the issue disappears, so I must be messing up when it comes to calculating my UVs. I will edit in the function where I calculate that into my main question. \$\endgroup\$
    – starrider
    Commented Jul 18 at 17:33

1 Answer 1

1
\$\begingroup\$

It looks like the issue is my uv calculation function. I was doing half pixel correction to prevent pixel bleeding, but it turns out I was doing that step totally wrong. The updated code now appears to be working just fine. If there are any issues with this, I'm not seeing them.

std::vector<glm::vec4> Texture2D::GetUVs(int w, int h)
{
    std::vector<glm::vec4> uvs;
    int rows = Width/ w;
    int columns = Height / h;
    //Half-pixel correction
    float offsetx = 0.5f / Width;
    float offsety = 0.5f / Height;
    for(int c = 0; c < columns; c ++)
    {
        for(int i = 0; i < rows; i ++)
        {
            uvs.emplace_back(glm::vec4(float(i * w + offsetx) / Width,
                float(i * w + w - offsetx) / Width,
                float(c * h + offsety) / Height,
                float(c * h + h - offsety) / Height));
        }
    }
    return uvs;
}
\$\endgroup\$

You must log in to answer this question.

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