Типичное УФ-картирование - это то, что называется аффинным преобразованием . Это означает, что отображение каждого треугольника между трехмерным пространством и текстурным пространством может включать в себя вращение, перемещение, масштабирование / сдвиг и наклон (т. Е. Все, что мы можем сделать с однородным умножением матриц)
Суть аффинных преобразований в том, что они однородны по всей своей области - вращение, перемещение, масштабирование и перекос, которые мы применяем к текстуре около вершины A, совпадает с тем, что мы применяем около вершины B внутри любого одного треугольника. Линии, параллельные в одном пространстве, будут отображаться на параллельные линии в другом, никогда не сходясь / не расходясь.
Но постепенное сужение, которое вы пытаетесь применить, не является равномерным - это сопоставление параллельных линий в текстуре со сходящимися линиями в сетке. Это означает, что масштаб текстуры, измеряемой по всей полосе, непрерывно меняется при движении вниз по полосе. Это больше, чем могут точно представить аффинные преобразования 2D UV-картирования: интерполяция 2D UV-координат между смежными вершинами даст один согласованный масштаб по всему краю, даже по диагональному краю, который должен уменьшаться в масштабе при перемещении вниз по полосе. Это несоответствие - то, что создает этот трогательный зигзаг.
Эта проблема возникает всякий раз, когда мы хотим отобразить прямоугольник на трапецию - параллельные стороны к сходящимся сторонам: просто нет аффинного преобразования, которое делает это, поэтому мы должны приблизить его кусочно, приводя к видимым швам.
Для большинства целей вы можете минимизировать эффект, добавив больше геометрии. Увеличение количества делений по длине полосы и разделение полосы на два или более сегмента вдоль ее ширины с диагоналями треугольников, расположенных в виде рисунка "елочкой", может сделать эффект гораздо менее заметным. Это всегда будет присутствовать до некоторой степени, пока мы используем аффинные преобразования.
Но есть способ обойти это. Мы можем использовать тот же трюк, который мы используем для 3D-рендеринга, чтобы рисовать трапеции в перспективе при заданных прямоугольных стенах и полах: мы используем проективные координаты !
Аффинное текстурирование:
Проективное текстурирование:
Для этого нам нужно добавить третью координату uv (uvw) и изменить наши шейдеры.
Учитывая масштабный коэффициент в каждой точке (скажем, равный ширине вашей полосы в этом месте), вы можете построить 3D-проективную координату uvw из вашей обычной 2D-координаты uv следующим образом:
Vector3 uv3 = ((Vector3)uv2) * scale;
uv3.z = scale;
Чтобы применить эти 3D-координаты uvw к вашей сетке, вам нужно использовать Mesh.SetUVs перегрузки Vector3 (int channel, List uvs)
И обязательно измените структуру ввода вашего шейдера так, чтобы он ожидал трехмерную текстурную координату (показанную здесь с помощью неосвещенного шейдера по умолчанию):
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;
Наконец, чтобы вернуться к 2D-координате текстуры для выборки текстуры, вы просто делите на третью координату в своем фрагментном шейдере :
float2 uv = i.uv.xy / i.uv.z;
Поскольку мы сделали эту трехмерную координату uvw из нашей желаемой 2D-координаты умножением на одно и то же число, две операции отменяются, и мы возвращаемся к нашей первоначальной желаемой 2D-координате, но теперь с нелинейной интерполяцией между вершинами. : D
Важно делать это деление на фрагмент, а не на вершинный шейдер. Если это сделано для каждой вершины, то мы вернулись к линейной интерполяции результирующих координат вдоль каждого ребра, и мы потеряли нелинейность, которую мы пытались ввести с проективной координатой!
id
иcount
? Что делаетUVs.ToArray()
? Как вы загружаете вершины и координаты текстуры на карту?