Typisches UV-Mapping ist eine sogenannte affine Transformation . Das bedeutet, dass die Zuordnung jedes Dreiecks zwischen 3D-Raum und Texturraum Rotation, Translation, Skalierung / Squash und Skew umfassen kann (dh alles, was wir mit einer homogenen Matrixmultiplikation tun können).
Die Sache mit affinen Transformationen ist, dass sie über ihre gesamte Domäne hinweg einheitlich sind - die Rotation, Translation, Skalierung und der Versatz, die wir auf die Textur in der Nähe von Scheitelpunkt A anwenden, sind die gleichen wie die, die wir in der Nähe von Scheitelpunkt B innerhalb eines Dreiecks anwenden. Linien, die in einem Raum parallel sind, werden parallelen Linien im anderen zugeordnet, ohne zu konvergieren / divergieren.
Die allmähliche Verjüngung, die Sie anwenden möchten, ist jedoch nicht einheitlich. Sie ordnet parallele Linien in der Textur konvergierenden Linien im Netz zu. Das bedeutet, dass sich die Skala der über das Band gemessenen Textur kontinuierlich ändert, wenn wir uns den Streifen entlang bewegen. Das ist mehr, als die affinen Transformationen der 2D-UV-Abbildung genau darstellen können: Durch Interpolation von 2D-UV-Koordinaten zwischen benachbarten Scheitelpunkten wird eine konsistente Skalierung entlang der gesamten Kante erhalten, selbst die diagonale Kante, deren Skalierung schrumpfen sollte, wenn sie sich entlang des Streifens bewegt. Diese Nichtübereinstimmung schafft diesen trälelnden Zickzack.
Dieses Problem tritt immer dann auf, wenn wir ein Rechteck einem Trapez zuordnen möchten - parallele Seiten zu konvergierenden Seiten: Es gibt einfach keine affine Transformation, die dies tut, daher müssen wir es stückweise approximieren, was zu sichtbaren Nähten führt.
In den meisten Fällen können Sie den Effekt minimieren, indem Sie mehr Geometrie hinzufügen. Durch Erhöhen der Anzahl der Unterteilungen entlang der Länge des Streifens und Aufteilen des Streifens in zwei oder mehr Segmente entlang seiner Breite, wobei die Diagonalen der Dreiecke in einem Fischgrätenmuster angeordnet sind, kann der Effekt viel weniger auffällig werden. Es wird immer bis zu einem gewissen Grad vorhanden sein, solange wir affine Transformationen verwenden.
Aber es gibt einen Weg, um das zu umgehen. Wir können denselben Trick verwenden, den wir für das 3D-Rendering verwenden, um Trapezoide bei rechteckigen Wänden und Böden perspektivisch zu zeichnen: Wir verwenden projektive Koordinaten !
Affine Texturierung:
Projektive Texturierung:
Dazu müssen wir eine dritte UV-Koordinate (UVW) hinzufügen und unsere Shader ändern.
Wenn Sie an jedem Punkt einen Skalierungsfaktor angeben (z. B. gleich der Breite Ihres Streifens an dieser Stelle), können Sie die projektive 3D-UVW-Koordinate aus Ihrer regulären 2D-UV-Koordinate folgendermaßen konstruieren:
Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;
Um diese 3D-UVW-Koordinaten auf Ihr Netz anzuwenden, müssen Sie die Vector3-Überlast Mesh.SetUVs (int channel, List uvs) verwenden.
Ändern Sie unbedingt die Eingabestruktur Ihres Shaders, um eine 3D-Texturkoordinate zu erwarten (hier mit dem standardmäßigen unbeleuchteten Shader dargestellt):
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.
Sie müssen auch das TRANSFORM_TEX-Makro im Vertex-Shader ausschneiden, da es eine 2D-UV erwartet:
// 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;
Um zu einer 2D-Texturkoordinate für die Texturabtastung zurückzukehren, dividieren Sie einfach durch die dritte Koordinate in Ihrem Fragment-Shader :
float2 uv = i.uv.xy / i.uv.z;
Da wir diese 3D-UVW-Koordinate aus unserer gewünschten 2D-Koordinate durch Multiplizieren mit derselben Zahl erstellt haben, werden die beiden Operationen aufgehoben und wir kehren zu unserer ursprünglichen gewünschten 2D-Koordinate zurück, jedoch jetzt mit nichtlinearer Interpolation zwischen den Scheitelpunkten. : D.
Es ist wichtig, diese Aufteilung pro Fragment und nicht im Vertex-Shader vorzunehmen. Wenn dies pro Scheitelpunkt erfolgt, werden die resultierenden Koordinaten wieder linear entlang jeder Kante interpoliert, und wir haben die Nichtlinearität verloren, die wir mit der projektiven Koordinate einführen wollten!
id
undcount
? Was machtUVs.ToArray()
das Wie lade ich die Eckpunkte und Texturkoordinaten auf die Karte hoch?