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

#c #opengl-es #textures

#c #opengl-es #Текстуры

Вопрос:

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

Вот идея того, что я описываю. В этом случае я бы хотел выбрать зелено-белую область размером 6×5, но то, что рендерит OpenGL, включает в себя легкий розовый оттенок в верхнем и левом пикселях. Иллюстрация смещения

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

Результирующая текстура на выходе

Я могу исправить это, добавив смещение к координатам текстуры перед передачей их в 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. gamedev.stackexchange.com/questions/46963/…

Ответ №1:

Имейте в виду, что OpenGL сэмплирует текстуры в центрах texel. Таким образом, при использовании линейной фильтрации (например, GL_LINEAR или GL_LINEAR_MIPMAP_LINEAR ) точный цвет текселя возвращается, только если выборка производится в центре текселя. Таким образом, если вы хотите использовать только подобласть текстуры, вам нужно сделать отступ в координатах текстуры на половину текселя (или 0.5/width и 0.5/height ). В противном случае фильтрация смешает границу текстуры с соседними текселями за пределами вашей предполагаемой области. Это приводит к слегка розоватой границе. Если вы используете всю текстуру целиком, этот эффект компенсируется 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;
  

Комментарии:

1. Это действительно близко, если я добавлю 0,5 f ко всем координатам, это исправит некоторые, но испортит другие. Если я добавляю / вычитаю, как вы упомянули, я не получаю никаких артефактов границ, но в изображении все еще происходит некоторое искажение пиксельных данных

2. Это тестовые рендеры с использованием двухцветных фигур, подобных приведенным выше. Без использования смещений: bit.ly/ioKuV7 . Добавление половины ко всем координатам: bit.ly/mklitW . Добавление / вычитание половины, как в вашем примере: bit.ly/m8O5dd

3. Вы могли бы попробовать также выровнять координаты ваших вершин по центрам пикселей, что означает корректировку их на половину пикселя (в координатах вида, конечно). В противном случае они немного отличаются от координат текстуры, что означает, что вы получили прямоугольную форму axb с текстурой cxd. Если вам нужно текстурирование с точностью до пикселя, вам нужны a == c и b == d. Поэтому выполните ту же настройку из texCoords и для позиций. Тогда размеры совпадают.

4. Кристиан, я собираюсь еще немного поиграть с этими значениями, но я думаю, что ты прав, и окончательное решение просто потребует еще немного доработки. В любом случае, мы достаточно близки, и команда разработчиков довольна, поэтому я собираюсь принять ваш ответ. Еще раз спасибо!

Ответ №2:

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

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

Комментарии:

1. Это улучшает результат, но общее изображение по-прежнему отсутствует. Кажется, это сработало, чтобы зафиксировать верхнюю и левую стороны, но поскольку это не изменяет вершину (1,1), захватываемая текстура по-прежнему включает некоторое слияние цветов пикселей.