10

Not so long ago I had a problem with displaying a texture as I was using edges of texels as texture coordinates instead of centers of texels. This, in combination with linear blending gave a smooth result of colors instead of pure colors given by a texture.

Thanks to advices given me here, I thought my problem is solved as I started to use centers of texels as coordinates, but it only worked in one case and I have no idea why only in that one case.

Again I'll show some pictures.

This is a texture I'm using (32x32 pixels) with border of 2 pixels:

enter image description here

My whole object that is being drawn consists of 9 quads, but they use only one texture (the one I showed). One of them will serve as an explanation to my problem:

enter image description here

I think it is well visible that colors of that quad aren't properly set according to the texture.

It looks like a problem with blending, but for setting texture coordinates I have used texels' centers, like this:

glBegin(GL_QUADS);
    // Bottom left
    glTexCoord2f(0.0 + texelCentersOffset, maxTexCoordBorderY + texelCentersOffset);
    glVertex2i(pos.x, pos.y + height - m_borderWidth);

    // Top left
    glTexCoord2f(0.0 + texelCentersOffset, (GLfloat)1.0 - maxTexCoordBorderY - texelCentersOffset);
    glVertex2i(pos.x, pos.y + m_borderWidth);

    // Top right
    glTexCoord2f(maxTexCoordBorderX - texelCentersOffset, (GLfloat)1.0 - maxTexCoordBorderY - texelCentersOffset);  
    glVertex2i(pos.x + m_borderWidth, pos.y + m_borderWidth);

    // Bottom right
    glTexCoord2f(maxTexCoordBorderX - texelCentersOffset, maxTexCoordBorderY + texelCentersOffset);
    glVertex2i(pos.x + m_borderWidth, pos.y + height - m_borderWidth);
glEnd();

For clarification:

m_borderWidth = 2

maxTexCoordBorderX = maxTexCoordBorderY = 2/32 = 0.0625

texelCentersOffset = 1/64 = 0.015625

Could anyone tell me what is wrong in what I've wrote?

EDIT1:

Here are settings for my texture:

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                 GL_LINEAR_MIPMAP_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                    GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                    GL_REPEAT );
gluBuild2DMipmaps( GL_TEXTURE_2D, 4, m_width, m_height,
                   GL_RGBA, GL_UNSIGNED_BYTE, pixmap );

When I change from GL_LINEAR to GL_NEAREST, it works properly so it's obviously a problem with blending, but still can't figure out why it is wrong.

EDIT2:

When I increase height of quad to be the same as or larger than texture's height, it works correctly without changing any texture coordinates.

Piotr Chojnacki
  • 6,837
  • 5
  • 34
  • 65
  • Where do you set your projection and modelview matrices? What's the value of `pos`? – genpfault Dec 18 '12 at 16:15
  • @genpfault pos.x and pos.y are 0 so they can be omitted. Matrices are set at the beginning like this: glViewport(0, 0, width, height); // Reset The Current Viewport glMatrixMode(GL_PROJECTION); // Select The Projection Matrix glLoadIdentity(); // Reset The Projection Matrix glOrtho(0.0, width, height, 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix glLoadIdentity(); // Reset The Modelview Matrix – Piotr Chojnacki Dec 18 '12 at 16:36
  • You should not try to assign texel centers to vertices. What you really want is texels to be centered on the resulting fragments *after* rasterization. I wrote a pretty through answer (with images to explain) here, perhaps reading this will help you understand: http://stackoverflow.com/a/11458037/1236185 – Tim Dec 19 '12 at 06:13
  • @Tim So according to your answer I should do it without using this "texelCentersOffset", right? But then again it's a problem with this blending as I wrote here: http://stackoverflow.com/questions/13929160/texture-not-displaying-properly-probably-coordinates-are-wrong-opengl-c And JasonD pointed me there that I should use this offset... or maybe I misunderstood your article? – Piotr Chojnacki Dec 19 '12 at 09:58
  • @Tim Well your problem *was* that you were not sampling at texel centers, but where the texture is sampled from is a function of both the texture co-ordinates, and the vertex positions. For perfect sampling at texel centers, both must be taken into account (as well as being aware of the rasterisation rules). It may indeed be the case that for your situation no texel-offset is necessary, but that implies that you must draw your primitive at exact pixel locations, and with exactly the right size. – JasonD Dec 19 '12 at 11:10

1 Answers1

3

It seems to me, that when you set the quad size less than the texture's size. It must sample the texture using a mipmap.

Mipmaps are made by averaging 4 texel blocks. So, when you sample the mipmap you get information from more than one texel. So, by having your quad be smaller than the texture it has to sample a mipmap and you're getting texture bleed. Turn off the mipmapping and my guess is it will go away.

Tocs
  • 752
  • 4
  • 17