Координаты выборки текстур для визуализации спрайта
Скажем, у нас есть текстура (в данном случае 8х8 пикселей), которую мы хотим использовать в качестве листа спрайтов. Одним из суб-изображений (спрайт) является субрегион 4x3 внутри текстуры, как на этом изображении:
![enter image description here]()
(Отображены нормализованные координаты текстур четырех углов)
Теперь есть два способа назначить координаты текстуры квадрату размера 4 пикселя x 3 пикселя, чтобы он эффективно стал спрайтом, который мы ищем; Первым и самым простым является выбор текстуры в углах субрегиона:
![enter image description here]()
// Texture coordinates
GLfloat sMin = (xIndex0 ) / imageWidth;
GLfloat sMax = (xIndex0 + subregionWidth ) / imageWidth;
GLfloat tMin = (yIndex0 ) / imageHeight;
GLfloat tMax = (yIndex0 + subregionHeight) / imageHeight;
Хотя при первом внедрении этого метода, ок. 2010, я понял, спрайты выглядели слегка "искаженными". После небольшого поиска я наткнулся на сообщение на форумах cocos2d, объяснив, что "правильный путь" для образца текстуры при визуализации спрайта таков:
![enter image description here]()
// Texture coordinates
GLfloat sMin = (xIndex0 + 0.5) / imageWidth;
GLfloat sMax = (xIndex0 + subregionWidth - 0.5) / imageWidth;
GLfloat tMin = (yIndex0 + 0.5) / imageHeight;
GLfloat tMax = (yIndex0 + subregionHeight - 0.5) / imageHeight;
... и после исправления моего кода я был рад на некоторое время. Но где-то по пути, и я считаю, что это связано с введением iOS 5, я начал чувствовать, что мои спрайты выглядят не очень хорошо. После некоторого тестирования я переключился на "синий" метод (второе изображение), и теперь они выглядят хорошо, но не всегда.
Я схожу с ума, или что-то изменилось с iOS 5, связанным с отображением текстуры GL ES? Возможно, я делаю что-то еще неправильно? (например, координаты позиции вершин немного выключены? Неправильные параметры настройки текстуры?) Но моя база кода не изменилась, поэтому, возможно, я делаю что-то неправильно с самого начала...?
Я имею в виду, по крайней мере, с моим кодом, кажется, что "красный" метод использовался правильно, но теперь "синий" метод дает лучшие результаты.
Сейчас моя игра выглядит нормально, но я чувствую, что есть что-то наполовину неправильное, что я должен решить рано или поздно...
Любые идеи/переживания/мнения?
ДОПОЛНЕНИЕ
Чтобы сделать спрайт выше, я бы нарисовал квадрат размером 4x3 в орфографической проекции, причем каждая вершина назначала текстурные коорды, указанные в упомянутом выше коде, например:
// Top-Left Vertex
{ sMin, tMin };
// Bottom-Left Vertex
{ sMin, tMax };
// Top-Right Vertex
{ sMax, tMin };
// Bottom-right Vertex
{ sMax, tMax };
Исходный квадрат создается из (-0,5, -0,5) до (+0,5, +0,5); то есть это единичный квадрат в центре экрана, а затем масштабируется до размера субрегиона (в данном случае 4x3), а его центр расположен с целыми (x, y) координатами. Я чувствую, что это тоже нужно делать, особенно если ни ширина, ни высота, ни то, и другое даже не являются?
ДОБАВЛЕНИЕ 2
Я также нашел эту статью, но я все еще пытаюсь собрать ее (это 4:00 здесь)
http://www.mindcontrol.org/~hplus/graphics/opengl-pixel-perfect.html
Ответы
Ответ 1
Там немного больше этого изображения, чем кажется на первый взгляд, координаты текстуры не являются единственным фактором, в котором происходит выборка текстуры. В вашем случае я считаю, что синий, вероятно, тот, который хочет иметь.
То, что вы в конечном итоге хотите, - это образец каждого текселя в центре. Вы не хотите брать образцы на границе между двумя текселями, потому что они либо объединяют их с линейной выборкой, либо произвольно выбирают один или другой с ближайшим, в зависимости от того, каким образом округляются вычисления с плавающей точкой.
Сказав это, вы можете подумать, что не хотите, чтобы ваши texcoords находились в (0,0), (1,1) и других углах, потому что они находятся на границе текселя. Однако важно отметить, что opengl отображает текстуры в центре фрагмента.
Для супер простого примера рассмотрим монитор размером 2 на 2 пикселя с текстурой размером 2 на 2 пикселя.
Если вы нарисуете квадрат от (0,0) до (2,2), это будет охватывать 4 пикселя. Если текстура отображает этот квадрат, ему нужно будет взять 4 образца из текстуры.
Если ваши координаты текстуры идут от 0 до 1, тогда opengl будет интерполировать это и образец из центра каждого пикселя, а нижний левый texcoord начинается в нижнем левом углу нижнего левого пикселя. Это, в конечном счете, порождает пары texcoord (0,25, 0,25), (0,75,0,75), (0,25, 0,75) и (0,75, 0,25). Который помещает образцы прямо в середину каждого текселя, что вы хотите.
Если вы компенсируете свои текскоды на половину пикселя, как в красном примере, то он будет интерполировать неправильно, и вы в конечном итоге отнесете текстуру от центра текселей.
Короче говоря, вы хотите убедиться, что ваши пиксели правильно совпадают с вашими текселями (не рисуйте спрайты в нецелочисленных пиксельных местоположениях) и не уменьшайте спрайты произвольными суммами.
Если синий квадрат дает вам плохие результаты, вы можете привести пример изображения или описать, как вы его рисуете?
Фото говорит 1000 слов:
![img]()