2015-05-21 4 views
1

(С этим вопросом я пытаюсь исследовать идею я имел для решения this other one)Отображение текстуры из «1D» в «2D» с матрицей OpenGL преобразований

Если у меня есть стандартный 2D массив размеры ширина и высота в памяти, можно превратить это в 1D массив длины ширина * высота, а затем индекс его через индекс = х + у * ширина. Это сопоставление чрезвычайно полезно при распределении и освобождении памяти для массива, поскольку менеджеру памяти не нужно беспокоиться о том, чтобы упаковать структуры в 2D, но нужно только беспокоиться об общей длине каждого выделенного массива, если он выражен в 1D.

Я пытаюсь посмотреть, могу ли я использовать этот же подход для управления памятью изображений для текстур OpenGL. Идея (как описано в вышеупомянутом связанном вопросе) состоит в том, чтобы объединить целую кучу необходимых текстур в одну большую ее часть (т. Е. Нарисовать их рядом друг с другом) в большую текстуру. Это помогает минимизировать дорогостоящие операции связывания текстур во время рендеринга.

Скажем, моя большая текстура 8 пикселей (всего есть 64 пикселей):

8x8 texture:    5x5 image:   4x5 image: 

    | 0 1 2 3 4 5 6 7   | 0 1 2 3 4   | 0 1 2 3 
---+-----------------  ---+-----------  ---+--------- 
0 | . . . . . . . .   0 | A B C D E   0 | a b c d 
1 | . . . . . . . .   1 | F G H I J   1 | e f g h 
2 | . . . . . . . .   2 | K L M N O   2 | i j k l 
3 | . . . . . . . .   3 | P Q R S T   3 | m n o p 
4 | . . . . . . . .   4 | U V W X Y   4 | q r s t 
5 | . . . . . . . . 
6 | . . . . . . . . 
7 | . . . . . . . . 

И я хотел бы хранить 5 × 5 изображений и 5 изображений в нем (то есть 25 + 20 = 45 пикселей). Технически, у меня есть много доступных пикселей, но я не могу разместить эти изображения рядом друг с другом в большой текстуре, поскольку для этого потребуется минимальный размер 9 в одном направлении и 5 в другом.

Если бы я мог просто относиться к моим 8 текстуру 64 продолжают пиксели памяти и отображать два изображения в 1D блоки памяти внутри, что я мог бы расположить изображения следующим образом внутри текстуры: x8 текстуры:

| 0 1 2 3 4 5 6 7 
---+----------------- 
0 | A B C D E F G H 
1 | I J K L M N O P    
2 | Q R S T U V W X 
3 | Y a b c d e f g    
4 | h i j k l m n o    
5 | p q r s t . . . 
6 | . . . . . . . . 
7 | . . . . . . . . 

Если я рисую все свои изображения по шкале от 1: 1, то есть без дробных координат пикселей в любом месте и не нужно никакой линейной фильтрации или другого смешивания пикселей, можно ли создать матрицу преобразования, использовать для рисования 5 изображений с использованием этой текстуры?

С вершин и фрагментов шейдеров, это выглядит, как это может быть довольно легко (если я не забыть что-то, я не пробовал):

  • вершинный шейдер отображает четыре угла изображение, чтобы привлечь к текстуре, выраженной в виде 64 × 1 изображения:

    • a: (0, 0) → (0 + 0 * 4 + 25, 0) = (25, 0)        , где 25 - смещение 4 × 5 изображения
    • d: (3, 0) → (3 + 0 * 4 + 25, 0) = (28, 0)
    • q: (0, 4) → (0 + 4 * 4 + 25, 0) = (41, 0)
    • t: (3, 4) → (3 + 4 * 4 + 25, 0) = (44, 0)

    интерполяция других координат внутри текстуры должно (?) затем также отобразить на правое смещение вдоль этой линии для целых координат

  • фрагмент шейдер преобразует 64 × 1-координата в конечный 8 координат, просто беря частное и остаток от деления на 8, например:
    • a: (0, 25) → (25% 8, 25/8) = (1, 3)
    • d: (0, 28) → (28% 8, 28/8) = (4, 3)
    • k: (0, 35) → (35% 8, 35/8) = (3, 4)
    • q: (0, 41) → (41% 8, 41/8) = (1, 5)
    • t: (0, 44) → (44% 8, 44/8) = (4, 5)

К сожалению пользовательские шейдеры требуют OpenGL ES v2.0 или выше, которая не доступна на всех устройствах.

Возможно ли достичь такого соответствия только посредством матричных преобразований, предлагаемых OpenGL ES 1.1?

+1

Обратите внимание, что процент активных устройств, которые не поддерживают по меньшей мере ES 2.0, упал настолько низко что Google прекратил отслеживать его (http://developer.android.com/about/dashboards). Я считаю, что это было около 1-2%, когда они публиковали последние номера для ES 1.1. На самом деле я бы больше беспокоился о том, насколько хорошо реализованы версии ES 1.1 на новых устройствах, учитывая, насколько они устарели. –

+0

Насколько я знаю, это не так, поскольку это не было бы линейным преобразованием и поэтому не может быть представлено матрицей. – chbaker0

+0

@RetoKoradi Хорошая точка. Я должен обязательно проверить последствия для производительности. В целом я стараюсь поддерживать как можно больше устройств, если это не вызовет проблемы для более современных. Однако я был бы удивлен, если бы стандартные преобразования матриц стали более медленными на современных устройствах. Это все еще стандартный способ делать что-то, нет? –

ответ

0

Я не пробовал это, но я хотел бросить его там, как идея уже:

UPDATE: Я попробовал это сейчас, и это прекрасно работает с одним небольшим изменением (см комментарий)!

Скажем, моя большая текстура имеет ширину size и изображение, которое я хочу обратить имеет ширину width и начинается смещение offset внутри большой текстуры, где offset является 1-D представление смещения, т.е. x + y * size.

Тогда следующая матрица 4х4 будет почти достичь этого отображения:

 _           _ 
    |  1  width  offset  0 | 
    |            | 
    | 1/size width/size offset/size 0 | 
M = |            | 
    |  0   0   0   0 | 
    |            | 
    |_  0   0   0   1 _| 

Таким образом, в приведенном выше примере, чтобы нарисовать 5 изображений, матрица будет

_     _ 
| 1 4 25 0 | 
| 1/8 1/2 25/8 0 | 
| 0 0  0 0 | 
|_ 0 0  0 1 _| 

координаты изображения затем должны быть указаны с помощью 4-вектора, содержащего

(x, y, 1, 1) 

Так, например, координаты k (т.е. (2,2)) будет отображаться по адресу:

M*(2, 2, 1, 1) => (35, 4.375, 0, 1) 

который будет интерпретирован как координата текстуры (35, 4.375).

Если мы обратимся теперь на ближайшего соседа, как правило, интерполяции и включить текстуры оборачивать в направлении х, то это должно соответствовать:

(3, 4) 

(я использовал целые координаты здесь, в то время как в окончательной реализации конечные координаты должны были бы быть поплавками в диапазоне от 0 до 1. Этого можно было бы достичь очень легко, заменив 1 в нижнем правом углу матрицы на size, так как это закончится в четвертом положении выхода вектор и, таким образом, разделите остальные три. Это, как указал @ chbaker0, будет работать, хотя, если координаты текстуры подчиняются обычным перспективам ive раздел. Если это не так, то для достижения желаемого результата необходимо разделить M всю матрицу на size.)

Это действительно разумно или может кто-то увидеть проблему с этим, прежде чем я начну и попытаюсь реализовать это ? (Возьмите меня через несколько дней, так как я должен сделать еще пару вещей, чтобы добраться до тестируемого приложения ...)

+1

«Этого можно добиться очень легко, заменив 1 в нижнем правом углу матрицы на размер, так как это закончится в четвертой позиции выходного вектора и, таким образом, разделит остальные три. " Я не уверен, что координаты текстуры подлежат разделению перспективы. Спецификация также не слишком ясна: https://www.khronos.org/registry/gles/specs/1.1/es_full_spec_1.1.12.pdf раздел 2.10. Я прочитал это, и из моего чтения я понимаю, что это * не * подвержено перспективному разделению. – chbaker0

+0

@ chbaker0 Удивительный! У меня возникли проблемы с поиском хорошего справочного руководства. Это кажется отличным! Спасибо за ссылку! Если координаты текстуры не подлежат разделению перспективы, все, что нужно сделать, состоит в том, чтобы разделить всю матрицу на «размер» вместо замены нижнего правого '1'. Так что это не должно быть разрывом сделки в любом случае ... Но я запомню это в ответе. –

+0

Это лучший вариант, это официальная спецификация OpenGL ES 1.1, опубликованная Khronos :) Я постараюсь немного поработать над бумагой завтра, потому что, хотя моя кишка говорит, что это не может быть сделано с матрицами, у вас есть хорошие моменты. – chbaker0

Смежные вопросы