使用Point(no filter)纹理时Unity Mesh出现环形着色故障求助
问题:Unity中使用Point滤波纹理时相机周围出现同心环形变色故障
故障现象
相机(包括玩家相机与场景编辑器相机)周围会出现同心环形变色区域。
复现步骤
- 创建新Unity项目(测试了3D(URP)和3D(HDRP)模板,均存在该问题)
- 创建空GameObject,添加Mesh Filter和Mesh Renderer组件
- 为该GameObject挂载以下脚本
- 导入纹理资源,设置Filter Mode为
Point(no filter),拖至GameObject - 运行游戏
- 移动场景编辑器相机即可看到故障,也可将Main Camera对准生成的Mesh在游戏窗口查看
切换Filter Mode为非Point模式时故障消失,但会导致像素画模糊,因此不考虑该方案。求问故障原因及可行修复方法?
脚本代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TerrainGenerator : MonoBehaviour { public int width = 100; public int height = 100; Mesh mesh; List<Vector3> vertices = new List<Vector3> (); List<int> triangles = new List<int>(); List<Vector2> uvs = new List<Vector2>(); int vertexCounter = 0; // Start is called before the first frame update void Start() { mesh = gameObject.GetComponent<MeshFilter>().mesh; mesh.Clear(); vertices.Clear (); triangles.Clear (); uvs.Clear (); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { addFace(i, j, 1, 1); } } mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); mesh.uv = uvs.ToArray(); mesh.RecalculateNormals(); } private void addFace(int x, int y, int width, int height) { vertices.Add(new Vector3(x, 0, y)); vertices.Add(new Vector3(x, 0, y + height)); vertices.Add(new Vector3(x + width, 0, y)); vertices.Add(new Vector3(x + width, 0, y + height)); vertices.Add(new Vector3(x + width, 0, y)); vertices.Add(new Vector3(x, 0, y + height)); triangles.Add(vertexCounter++); triangles.Add(vertexCounter++); triangles.Add(vertexCounter++); triangles.Add(vertexCounter++); triangles.Add(vertexCounter++); triangles.Add(vertexCounter++); uvs.Add(new Vector2(0, 0)); uvs.Add(new Vector2(0, 1)); uvs.Add(new Vector2(1, 0)); uvs.Add(new Vector2(1, 1)); uvs.Add(new Vector2(1, 0)); uvs.Add(new Vector2(0, 1)); } }
故障原因
这是Point滤波纹理的UV采样精度与透视投影冲突导致的:
- 当前代码中每个小四边形面的UV都设置为
(0,0)-(1,1),意味着每个面都在采样整张纹理。当相机远离Mesh时,屏幕单个像素会覆盖大量相邻的小面,Point滤波的"取最近纹理像素"逻辑,会在这些面的UV采样点间跳变;加上透视投影的非线性特性,最终形成周期性的同心环形颜色偏差。 - 本质是透视下的UV采样走样,Point滤波无插值过渡,直接采样离散的纹理像素,多个相邻面的采样点在屏幕空间重叠时,就会出现这种视觉故障。
修复方法
方法1:修正UV映射逻辑(最优解)
让每个小面对应纹理的单个像素区域,而非整张纹理。修改addFace方法中的UV赋值逻辑:
// 先在脚本顶部添加公开纹理引用 public Texture2D pixelTexture; // 替换addFace方法中的uv.Add代码 float uvStepX = 1f / pixelTexture.width; float uvStepY = 1f / pixelTexture.height; uvs.Add(new Vector2(x * uvStepX, y * uvStepY)); uvs.Add(new Vector2(x * uvStepX, (y + height) * uvStepY)); uvs.Add(new Vector2((x + width) * uvStepX, y * uvStepY)); uvs.Add(new Vector2((x + width) * uvStepX, (y + height) * uvStepY)); uvs.Add(new Vector2((x + width) * uvStepX, y * uvStepY)); uvs.Add(new Vector2(x * uvStepX, (y + height) * uvStepY));
这样每个小面仅对应纹理的一个像素区域,Point滤波能精准采样,环形故障会完全消失。
方法2:配合纹理Wrap Mode优化
在纹理的Import Settings中,将Wrap Mode设置为Clamp,避免UV边缘的采样溢出,配合方法1使用可进一步提升稳定性。
方法3:自定义Shader处理(复杂场景适配)
如果必须保留原UV逻辑,可以在URP/HDRP的自定义Shader中,添加透视校正的采样处理,或在片元着色器中对UV进行平滑过渡。该方法需要Shader编写能力,适合无法修改Mesh UV的场景。
内容的提问来源于stack exchange,提问作者jared goddard
相关产品推荐
相关产品推荐

