在着色器 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;
首先我会解释。我正在写一个 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;