WorkInProgress/VolumetricMaterial.cs
using NativeEngine;
using static Sandbox.Component;

namespace Sandbox;


[Category( "Rendering" )]
[Icon( "cloud_circle" )]
public sealed partial class VolumetricMaterialRenderer : Renderer, ExecuteInEditor
{
    /// <summary>
    /// The volumetric material to render.
    /// </summary>
    private NanoVDB VDB { get; set; }

	[Property, NVDBPath] public string VDBPath { get; set; }


    List<GpuBuffer<uint>> GridsBuffer = new();

	internal SceneObject _sceneObject;

	protected override void OnEnabled()
    {
		
		VDB = NanoVDB.Load( VDBPath );
		if ( VDB is null )
			return;

		GridsBuffer.Clear();
		foreach ( var grid in VDB.Grids )
		{
			var Buffer = new GpuBuffer<uint>( grid.Data.Length );
			Buffer.SetData( grid.Data.AsSpan() );
			GridsBuffer.Add( Buffer );
		}

        var model = CreateModel();
		_sceneObject = new( Scene.SceneWorld, model, Transform.World );
		Transform.OnTransformChanged += OnTransformChanged;

		_sceneObject.Attributes.Set( "GridBuffer", GridsBuffer[0] );
	}

	protected override void OnDisabled()
	{
		_sceneObject?.Delete();
		_sceneObject = null;
	}

	private void OnTransformChanged()
	{
		if ( _sceneObject.IsValid() )
			_sceneObject.Transform = Transform.World;
	}

	private Model CreateModel()
	{
		// Create material and mesh with the cube bounds
		var material = Material.FromShader("volumetric");
		var mesh = new Mesh(material) { Bounds = VDB.BoundingBox };

		// Initialize and prepare the vertex buffer
		var vb = new VertexBuffer();
		vb.Init(true);

		var min = VDB.BoundingBox.Mins;
		var max = VDB.BoundingBox.Maxs;

		// Define cube vertices (front and back faces)
		var vertices = new[]
		{
			new Vector3(min.x, min.y, max.z), // Front-bottom-left
			new Vector3(max.x, min.y, max.z), // Front-bottom-right
			new Vector3(max.x, max.y, max.z), // Front-top-right
			new Vector3(min.x, max.y, max.z), // Front-top-left
			new Vector3(min.x, min.y, min.z), // Back-bottom-left
			new Vector3(max.x, min.y, min.z), // Back-bottom-right
			new Vector3(max.x, max.y, min.z), // Back-top-right
			new Vector3(min.x, max.y, min.z)  // Back-top-left
		};

		// Define cube triangle indices
		var indices = new[]
		{
			// Front face
			0, 1, 2, 2, 3, 0,
			// Back face
			4, 6, 5, 6, 4, 7,
			// Left face
			4, 0, 3, 3, 7, 4,
			// Right face
			1, 5, 6, 6, 2, 1,
			// Top face
			3, 2, 6, 6, 7, 3,
			// Bottom face
			4, 5, 1, 1, 0, 4
		};

		// Add indices and vertices to the buffer
		foreach (var index in indices)
		{
			vb.AddRawIndex(index);
		}

		foreach (var vertex in vertices)
		{
			vb.Add(new Vertex { Position = vertex });
		}

		mesh.CreateBuffers(vb);

		// Build and return the model
		return new ModelBuilder().AddMesh(mesh).Create();
	}


    protected override void DrawGizmos()
	{
		if( VDB is null )
			return;

		if ( !Gizmo.IsSelected )
			return;

		Gizmo.Draw.LineBBox( VDB.BoundingBox );
	}
}