Координаты выборки текстур для визуализации спрайта

Скажем, у нас есть текстура (в данном случае 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