Скорее всего, ваша проблема не в ошибках округления, а в неправильном понимании того, как OpenGL отображает тексели в пиксели. Если вы замечаете отдельные ошибки, возможно, это связано с тем, что ваши UV, ваши позиции вершин или пара проекционной матрицы / видового экрана не выровнены относительно того места, где они должны быть.
Чтобы упростить, я просто расскажу о 1D, и предположим, что вы используете проекцию и область просмотра, которые отображают координаты X, Y в эквивалентном расположении пикселей (то есть a 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, что все внутри первого текселя).
В общем, если вы будете следовать общим принципам, которые я изложил, вы никогда не увидите артефактов.
- Используйте Ortho и Viewport точно вашего размера буфера кадра
- Используйте позиции X, X + ширина точно
- Используйте UV, которые точно соответствуют вашим текселям (если вы хотите, чтобы 10 текселей начинались с texel 0, используйте U = 0 до U = 10.
Если где-то в вашей математике есть -1, это, вероятно, не правильно (для позиции или UV).
Чтобы вернуться к вашему примеру, неясно, как вы связываете uvs, которые вы вычисляете, с позициями (так как вы не показываете вычисление позиции).
Также неясно, как вы получили xpos_in_texture (вы должны объяснить, как вы их вычислили для углов вашего спрайта). Я предполагаю, что вы это неправильно вычислили.