La tipica mappatura UV è quella che viene definita una trasformazione affine . Ciò significa che la mappatura di ciascun triangolo tra lo spazio 3D e lo spazio texture può includere rotazione, traduzione, ridimensionamento / squash e inclinazione (ovvero qualsiasi cosa che possiamo fare con una moltiplicazione di matrice omogenea)
La cosa sulle trasformazioni affine è che sono uniformi in tutto il loro dominio - la rotazione, la traduzione, la scala e l'inclinazione che applichiamo alla trama vicino al vertice A sono le stesse di quelle che applichiamo vicino al vertice B, all'interno di un singolo triangolo. Le linee che sono parallele in uno spazio saranno mappate a linee parallele nell'altro, senza mai convergere / divergere.
Ma la graduale rastremazione che stai cercando di applicare non è uniforme: sta mappando linee parallele nella trama a linee convergenti sulla trama. Ciò significa che la scala della trama misurata attraverso la banda cambia continuamente mentre ci muoviamo lungo la striscia. Questo è più di quanto le trasformazioni affine della mappatura UV 2D possano rappresentare accuratamente: l'interpolazione delle coordinate uv 2D tra i vertici adiacenti otterrà una scala coerente lungo l'intero bordo, anche il bordo diagonale che dovrebbe ridursi in scala mentre si sposta lungo la striscia. Quella discrepanza è ciò che crea questo zigzag guerriero.
Questo problema si presenta ogni volta che vogliamo mappare un rettangolo su un trapezio - lati paralleli a lati convergenti: non esiste alcuna trasformazione affine che lo faccia, quindi dobbiamo approssimarlo a tratti, portando a cuciture visibili.
Per la maggior parte degli scopi è possibile ridurre al minimo l'effetto aggiungendo più geometria. Aumentare il numero di suddivisioni lungo la lunghezza della striscia e dividere la striscia in due o più segmenti lungo la sua larghezza, con le diagonali dei triangoli disposti a spina di pesce, può rendere l'effetto molto meno evidente. Sarà sempre presente fino a un certo punto, purché utilizziamo trasformazioni affini.
Ma c'è un modo per aggirarlo. Possiamo usare lo stesso trucco che usiamo per il rendering 3D per disegnare trapezoidi in prospettiva dato pareti e pavimenti rettangolari: usiamo coordinate proiettive !
Tessitura affine:
Texturing proiettivo:
Per fare ciò, dobbiamo aggiungere una terza coordinata uv (uvw) e modificare i nostri shader.
Dato un fattore di scala in ogni punto (diciamo, uguale all'ampiezza della tua striscia in quel punto), puoi costruire la coordinata uvw proiettiva 3D dalle tue normali coordinate uv 2D in questo modo:
Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;
Per applicare queste coordinate uvw 3D alla tua mesh, dovrai usare il Mesh.SetUVs di sovraccarico Vector3 (int channel, List uvs)
E assicurati di cambiare la struttura di input del tuo shader per aspettarti una coordinata di texture 3D (mostrata qui usando lo shader predefinito non illuminato):
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.
Dovrai anche tagliare la macro TRANSFORM_TEX nello shader di vertice, poiché si aspetta un uv 2D:
// 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;
Infine, per tornare a una coordinata di trama 2D per il campionamento di trama, ti basta dividere per la terza coordinata nel tuo shader di frammento :
float2 uv = i.uv.xy / i.uv.z;
Da quando abbiamo creato questa coordinata uvw 3D dalla nostra coordinata 2D desiderata moltiplicandola per lo stesso numero, le due operazioni si annullano e torniamo alla coordinata 2D desiderata originale, ma ora con interpolazione non lineare tra i vertici. : D
È importante eseguire questa divisione per frammento e non nello shader di vertice. Se è fatto per vertice, allora torniamo ad interpolare linearmente le coordinate risultanti lungo ciascun bordo e abbiamo perso la non linearità che stavamo cercando di introdurre con le coordinate proiettive!
id
ecount
? Cosa faUVs.ToArray()
? Come stai caricando i vertici e le coordinate delle trame sulla carta?