Проблема з використанням текстурних атласів та протікання суміжних текстилів пов'язана з тим, як працює лінійна фільтрація текстур.
Для будь-якої точки текстури, яка не відбирається в центрі текстулі, лінійний відбір проб відбирає 4 суміжних текселя та обчислює значення в тому місці, яке ви запитували, як середньозважене (виходячи з відстані від точки вибірки) середнього рівня для всіх 4 зразки.
Ось приємна візуалізація проблеми:
Оскільки ви не можете використовувати щось на кшталт GL_CLAMP_TO_EDGE
атласу текстури, вам потрібно створити межі текстури навколо краю кожної текстури. Ці межові текстилі не дозволять сусіднім зразкам абсолютно різних текстур в атласі змінити зображення через зважену інтерполяцію, пояснену вище.
Зауважте, що при використанні анізотропної фільтрації може знадобитися збільшити ширину межі. Це відбувається тому, що анізотропна фільтрація збільшить розмір сусідства зразка під крайніми кутами.
Щоб проілюструвати, що я маю на увазі, використовуючи рамку навколо краю кожної текстури, розгляньте різні режими обгортання, наявні в OpenGL. Зверніть особливу увагу на CLAMP TO EDGE
.
Незважаючи на те, що існує режим під назвою "Затискати до межі", нас насправді це не те, що нас цікавить. Цей режим дозволяє вам визначити один колір, який використовуватиметься як рамка навколо вашої текстури для будь-яких координат текстури, які не виходять із нормованих [0.0 -1,0] діапазон.
Ми хочемо - це повторити поведінку CLAMP_TO_EDGE
, коли будь-яка координата текстури за межами належного діапазону для (під-) текстури отримує значення останнього центру текселя в напрямку, в якому воно було поза межами. Оскільки ви майже повний контроль над координати текстури в системі атласу, єдиний сценарій, в якому (ефективні) координати текстури можуть посилатися на розташування поза вашою текстурою, під час середньозваженого кроку фільтрації текстури.
Ми знаємо, що GL_LINEAR
проведемо вибірку чотирьох найближчих сусідів, як показано на діаграмі вище, тому нам потрібна лише одна-тексельна межа. Можливо, вам знадобиться більш широка рамка текселя, якщо ви використовуєте анізотропну фільтрацію, оскільки вона збільшує розмір сусідства вибірки за певних умов.
Ось приклад текстури, яка більш наочно ілюструє рамку, хоча для своїх цілей ви можете зробити облямівку 1 текселем або 2 текстовими шириною.
(ПРИМІТКА. Межа, яку я маю на увазі, - це не чорний колір навколо всіх чотирьох країв зображення, а область, де шаблон шаблону перестає регулярно повторюватися)
Якщо вам було цікаво, ось чому я продовжую висувати анізотропну фільтрацію. Це змінює форму сусіднього зразка на основі кута і може спричинити використання більше 4 текстових тканин для фільтрації:
http://www.arcsynthesis.org/gltut/Texturing/ParallelogramDiag.svg
Чим більший ступінь використання анізотропії, тим більше шансів на те, що вам доведеться мати справу з примірними районами, що містять більше 4 текстолів. Рамка з двома текселями повинна бути достатньою для більшості ситуацій з анізотропною фільтрацією.
І останнє, але не менш важливе, ось, як будувався би атлас текстур, який би повторював GL_CLAMP_TO_EDGE
поведінку за наявності GL_LINEAR
текстурного фільтра:
( Відніміть 1 від X і Y у чорних координатах, я не довів прочитати зображення перед публікацією. )
Через обмежене зберігання для зберігання 4 текстур 256x256 в цьому атласі потрібна текстура розмірами 516x516. Межі кольором кодуються на основі того, як ви заповнили їх текстовими даними під час створення атласу:
- Червоний = Замініть текселем прямо внизу
- Жовтий = Замініть текселем прямо вгорі
- Зелений = Замініть текселем прямо зліва
- Синій = Замініть текселем прямо праворуч
Ефективно в цьому упакованому прикладі кожна текстура в атласі використовує область 258x258 атласу, але ви будете генерувати координати текстури, які відображають у видимій області 256x256. Окантовуючі текстилі використовуються лише коли фільтрування текстур робиться по краях фактур в атласі, і спосіб їх оформлення імітує GL_CLAMP_TO_EDGE
поведінку.
Якщо вам було цікаво, ви можете реалізувати інші типи режимів обгортання, використовуючи аналогічний підхід - GL_REPEAT
це можна реалізувати шляхом обміну лівої / правої та верхньої / нижньої меж текстильної текстури в атласі текстури та трохи розумної математики координат текстури в шейдер. Це трохи складніше, тому зараз не турбуйтеся про це. Оскільки ви маєте справу лише з спрайтовими листами, обмежтесь GL_CLAMP_TO_EDGE
:)
GL_NEAREST
абоGL_LINEAR
для рендерингу текстури?