Я пишу 2D игру с помощью OpenGL. Когда я хочу блитировать часть структуры как спрайт, я использую glTexCoord2f (u, v) для определения ультрафиолетовых координат, с u и v, вычисленным как это:
GLfloat u = (GLfloat)xpos_in_texture/(GLfloat)width_of_texture;
GLfloat v = (GLfloat)ypos_in_texture/(GLfloat)height_of_texture;
Это работает отлично большую часть времени, кроме тех случаев, когда я использую glScale для увеличения масштаба игры или. Затем погрешности округления с плавающей точкой заставляют некоторые пиксели быть оттянутыми один направо от или один ниже намеченного прямоугольника в структуре.
Что может быть сделано об этом? В данный момент я вычитаю значение 'эпсилона' из правых краев и базовых краев прямоугольника, и это, кажется, работает, но это походит на ужасный клудж. Есть ли какие-либо лучшие решения?
Выполните деление как двойное, округлите результат вниз до желаемого уровня точности, затем преобразуйте его в GLFloat.
Ваши xpos / ypos должны быть основаны на от 0 до (ширина или высота) - 1, а затем:
GLfloat u = (GLfloat)xpos_in_texture/(GLfloat)(width_of_texture - 1);
GLfloat v = (GLfloat)ypos_in_texture/(GLfloat)(height_of_texture - 1);
Скорее всего, ваша проблема связана не с ошибками округления, а с непониманием того, как OpenGL сопоставляет тексели с пикселями. Если вы замечаете ошибки "off-by-one", это, вероятно, потому, что ваши UV, позиции вершин или ваша проекционная матрица/пара видовых экранов не выровнены там, где они должны быть.
Для упрощения я буду говорить только о 1D, и буду считать, что вы используете проекцию и видовой экран, которые отображают координаты X,Y на эквивалентное расположение пикселей (т.е. glOrtho(0,width,0,height,zmin,zmax)
и glViewport(0,width,0,height)
).
Скажем, вы хотите нарисовать 5 текселей (начиная с 0 для простоты) вашей 64-широкой текстуры, отображающейся на 10 пикселях (масштаб 2) вашего экрана, начиная с пикселя 20.
Чтобы добиться этого, нарисуйте треугольник с координатами X 20 и 30, и U (из пары UV) 10/64 и 15/64. Растеризация OpenGL создаст 10 пикселей для затенения с координатами X 20.5, 21.5, ... 29.5. Обратите внимание, что позиции не являются полными целыми числами. OpenGL растеризует в середине пикселя.
Аналогично, он сгенерирует U-координаты 10.25/64, 10.75/64, 11.25/64, 11.75/64 ... 14.25/64, 14.75/64. Заметим еще раз, что координаты текселей, приведенные к позициям текселей в пространстве текстур, не являются полными целыми числами. OpenGL делает выборку из середины расположения текселей, так что это нормально.
То, как сэмплеры используют эти UV для генерации значений текселей, зависит от режимов фильтрации, но будь то ближайшая или линейная, пиксели должны содержаться исключительно внутри интересующих текселей (0.25 с размером 0.5 должен использовать только цвет от 0 до 0.5, который находится внутри первого текселя).
В целом, если вы будете следовать общим принципам, которые я изложил, вы никогда не увидите артефактов.
Если у вас в математике где-то есть -1, то это, скорее всего, неправильно (для позиции или UVs).
Возвращаясь к вашему примеру, неясно, как вы связываете вычисленные вами uvs с позициями (поскольку вы не показываете вычисление позиций). Также неясно, как вы получили xpos_in_texture (вы должны объяснить, как вы вычислили их для углов вашего спрайта). Я предполагаю, что вы вычислили это неправильно.