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

相关文章

通过prometheus监控Tomcat运行状态的操作流程

《通过prometheus监控Tomcat运行状态的操作流程》文章介绍了如何安装和配置Tomcat,并使用Prometheus和TomcatExporter来监控Tomcat的运行状态,文章详细讲解了... 目录Tomcat安装配置以及prometheus监控Tomcat一. 安装并配置tomcat1、安装

mysqld_multi在Linux服务器上运行多个MySQL实例

《mysqld_multi在Linux服务器上运行多个MySQL实例》在Linux系统上使用mysqld_multi来启动和管理多个MySQL实例是一种常见的做法,这种方式允许你在同一台机器上运行多个... 目录1. 安装mysql2. 配置文件示例配置文件3. 创建数据目录4. 启动和管理实例启动所有实例

IDEA运行spring项目时,控制台未出现的解决方案

《IDEA运行spring项目时,控制台未出现的解决方案》文章总结了在使用IDEA运行代码时,控制台未出现的问题和解决方案,问题可能是由于点击图标或重启IDEA后控制台仍未显示,解决方案提供了解决方法... 目录问题分析解决方案总结问题js使用IDEA,点击运行按钮,运行结束,但控制台未出现http://

解决Spring运行时报错:Consider defining a bean of type ‘xxx.xxx.xxx.Xxx‘ in your configuration

《解决Spring运行时报错:Considerdefiningabeanoftype‘xxx.xxx.xxx.Xxx‘inyourconfiguration》该文章主要讲述了在使用S... 目录问题分析解决方案总结问题Description:Parameter 0 of constructor in x

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

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集群