[英]Unity - Project a texture on a mesh using C# (No Shaders)
我正在尝试仅使用 C# 在简单的立方体 meshFilter 上投影纹理,但我很难理解该怎么做。 我几乎让它适用于 X 轴旋转,并且 Y/Z 有很多不好的翘曲。 基本上,当相机的位置/旋转发生变化时,我会更新 UV,这是我的代码:
[ExecuteInEditMode]
public class ObjectEditor : MonoBehaviour {
public GameObject Model;
public void UpdateTexture(Camera camera) {
MeshFilter[] mesheFilters = Model.GetComponentsInChildren<MeshFilter>();
foreach (MeshFilter meshFilter in mesheFilters) {
int size = meshFilter.sharedMesh.vertices.Length;
Vector2[] uvs = new Vector2[size];
for (int i = 0; i < size; i++) {
uvs[i] = vertexToUVPosition(camera, meshFilter, i);
}
meshFilter.sharedMesh.SetUVs(0, uvs);
}
}
private Vector2 vertexToUVPosition(Camera camera, MeshFilter meshFilter, int index) {
Vector3 vertex = meshFilter.sharedMesh.vertices[index];
Matrix4x4 VP = camera.projectionMatrix * camera.worldToCameraMatrix;
Vector4 worldPos = new Vector4(vertex.x, vertex.y, vertex.z, 1f);
Vector4 clipPos = VP * worldPos;
clipPos *= 1f / clipPos.w;
return camera.WorldToScreenPoint(clipPos);
}
}
关于投影的一切都发生在 vertexToUVPosition 中。 这就是我现在所拥有的(投影纹理是一个简单的黑白棋盘):
有预测经验的人可以向我解释我做错了什么,并可能提供一个可以正常工作的示例 C# 代码吗? 谢谢你。
我找到了一个完全解决问题的解决方案,但我想它在数学上并不正确,因为我对矩阵和投影知之甚少。 然而,对于想要在没有任何经验的情况下做类似事情的人来说,这是一个很好的起点。
在显示代码之前,您应该设置一些东西以便更容易调试潜在问题:
算法:
// Calculate the VP matrix based on the Perspective Camera
VP = camera.projectionMatrix * camera.worldToCameraMatrix
foreach vertex in mesh
// Replace the "w" component by 1.
worldPosition = new Vector4(vertex.x, vertex.y, vertex.z, 1f);
clipPosition = VP * worldPosition;
// Small correction on Y axis (maybe someone can explain why I need this?).
clipPosition.Scale(new Vector3(1, 0.5f, 1));
// Use the clipPosition as UV coordinates for that vertex.
...
我的实现:
[ExecuteInEditMode]
public class ObjectEditor : MonoBehaviour {
public GameObject Model;
public void UpdateTexture(Camera camera) {
Matrix4x4 vp = camera.projectionMatrix * camera.worldToCameraMatrix;
MeshFilter[] mesheFilters = Model.GetComponentsInChildren<MeshFilter>();
foreach (MeshFilter meshFilter in mesheFilters) {
int size = meshFilter.sharedMesh.vertices.Length;
Vector2[] uvs = new Vector2[size];
for (int i = 0; i < size; i++) {
uvs[i] = vertexToUVPosition(vp, meshFilter, i);
}
meshFilter.sharedMesh.SetUVs(0, uvs);
}
}
private Vector2 vertexToUVPosition(Matrix4x4 vp, MeshFilter meshFilter, int index) {
Vector3 vertex = meshFilter.sharedMesh.vertices[index];
Vector4 worldPos = new Vector4(vertex.x, vertex.y, vertex.z, 1f);
Vector4 clipPos = vp * worldPos;
clipPos.Scale(new Vector3(1, 0.5f, 1));
return clipPos;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.