在着色器 Unity3D 中更改平铺平面

Change plane of tile in shader Unity3D

首先我会解释。我正在写一个 2D 游戏,添加了法线贴图和光照。所有物体都在一个平面上。结果,墙壁行为不当,实际上是在地板上。可不可以写一个这样的shader来替换这面墙的坐标,就好像它在另一个平面,垂直于它所在的平面然后再做处理?

当前平面:

需要飞机:

根据我的理解,您希望瓷砖平放在地面上,但您希望它像直立一样被遮蔽,光线从一个角度照射它。

对此有三种可能的解决方案。第一个选项是将倾斜的法线烘焙到法线贴图中。考虑这个球体的法线贴图:

青色部分朝上,紫色部分朝下。您可以从您选择的角度采样颜色并将该颜色叠加到您的法线贴图中。有一个关于如何 属性 合并法线贴图 here 的教程。

另一种方法是将旋转矩阵传递到着色器中,并使用它在顶点着色器中旋转法线。

以下是旋转矩阵的构造方式:

在着色器中,您可以这样定义矩阵:

float3x3 _RotMatrix;

在顶点着色器中,您可以像这样应用它们:

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

您可以使用此函数将矩阵传递到着色器中:

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

或者,您可以只传递一个旋转向量并在顶点着色器中构造矩阵。无论哪种方式,您都可以为您的对象设置每个 material 的旋转偏移量以用于照明计算。

第三个选项是为您的飞机模型设置自定义法线。您可以在网格内部执行此操作 - 这可能是最简单的解决方案。从网格过滤器中获取网格,遍历所有法线,并使用四元数旋转它们,使它们大致朝向您希望墙壁朝向的方向。

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;