Координаты текстуры OpenGL ES слегка ослаблены

Я пытаюсь нарисовать субрегион текстуры в OpenGL, указав нужные координаты. Однако происходит то, что, в зависимости от размера изображения, кажется, что есть небольшое смещение в начале координат, где он выбирает координаты текстуры. Сумма смещения, по-видимому, меньше размера пикселя, а выход представляет собой размытую комбинацию соседних пикселей.

Вот идея того, что я описываю. В этом случае я бы хотел выбрать 6x5 зеленый/белый регион, но то, что рендеринг OpenGL включает небольшой розовый оттенок в верхний и левый пиксели. Offset Illustration

Какой результат будет выглядеть:

Resulting Output Texture

Я могу исправить это, добавив смещение к координатам текстуры, прежде чем передавать их в glTexCoordPointer, но проблема в том, что у меня нет возможности рассчитать, что такое смещение, и для разных текстур кажется различным.

псевдокод:

float uFactor = regionWidth / textureWidth;   // For the example: 0.6f
float vFactor = regionHeight / textureHeight; // For the example: 0.5f

data[0].t[0] = 0.0f * uFactor;
data[0].t[1] = 0.0f * vFactor;
data[1].t[0] = 1.0f * uFactor;
data[1].t[1] = 0.0f * vFactor;
data[2].t[0] = 0.0f * uFactor;
data[2].t[1] = 1.0f * vFactor;
data[3].t[0] = 1.0f * uFactor;
data[3].t[1] = 1.0f * vFactor;

glPushMatrix();

// translate/scale/bind operations

glTexCoordPointer(2, GL_FLOAT, 0, data[0].t);

Ответ 1

Имейте в виду, что OpenGL отображает текстуры в центрах texel. Поэтому, когда вы используете линейную фильтрацию (например, GL_LINEAR или GL_LINEAR_MIPMAP_LINEAR), точный цвет текселя возвращается только при выборке в центре текселя. Таким образом, когда вы хотите использовать субрегион текстуры, вам нужно отступывать ваши координаты текстуры наполовину текселем (или 0.5/width и 0.5/height). В противном случае фильтрация будет смешать границу текстуры с neigbouting texels вне вашего предполагаемого региона. Это вызывает вашу слегка розоватую границу. Если вы используете всю текстуру, этот эффект компенсируется режимом обтекания GL_CLAMP_TO_EDGE, но при использовании субрегиона GL не знает, где находится ребро, и что фильтрация не должна пересекать его.

Итак, когда вы получили субрегион текстуры в диапазоне [s1,s2]x[t1,t2] (0 <= s,t <= 1), действительный действительный интервал texCoord должен быть [s1+x,s2-x]x[t1+y,t2-y] с x равным 0.5/width и y being 0.5/height ( ширина и высота всей текстуры, соответствующей [0,1]x[0,1]).

Поэтому попробуйте

data[0].t[0] = 0.0f * uFactor + 0.5/textureWidth;
data[0].t[1] = 0.0f * vFactor + 0.5/textureHeight;
data[1].t[0] = 1.0f * uFactor - 0.5/textureWidth;
data[1].t[1] = 0.0f * vFactor + 0.5/textureHeight;
data[2].t[0] = 0.0f * uFactor + 0.5/textureWidth;
data[2].t[1] = 1.0f * vFactor - 0.5/textureHeight;
data[3].t[0] = 1.0f * uFactor - 0.5/textureWidth;
data[3].t[1] = 1.0f * vFactor - 0.5/textureHeight;

Ответ 2

Возможно, это связано с оберткой. Попробуйте это, создав исходное изображение:

glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP )
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP )