2020-08-21 利用Graphics.DrawMeshNow绘制运行时Gizmos,VR可用,HDRP可用

2024-09-03 05:18

本文主要是介绍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可用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1132131

相关文章

centos7基于keepalived+nginx部署k8s1.26.0高可用集群

《centos7基于keepalived+nginx部署k8s1.26.0高可用集群》Kubernetes是一个开源的容器编排平台,用于自动化地部署、扩展和管理容器化应用程序,在生产环境中,为了确保集... 目录一、初始化(所有节点都执行)二、安装containerd(所有节点都执行)三、安装docker-

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Linux使用nohup命令在后台运行脚本

《Linux使用nohup命令在后台运行脚本》在Linux或类Unix系统中,后台运行脚本是一项非常实用的技能,尤其适用于需要长时间运行的任务或服务,本文我们来看看如何使用nohup命令在后台... 目录nohup 命令简介基本用法输出重定向& 符号的作用后台进程的特点注意事项实际应用场景长时间运行的任务服

如何在一台服务器上使用docker运行kafka集群

《如何在一台服务器上使用docker运行kafka集群》文章详细介绍了如何在一台服务器上使用Docker运行Kafka集群,包括拉取镜像、创建网络、启动Kafka容器、检查运行状态、编写启动和关闭脚本... 目录1.拉取镜像2.创建集群之间通信的网络3.将zookeeper加入到网络中4.启动kafka集群

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

PostgreSQL如何用psql运行SQL文件

《PostgreSQL如何用psql运行SQL文件》文章介绍了两种运行预写好的SQL文件的方式:首先连接数据库后执行,或者直接通过psql命令执行,需要注意的是,文件路径在Linux系统中应使用斜杠/... 目录PostgreSQ编程L用psql运行SQL文件方式一方式二总结PostgreSQL用psql运

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p