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

相关文章

使用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

Java NoClassDefFoundError运行时错误分析解决

《JavaNoClassDefFoundError运行时错误分析解决》在Java开发中,NoClassDefFoundError是一种常见的运行时错误,它通常表明Java虚拟机在尝试加载一个类时未能... 目录前言一、问题分析二、报错原因三、解决思路检查类路径配置检查依赖库检查类文件调试类加载器问题四、常见

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

Python如何精准判断某个进程是否在运行

《Python如何精准判断某个进程是否在运行》这篇文章主要为大家详细介绍了Python如何精准判断某个进程是否在运行,本文为大家整理了3种方法并进行了对比,有需要的小伙伴可以跟随小编一起学习一下... 目录一、为什么需要判断进程是否存在二、方法1:用psutil库(推荐)三、方法2:用os.system调用

Python运行中频繁出现Restart提示的解决办法

《Python运行中频繁出现Restart提示的解决办法》在编程的世界里,遇到各种奇怪的问题是家常便饭,但是,当你的Python程序在运行过程中频繁出现“Restart”提示时,这可能不仅仅是令人头疼... 目录问题描述代码示例无限循环递归调用内存泄漏解决方案1. 检查代码逻辑无限循环递归调用内存泄漏2.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同