O mapeamento UV típico é chamado de transformação afim . Isso significa que o mapeamento de cada triângulo entre o espaço 3D e o espaço da textura pode incluir rotação, tradução, redimensionamento / squash e inclinação (ou seja, qualquer coisa que possamos fazer com uma multiplicação de matriz homogênea)
A questão das transformações afins é que elas são uniformes em todo o domínio - a rotação, a translação, a escala e a inclinação que aplicamos à textura perto do vértice A é a mesma que aplicamos perto do vértice B, dentro de qualquer triângulo. Linhas paralelas em um espaço serão mapeadas para linhas paralelas no outro, nunca convergindo / divergindo.
Mas o afilamento gradual que você está tentando aplicar não é uniforme - ele está mapeando linhas paralelas na textura para linhas convergentes na malha. Isso significa que a escala da textura medida na banda está mudando continuamente à medida que avançamos na faixa. Isso é mais do que as transformações afins do mapeamento UV 2D podem representar com precisão: a interpolação de coordenadas uv 2D entre vértices adjacentes obterá uma escala consistente ao longo de toda a borda, até a borda diagonal que deve estar diminuindo de escala à medida que se move pela faixa. Essa incompatibilidade é o que cria esse ziguezague de guerra.
Esse problema surge a qualquer momento que queremos mapear um retângulo para um trapézio - lados paralelos para lados convergentes: simplesmente não há transformação afim que faz isso, por isso temos que aproximá-lo por partes, levando a costuras visíveis.
Para a maioria dos propósitos, você pode minimizar o efeito adicionando mais geometria. Aumentar o número de subdivisões ao longo do comprimento da faixa e dividi-la em dois ou mais segmentos ao longo de sua largura, com as diagonais dos triângulos dispostos em um padrão de espinha de peixe, pode tornar o efeito muito menos perceptível. Ele sempre estará presente até certo ponto, enquanto estivermos usando transformações afins.
Mas há uma maneira de contornar isso. Podemos usar o mesmo truque que usamos na renderização 3D para desenhar trapézios em perspectiva, dadas paredes e pisos retangulares: usamos coordenadas projetivas !
Texturas afins:
Texturização projetiva:
Para fazer isso, precisamos adicionar uma terceira coordenada uv (uvw) e modificar nossos shaders.
Dado um fator de escala em cada ponto (digamos, igual à largura da sua faixa nesse ponto), você pode construir a coordenada uvw projetiva em 3D a partir da coordenada uv 2D 2D normal da seguinte maneira:
Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;
Para aplicar essas coordenadas uvw 3D à sua malha, você precisará usar a sobrecarga Vector3 Mesh.SetUVs (int channel, List uvs)
E certifique-se de alterar a estrutura de entrada do seu sombreador para esperar uma coordenada de textura 3D (mostrada aqui usando o sombreador apagado padrão):
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.
Você também precisará recortar a macro TRANSFORM_TEX no sombreador de vértices, pois espera um 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;
Por fim, para retornar a uma coordenada de textura 2D para amostragem de textura, basta dividir pela terceira coordenada no seu shader de fragmento :
float2 uv = i.uv.xy / i.uv.z;
Como fizemos essa coordenada uvw 3D a partir da coordenada 2D desejada multiplicando pelo mesmo número, as duas operações cancelam e voltamos à coordenada 2D desejada original, mas agora com interpolação não linear entre os vértices. : D
É importante fazer essa divisão por fragmento e não no shader de vértice. Se for feito por vértice, voltaremos a interpolar linearmente as coordenadas resultantes ao longo de cada aresta e perdemos a não linearidade que estávamos tentando introduzir com a coordenada projetiva!
id
ecount
? O queUVs.ToArray()
faz? Como você está carregando os vértices e as coordenadas de textura no cartão?