一、需求描述:
在做全球Gis项目时,有一个需求:
需要在地球表面上绘制一些像素宽度的线。
二:问题说明
Unity自带的LineRender因为效果问题,首先被弃用。资源商店中有一些效果和性能很不错的Line插件。但是经过测试,都存在一个问题:
由于使用的地球是全尺寸地球,所以物体在地球表面时,坐标会非常大,如果在物体之间连线时,因为Unity本身的计算精度问题,会使得mesh产生渲染抖动现象。而且这些插件都是基于Mesh进行的绘制,所以都存在这个现象,没有办法使用。
三、解决方案
解决这个问题的方式有两种:
1.对全尺寸地球进行缩放,比如缩小1000倍。这样坐标就满足Unity精度需求,不会产生Mesh抖动现象。
2.使用不基于Mesh的绘线方式。
两种方式都可以解决问题,但是如果由于一些原因,导致第一种方案无法使用,则可以使用第二种方式解决。这里我主要描述第二种解决方案。
四、最终采用方案
不基于Mesh的GPU Line的绘制方式:
Unity原生支持GL绘线,这种绘线方式可以完美满足我的需求,基于像素绘制宽度,不基于Mesh绘制线段,不存在抖动问题。
使用教程:
1.新建下方脚本,将脚本挂在相机上(必须挂在相机上,否则无法运行),并且调整好相机视角,保证相机能看到线。
using System.Collections.Generic;
using UnityEngine;
public class GLLineTest : MonoBehaviour
{
#region 测试
public void Start()
{
//初始化坐标集合
for (int i = 0; i < 10; i++)
{
poss.Add(new Vector3(i*0.2f,0, 0));
//在点位上生成小球,以便观察
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = Vector3.one*0.05f;
go.transform.position = poss[i];
go.name = i.ToString();
}
}
#endregion
public Material lineMat;
private List<Vector3> poss = new List<Vector3> ();
private void OnPostRender()
{
DrawLineEffect();
}
public void DrawLineEffect()
{
if (poss.Count == 0)
{
return;
}
//------------------------------
//对线的信息进行设置。如果有多个颜色或样式的线,可以把设置放到每一类的线的绘制代码中
GL.Begin(GL.LINES);
lineMat.SetPass(0);
GL.Color(lineMat.color);
//-------------------------------
for (int i = 0; i < poss.Count; i++)
{
#region 实线
if (i == 0 || i == poss.Count - 1)
{
GL.Vertex(poss[i]);
}
else
{
GL.Vertex(poss[i]);
GL.Vertex(poss[i]);
}
#endregion
#region 虚线
//GL.Vertex(poss[i]);
#endregion
}
GL.End();
}
}
2.新建材质球,shader如下图所示,并将材质球赋值给脚本的材质参数
五、注意事项
1.脚本必须挂在相机上,否则无法运行
2.GL绘出的线不能在Scene视图中显示,如果需要显示,请使用Debug.Drawxx()函数绘制