Смена плоскости плитки в шейдере Unity3D - PullRequest
0 голосов
/ 28 октября 2019

Для начала объясню. Я пишу 2D-игру, добавил карты нормалей и освещение. Все объекты лежат в одной плоскости. В результате стены ведут себя неуместно и буквально лежат на полу. Можно ли написать такой шейдер для замены координат этой стены, как если бы она была в другой плоскости, перпендикулярной той, в которой она расположена, и после этого выполнить обработку?

Текущая плоскость:

enter image description here

Необходимая плоскость:

enter image description here

1 Ответ

0 голосов
/ 30 октября 2019

Насколько я понимаю, вы хотите, чтобы плитка была плоской на земле, но вы хотите, чтобы она была затенена, как если бы она стояла, и свет падал на нее под углом.

Для этого есть три возможных решения. Первый вариант заключается в том, что вы запекаете нормали как наклоненные на карту нормалей. Рассмотрим эту нормальную карту сферы:

image

The teal parts are pointing upwards, and the purple parts are pointing downwards. You can sample a color from an angle of your choice and overlay that color into your normal map. There is a tutorial on how to property combine normal maps здесь .

Другой метод - передать матрицу вращения в ваш шейдер и использовать ее для вращения вашей нормали в вершинном шейдере.

Вот как создаются матрицы вращения:

enter image description here

В шейдере вы определяете матрицы следующим образом:

float3x3 _RotMatrix;

В вершинном шейдере вы применяете их следующим образом:

float3 normal = UnityObjectToWorldNormal(v.normal);
o.normal = mul(normal, _RotMatrix);

Вы можете передавать матрицы в шейдеры, используя эту функцию:

Matrix4x4 rotMatrix = Matrix4x4.Rotate(rotation);
GetComponent<MeshRenderer>().material.SetMatrix("_RotMatrix", matrix);

Или вы можете просто передать вектор вращения и построить матрицу внутри вершинного шейдера. В любом случае, вы можете установить смещение вращения для каждого материала для ваших объектов для использования в расчетах освещения.

Третий вариант - установить пользовательские нормали для вашей модели самолета. Вы можете сделать это внутри меша - это, вероятно, самое простое решение. Возьмите сетку из фильтра сетки, обведите все нормали и поверните их, используя кватернион, чтобы они были примерно ориентированы в том направлении, в котором вы хотите видеть стену.

Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] normals = mesh.normals;
for(int i=0; i<= normals.Length; i++) {
    normals[i] = Quaternion.Euler(new Vector3(45, 0, 0)) * normals[i];
}
mesh.normals = normals;
mesh.RecalculateTangents();
GetComponent<MeshFilter>().mesh = mesh;
...