#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:
Имейте в виду, что 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), захватываемая текстура по-прежнему включает некоторое слияние цветов пикселей.