本文主要是介绍2020-08-21 利用Graphics.DrawMeshNow绘制运行时Gizmos,VR可用,HDRP可用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
先放效果图:
功能本身为测试用例,所以写的并不是很严谨,三角线使用的是缩放后的圆柱Mesh,黄色使用Box的Mesh,绿色使用Sphere的Mesh。
box和sphere也可以同时生成多个,但需要修改VrGizmos.cs中的两个方法DrawSphere、DrawBox,逻辑类似三角线的方法DrawSegments
放上VrGizmos.cs的源码:
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// Calling any VrGizmo static function will add this to Camera.main.
/// Or attach to a VR camera to manually enable VR gizmo drawing.
/// </summary>
[RequireComponent(typeof(Camera))]
public class VrGizmos : MonoBehaviour
{#region Consts and typesconst string SHADER = "Unlit/Color";public class DrawCommand{Mesh[] _mesh;Matrix4x4[] _matrix;Color[] _color;public DrawCommand(Mesh[] mesh, Color[] color, Matrix4x4[] matrix){_mesh = mesh;_matrix = matrix;_color = color;}public void Draw(Material m){for (int i = 0; i < _mesh.Length; i++){_color[i].a *= alpha;m.color = _color[i];m.SetPass(0);Graphics.DrawMeshNow(_mesh[i], _matrix[i]);}}}#endregion#region Staticstatic List<VrGizmos> _drawers = new List<VrGizmos>();public static Dictionary<PrimitiveType, Mesh> _meshes;static bool _initd = false;static void Init(){if (_initd) return;alpha = 1;_meshes = new Dictionary<PrimitiveType, Mesh>();foreach (PrimitiveType pt in (PrimitiveType[]) System.Enum.GetValues(typeof(PrimitiveType))){GameObject go = GameObject.CreatePrimitive(pt);Mesh m = go.GetComponent<MeshFilter>().sharedMesh;Object.DestroyImmediate(go);_meshes.Add(pt, m);}_initd = true;}static bool AddDrawer(Camera cam){if (cam == null) return false;if (cam.stereoTargetEye != StereoTargetEyeMask.None){cam.gameObject.AddComponent<VrGizmos>();Debug.LogWarningFormat("Automatically added VrGizmo component to camera {0}", cam.name);return true;}return false;}public static void AddDraw(DrawCommand drawCommand){if (!active || !Application.isPlaying) return;if (_drawers.Count == 0){bool added = AddDrawer(Camera.main);if (!added){foreach (var cam in Camera.allCameras){added = AddDrawer(cam);if (added) break;}}if (!added){Debug.LogWarning("No VrGizmo components detected on cameras and no valid VR cameras found - nothing will be drawn");}}foreach (var d in _drawers){if (!d._cmds.Contains(drawCommand)){d._cmds.Add(drawCommand);}}}public static void RemoveDraw(DrawCommand drawCommand){foreach (var d in _drawers){if (d._cmds.Contains(drawCommand)){d._cmds.Remove(drawCommand);}}}#region APIpublic static float alpha;public static bool active = true;public struct Segment{public Vector3 _start;public Vector3 _end;public Color _color;public Segment(Vector3 start, Vector3 end, Color color){_start = start;_end = end;_color = color;}}public static DrawCommand DrawSegments(Segment[] segments, float thickness){Mesh[] meshes = new Mesh[segments.Length];Color[] colors = new Color[segments.Length];Matrix4x4[] matrixs = new Matrix4x4[segments.Length];for (int i = 0; i < segments.Length; i++){var start = segments[i]._start;var end = segments[i]._end;var position = (start + end) / 2f;var rotation = Quaternion.FromToRotation(Vector3.up, end - start);var length = Vector3.Distance(start, end) / 2f;meshes[i] = _meshes[PrimitiveType.Cylinder];matrixs[i] = Matrix4x4.TRS(position, rotation, new Vector3(thickness, length, thickness));colors[i] = segments[i]._color;}return new DrawCommand(meshes, colors, matrixs);}public static DrawCommand DrawSphere(Vector3 position, float radius, Color color){Mesh[] meshes = new[] {_meshes[PrimitiveType.Sphere]};Color[] colors = new[] {color};Matrix4x4[] matrixs = new[] {Matrix4x4.TRS(position, Quaternion.identity, Vector3.one * radius)};return new DrawCommand(meshes, colors, matrixs);}public static DrawCommand DrawBox(Vector3 position, Quaternion rotation, Vector3 size, Color color){Mesh[] meshes = new[] {_meshes[PrimitiveType.Cube]};Color[] colors = new[] {color};Matrix4x4[] matrixs = new[] {Matrix4x4.TRS(position, rotation, size)};return new DrawCommand(meshes, colors, matrixs);}#endregion#endregion#region Instancepublic Material _mat;List<DrawCommand> _cmds = new List<DrawCommand>();void Awake(){Init();_drawers.Add(this);_mat = new Material(Shader.Find(SHADER));_mat.hideFlags = HideFlags.HideAndDontSave;}void OnDestroy(){_drawers.Remove(this);Destroy(_mat);_cmds.Clear();}void OnPostRender(){foreach (var c in _cmds){c.Draw(_mat);}}#endregion
}
以及测试使用的代码:
using UnityEngine;public class TestVrGizmos : MonoBehaviour
{private VrGizmos.DrawCommand _cmdSphere;private VrGizmos.DrawCommand _cmdBox;private VrGizmos.DrawCommand _cmdLines;private Vector3 currPos;private Vector3 lastPos;// Start is called before the first frame updatevoid Start(){VrGizmos.alpha = 0.2f;lastPos = currPos = transform.position;_cmdSphere = VrGizmos.DrawSphere(currPos, 1f, Color.green);_cmdBox = VrGizmos.DrawBox(currPos + Vector3.up, Quaternion.identity, Vector3.one, Color.yellow);VrGizmos.Segment[] segments = new[]{new VrGizmos.Segment(new Vector3(0, 0, 0), new Vector3(1, 1, 1), Color.cyan),new VrGizmos.Segment(new Vector3(1, 1, 1), new Vector3(1, 0, 1), Color.green),new VrGizmos.Segment(new Vector3(1, 0, 1), new Vector3(0, 0, 0), Color.red)};_cmdLines = VrGizmos.DrawSegments(segments, 0.01f);}// Update is called once per framevoid Update(){currPos = transform.position;if (!lastPos.Equals(currPos)){lastPos = currPos;VrGizmos.RemoveDraw(_cmdSphere);VrGizmos.RemoveDraw(_cmdBox);_cmdSphere = VrGizmos.DrawSphere(currPos, 1f, Color.green);_cmdBox = VrGizmos.DrawBox(currPos + Vector3.up, Quaternion.identity, Vector3.one, Color.yellow);}VrGizmos.AddDraw(_cmdSphere);VrGizmos.AddDraw(_cmdBox);VrGizmos.AddDraw(_cmdLines);}
}
使用方式:
1.导入SteamVR插件,并在场景中拖入[CameraRig]预制体
2.将脚本VrGizmos.cs挂在[CameraRig]下面的Camera上
3.新建空白对象,挂上脚本TestVrGizmos.cs,运行即可
感谢Dr Luke Thompson的项目源码https://github.com/SixWays/VrGizmos
2020-08-25更新:
经过进一步的使用发现项目升级到HDRP后,Graphics.DrawMeshNow绘制的网格显示不出来,原因未知。
只能更换绘制API为Graphics.DrawMesh。
转载注明出处,感谢。
这篇关于2020-08-21 利用Graphics.DrawMeshNow绘制运行时Gizmos,VR可用,HDRP可用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!