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

相关文章

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图

k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)

《k8s上运行的mysql、mariadb数据库的备份记录(支持x86和arm两种架构)》本文记录在K8s上运行的MySQL/MariaDB备份方案,通过工具容器执行mysqldump,结合定时任务实... 目录前言一、获取需要备份的数据库的信息二、备份步骤1.准备工作(X86)1.准备工作(arm)2.手

Java -jar命令如何运行外部依赖JAR包

《Java-jar命令如何运行外部依赖JAR包》在Java应用部署中,java-jar命令是启动可执行JAR包的标准方式,但当应用需要依赖外部JAR文件时,直接使用java-jar会面临类加载困... 目录引言:外部依赖JAR的必要性一、问题本质:类加载机制的限制1. Java -jar的默认行为2. 类加

java -jar命令运行 jar包时运行外部依赖jar包的场景分析

《java-jar命令运行jar包时运行外部依赖jar包的场景分析》:本文主要介绍java-jar命令运行jar包时运行外部依赖jar包的场景分析,本文给大家介绍的非常详细,对大家的学习或工作... 目录Java -jar命令运行 jar包时如何运行外部依赖jar包场景:解决:方法一、启动参数添加: -Xb

eclipse如何运行springboot项目

《eclipse如何运行springboot项目》:本文主要介绍eclipse如何运行springboot项目问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目js录当在eclipse启动spring boot项目时出现问题解决办法1.通过cmd命令行2.在ecl

使用nohup和--remove-source-files在后台运行rsync并记录日志方式

《使用nohup和--remove-source-files在后台运行rsync并记录日志方式》:本文主要介绍使用nohup和--remove-source-files在后台运行rsync并记录日... 目录一、什么是 --remove-source-files?二、示例命令三、命令详解1. nohup2.

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例

《Nginx使用Keepalived部署web集群(高可用高性能负载均衡)实战案例》本文介绍Nginx+Keepalived实现Web集群高可用负载均衡的部署与测试,涵盖架构设计、环境配置、健康检查、... 目录前言一、架构设计二、环境准备三、案例部署配置 前端 Keepalived配置 前端 Nginx

Spring Boot项目打包和运行的操作方法

《SpringBoot项目打包和运行的操作方法》SpringBoot应用内嵌了Web服务器,所以基于SpringBoot开发的web应用也可以独立运行,无须部署到其他Web服务器中,下面以打包dem... 目录一、打包为JAR包并运行1.打包为可执行的 JAR 包2.运行 JAR 包二、打包为WAR包并运行

Redis高可用-主从复制、哨兵模式与集群模式详解

《Redis高可用-主从复制、哨兵模式与集群模式详解》:本文主要介绍Redis高可用-主从复制、哨兵模式与集群模式的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录Redis高可用-主从复制、哨兵模式与集群模式概要一、主从复制(Master-Slave Repli