El mapeo UV típico es lo que se llama una transformación afín . Eso significa que el mapeo de cada triángulo entre el espacio 3D y el espacio de textura puede incluir rotación, traslación, escala / aplastamiento y sesgo (es decir, cualquier cosa que podamos hacer con una multiplicación de matriz homogénea)
Lo que pasa con las transformaciones afines es que son uniformes en todo su dominio: la rotación, la traslación, la escala y la inclinación que aplicamos a la textura cerca del vértice A es la misma que aplicamos cerca del vértice B, dentro de cualquier triángulo. Las líneas que son paralelas en un espacio se asignarán a líneas paralelas en el otro, nunca convergentes / divergentes.
Pero la reducción gradual que está tratando de aplicar no es uniforme: está mapeando líneas paralelas en la textura a líneas convergentes en la malla. Eso significa que la escala de la textura medida a través de la banda está cambiando continuamente a medida que avanzamos por la franja. Eso es más de lo que las transformaciones afines del mapeo UV 2D pueden representar con precisión: la interpolación de coordenadas uv 2D entre vértices adyacentes obtendrá una escala consistente a lo largo de todo el borde, incluso el borde diagonal que debería reducirse a medida que avanza por la franja. Esa falta de coincidencia es lo que crea este zigzag chirriante.
Este problema surge cada vez que queremos mapear un rectángulo a un trapecio: lados paralelos a lados convergentes: simplemente no hay transformación afín que haga esto, por lo que tenemos que aproximarlo por partes, lo que lleva a costuras visibles.
Para la mayoría de los propósitos, puede minimizar el efecto agregando más geometría. Aumentar el número de subdivisiones a lo largo de la tira y dividir la tira en dos o más segmentos a lo largo de su ancho, con las diagonales de los triángulos dispuestos en un patrón de espiga, puede hacer que el efecto sea mucho menos notable. Sin embargo, siempre estará presente en cierta medida siempre que estemos usando transformaciones afines.
Pero hay una forma de evitarlo. Podemos usar el mismo truco que usamos para el renderizado 3D para dibujar trapecios en perspectiva dados los muros y pisos rectangulares: ¡usamos coordenadas proyectivas !
Texturas afines:
Texturas proyectivas:
Para hacer esto, necesitamos agregar una tercera coordenada uv (uvw) y modificar nuestros sombreadores.
Dado un factor de escala en cada punto (digamos, igual a la amplitud de su tira en ese punto), puede construir la coordenada uvw proyectiva 3D a partir de su coordenada uv 2D normal de esta manera:
Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;
Para aplicar estas coordenadas 3D uvw a su malla, necesitará usar Mesh.SetUVs de sobrecarga de Vector3 (int channel, List uvs)
Y asegúrese de cambiar la estructura de entrada de su sombreador para esperar una coordenada de textura 3D (que se muestra aquí usando el sombreador apagado predeterminado):
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.
También deberá cortar la macro TRANSFORM_TEX en el sombreador de vértices, ya que espera 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;
Finalmente, para volver a una coordenada de textura 2D para el muestreo de textura, simplemente divida por la tercera coordenada en su sombreador de fragmentos :
float2 uv = i.uv.xy / i.uv.z;
Como hicimos esta coordenada uvw 3D a partir de nuestra coordenada 2D deseada multiplicando por el mismo número, las dos operaciones se cancelan y volvemos a nuestra coordenada 2D original deseada, pero ahora con interpolación no lineal entre los vértices. :RE
Es importante hacer esta división por fragmento y no en el sombreador de vértices. Si se hace por vértice, entonces volvemos a interpolar las coordenadas resultantes linealmente a lo largo de cada borde, ¡y hemos perdido la no linealidad que estábamos tratando de introducir con la coordenada proyectiva!
id
ycount
? ¿QuéUVs.ToArray()
hacer? ¿Cómo carga los vértices y las coordenadas de textura en la tarjeta?