Типове УФ-карти - це те, що називається афінним перетворенням . Це означає, що відображення кожного трикутника між тривимірним простором та простором текстури може включати обертання, переклад, масштабування / сквош і скасування (тобто все, що ми можемо зробити з однорідним множенням матриці)
Справа в афінних перетвореннях полягає в тому, що вони рівномірні у всій своїй області - обертання, переклад, масштаб та перекос, які ми застосовуємо до текстури біля вершини A, це те саме, що ми застосовуємо біля вершини B, в будь-якому одному трикутнику. Рядки, паралельні в одному просторі, будуть відображатися на паралельні лінії в іншому, ніколи не збігаючись / розходячись.
Але поступове звуження, яке ви намагаєтеся застосувати, не є рівномірним - це зіставлення паралельних ліній текстури до збіжних ліній на сітці. Це означає, що масштаб текстури, виміряної по всій смузі, постійно змінюється, коли ми рухаємось по смузі. Це більше, ніж афінні перетворення 2D-ультрафіолетового відображення можуть точно представляти: інтерполяція 2D координат uv між сусідніми вершинами отримає одну послідовну шкалу по всьому краю, навіть діагональний край, який повинен скорочуватися в масштабі, коли рухається вниз по смузі. Саме невідповідність - це те, що створює цей кричущий зигзаг.
Цей випуск з'являється в будь-який час, коли ми хочемо зіставити прямокутник на трапецію - паралельну сторону до збіжних сторін: просто немає афінних перетворень, які це роблять, тому ми повинні наблизити його кусочно, що призведе до видимих швів.
Для більшості цілей ви можете мінімізувати ефект, додавши більше геометрії. Збільшення кількості підрозділів по довжині смуги та розбиття смуги на два чи більше сегменти по її ширині з діагоналями трикутників, розташованих за схемою ялинки, можуть зробити ефект значно менш помітним. Він завжди буде присутній до деякої міри, поки ми використовуємо афінну трансформацію.
Але є спосіб її обійти. Ми можемо використовувати той же трюк, який використовуємо для 3D-рендерінга, щоб намалювати трапеції в перспективі заданих прямокутних стін та підлог: ми використовуємо проективні координати !
Вдосконалення текстурування:
Проективне текстурування:
Для цього нам потрібно додати третю координату uv (uvw) та змінити наші шейдери.
Враховуючи коефіцієнт масштабу в кожній точці (скажімо, рівну ширині вашої смуги на цьому місці), ви можете побудувати 3D-проективну координату uvw з вашої звичайної 2D uv координати таким чином:
Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;
Щоб застосувати ці 3D-координати uvw до вашої сітки, вам потрібно використовувати Mesh.SetUVs перевантаження Vector3 (int канал, Список uvs)
Не забудьте змінити вхідну структуру вашого шейдера, щоб очікувати координати 3D текстури (показано тут, використовуючи шейдер, не освітлений за замовчуванням):
struct appdata
{
float4 vertex : POSITION;
float3 uv : TEXCOORD0; // Change float2 to float 3.
};
// Also do this for the uv sent from the vertex shader to the fragment shader.
Вам також потрібно вирізати макрос TRANSFORM_TEX у вершинній шейдері, оскільки він очікує 2D uv:
// o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.uv = v.uv;
// If you define a float4 with the special name _MainTex_ST,
// you can get the same effect the macro had by doing this:
o.uv.xy = o.uv.xy * _MainTex_ST.xy + _MainTex_ST.zw;
Нарешті, щоб повернутись до двовимірної координати текстури для вибірки текстури, ви просто розділите на третю координату у вашому шейдері фрагмента :
float2 uv = i.uv.xy / i.uv.z;
Оскільки ми зробили цю 3D-координату uvw з потрібної 2D координати шляхом множення на одне і те ж число, дві операції скасовуються, і ми повертаємося до початкової бажаної 2D координати, але тепер з нелінійною інтерполяцією між вершинами. : D
Важливо робити цей поділ на фрагмент, а не у вершинній шейдері. Якщо це робиться за вершиною, ми повертаємось до інтерполяції отриманих координат лінійно вздовж кожного краю, і ми втратили нелінійність, яку ми намагалися ввести з проективною координатою!
id
іcount
? Що робитьUVs.ToArray()
? Як ви завантажуєте вершини та координати текстури на карту?