Cailean Finn
9 months ago
38 changed files with 31850 additions and 2 deletions
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 0742a7add6bdfb84f81e897f7a4aa627 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,16 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEditor; |
||||
|
|
||||
|
namespace SplatVfx.Editor { |
||||
|
|
||||
|
[CustomEditor(typeof(SplatData))] |
||||
|
public sealed class SplatDataInspector : UnityEditor.Editor |
||||
|
{ |
||||
|
public override void OnInspectorGUI() |
||||
|
{ |
||||
|
var count = ((SplatData)target).SplatCount; |
||||
|
EditorGUILayout.LabelField("Splat Count", $"{count:N0}"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} // namespace SplatVfx.Editor
|
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 90300afbf61b2ac46906aa1e19eedddc |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,122 @@ |
|||||
|
using Unity.Burst; |
||||
|
using Unity.Mathematics; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.VFX; |
||||
|
using UnityEngine.VFX.Utility; |
||||
|
using UnityEditor; |
||||
|
using UnityEditor.AssetImporters; |
||||
|
using UnityEditor.Experimental; |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
namespace SplatVfx.Editor { |
||||
|
|
||||
|
[ScriptedImporter(1, "splat"), BurstCompile] |
||||
|
public sealed class SplatImporter : ScriptedImporter |
||||
|
{ |
||||
|
#region ScriptedImporter implementation
|
||||
|
|
||||
|
public override void OnImportAsset(AssetImportContext context) |
||||
|
{ |
||||
|
var data = ImportAsSplatData(context.assetPath); |
||||
|
var prefab = CreatePrefab(data); |
||||
|
context.AddObjectToAsset("prefab", prefab); |
||||
|
context.AddObjectToAsset("data", data); |
||||
|
context.SetMainObject(prefab); |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region Prefab construction
|
||||
|
|
||||
|
const string DefaultVfxPath = "Packages/jp.keijiro.splat-vfx/VFX/Splat.vfx"; |
||||
|
|
||||
|
GameObject CreatePrefab(SplatData data) |
||||
|
{ |
||||
|
var go = new GameObject(); |
||||
|
|
||||
|
var vfx = go.AddComponent<VisualEffect>(); |
||||
|
vfx.visualEffectAsset = EditorResources.Load<VisualEffectAsset>(DefaultVfxPath); |
||||
|
|
||||
|
var binderBase = go.AddComponent<VFXPropertyBinder>(); |
||||
|
var binder = binderBase.AddPropertyBinder<VFXSplatDataBinder>(); |
||||
|
binder.SplatData = data; |
||||
|
|
||||
|
return go; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region Reader implementation
|
||||
|
|
||||
|
SplatData ImportAsSplatData(string path) |
||||
|
{ |
||||
|
var data = ScriptableObject.CreateInstance<SplatData>(); |
||||
|
data.name = Path.GetFileNameWithoutExtension(path); |
||||
|
|
||||
|
var arrays = LoadDataArrays(path); |
||||
|
data.PositionArray = arrays.position; |
||||
|
data.AxisArray = arrays.axis; |
||||
|
data.ColorArray = arrays.color; |
||||
|
data.ReleaseGpuResources(); |
||||
|
|
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
#pragma warning disable CS0649
|
||||
|
|
||||
|
struct ReadData |
||||
|
{ |
||||
|
public float px, py, pz; |
||||
|
public float sx, sy, sz; |
||||
|
public byte r, g, b, a; |
||||
|
public byte rw, rx, ry, rz; |
||||
|
} |
||||
|
|
||||
|
#pragma warning restore CS0649
|
||||
|
|
||||
|
(Vector3[] position, Vector3[] axis, Color[] color) |
||||
|
LoadDataArrays(string path) |
||||
|
{ |
||||
|
var bytes = (Span<byte>)File.ReadAllBytes(path); |
||||
|
var count = bytes.Length / 32; |
||||
|
|
||||
|
var source = MemoryMarshal.Cast<byte, ReadData>(bytes); |
||||
|
|
||||
|
var position = new Vector3[count]; |
||||
|
var axis = new Vector3[count * 3]; |
||||
|
var color = new Color[count]; |
||||
|
|
||||
|
for (var i = 0; i < count; i++) |
||||
|
ParseReadData(source[i], |
||||
|
out position[i], |
||||
|
out axis[i * 3], |
||||
|
out axis[i * 3 + 1], |
||||
|
out axis[i * 3 + 2], |
||||
|
out color[i]); |
||||
|
|
||||
|
return (position, axis, color); |
||||
|
} |
||||
|
|
||||
|
[BurstCompile] |
||||
|
void ParseReadData(in ReadData src, |
||||
|
out Vector3 position, |
||||
|
out Vector3 axis1, |
||||
|
out Vector3 axis2, |
||||
|
out Vector3 axis3, |
||||
|
out Color color) |
||||
|
{ |
||||
|
var rv = (math.float4(src.rx, src.ry, src.rz, src.rw) - 128) / 128; |
||||
|
var q = math.quaternion(-rv.x, -rv.y, rv.z, rv.w); |
||||
|
position = math.float3(src.px, src.py, -src.pz); |
||||
|
axis1 = math.mul(q, math.float3(src.sx, 0, 0)); |
||||
|
axis2 = math.mul(q, math.float3(0, src.sy, 0)); |
||||
|
axis3 = math.mul(q, math.float3(0, 0, src.sz)); |
||||
|
color = (Vector4)math.float4(src.r, src.g, src.b, src.a) / 255; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
} |
||||
|
|
||||
|
} // namespace SplatVfx.Editor
|
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 7a7f5d2fd17129a42904e57ffbcf8a67 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,21 @@ |
|||||
|
{ |
||||
|
"name": "SplatVfx.Editor", |
||||
|
"rootNamespace": "", |
||||
|
"references": [ |
||||
|
"GUID:57d6a1ae39d606347b1307f1eadefe70", |
||||
|
"GUID:d8b63aba1907145bea998dd612889d6b", |
||||
|
"GUID:2665a8d13d1b3f18800f46e256720795", |
||||
|
"GUID:d04eb9c554ad44ceab303cecf0c0cf82" |
||||
|
], |
||||
|
"includePlatforms": [ |
||||
|
"Editor" |
||||
|
], |
||||
|
"excludePlatforms": [], |
||||
|
"allowUnsafeCode": false, |
||||
|
"overrideReferences": false, |
||||
|
"precompiledReferences": [], |
||||
|
"autoReferenced": true, |
||||
|
"defineConstraints": [], |
||||
|
"versionDefines": [], |
||||
|
"noEngineReferences": false |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: f9e984872a36ed840845202c3d099efc |
||||
|
AssemblyDefinitionImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 1fed89f6395c66f45869fa300c022eae |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,70 @@ |
|||||
|
using UnityEngine; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace SplatVfx { |
||||
|
|
||||
|
public sealed class SplatData : ScriptableObject |
||||
|
{ |
||||
|
#region Public properties
|
||||
|
|
||||
|
public int SplatCount => PositionArray.Length; |
||||
|
public GraphicsBuffer PositionBuffer => GetCachedBuffers().position; |
||||
|
public GraphicsBuffer AxisBuffer => GetCachedBuffers().axis; |
||||
|
public GraphicsBuffer ColorBuffer => GetCachedBuffers().color; |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region Serialized data
|
||||
|
|
||||
|
[field:SerializeField] public Vector3[] PositionArray { get; set; } |
||||
|
[field:SerializeField] public Vector3[] AxisArray { get; set; } |
||||
|
[field:SerializeField] public Color[] ColorArray { get; set; } |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region Public methods
|
||||
|
|
||||
|
public void ReleaseGpuResources() |
||||
|
{ |
||||
|
_cachedBuffers.position?.Release(); |
||||
|
_cachedBuffers.axis?.Release(); |
||||
|
_cachedBuffers.color?.Release(); |
||||
|
_cachedBuffers = (null, null, null); |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region GPU resource management
|
||||
|
|
||||
|
(GraphicsBuffer position, GraphicsBuffer axis, GraphicsBuffer color) |
||||
|
_cachedBuffers; |
||||
|
|
||||
|
static unsafe GraphicsBuffer NewBuffer<T>(int count) where T : unmanaged |
||||
|
=> new GraphicsBuffer(GraphicsBuffer.Target.Structured, count, sizeof(T)); |
||||
|
|
||||
|
(GraphicsBuffer position, GraphicsBuffer axis, GraphicsBuffer color) |
||||
|
GetCachedBuffers() |
||||
|
{ |
||||
|
if (_cachedBuffers.position == null) |
||||
|
{ |
||||
|
_cachedBuffers.position = NewBuffer<Vector3>(SplatCount); |
||||
|
_cachedBuffers.axis = NewBuffer<Vector3>(SplatCount * 3); |
||||
|
_cachedBuffers.color = NewBuffer<Color>(SplatCount); |
||||
|
_cachedBuffers.position.SetData(PositionArray); |
||||
|
_cachedBuffers.axis.SetData(AxisArray); |
||||
|
_cachedBuffers.color.SetData(ColorArray); |
||||
|
} |
||||
|
return _cachedBuffers; |
||||
|
} |
||||
|
|
||||
|
#endregion
|
||||
|
|
||||
|
#region ScriptableObject implementation
|
||||
|
|
||||
|
void OnDisable() => ReleaseGpuResources(); |
||||
|
|
||||
|
#endregion
|
||||
|
} |
||||
|
|
||||
|
} // namespace SplatVfx
|
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 99e8102f25e54bf4d89eb4309bb9901a |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,61 @@ |
|||||
|
using UnityEngine; |
||||
|
using UnityEngine.VFX; |
||||
|
using UnityEngine.VFX.Utility; |
||||
|
|
||||
|
namespace SplatVfx { |
||||
|
|
||||
|
[AddComponentMenu("VFX/Property Binders/Splat Data Binder")] |
||||
|
[VFXBinder("Splat Data")] |
||||
|
public sealed class VFXSplatDataBinder : VFXBinderBase |
||||
|
{ |
||||
|
public SplatData SplatData = null; |
||||
|
|
||||
|
public string SplatCountProperty |
||||
|
{ get => (string)_splatCountProperty; |
||||
|
set => _splatCountProperty = value; } |
||||
|
|
||||
|
public string PositionBufferProperty |
||||
|
{ get => (string)_positionBufferProperty; |
||||
|
set => _positionBufferProperty = value; } |
||||
|
|
||||
|
public string AxisBufferProperty |
||||
|
{ get => (string)_axisBufferProperty; |
||||
|
set => _axisBufferProperty = value; } |
||||
|
|
||||
|
public string ColorBufferProperty |
||||
|
{ get => (string)_colorBufferProperty; |
||||
|
set => _colorBufferProperty = value; } |
||||
|
|
||||
|
[VFXPropertyBinding("System.UInt32"), SerializeField] |
||||
|
ExposedProperty _splatCountProperty = "SplatCount"; |
||||
|
|
||||
|
[VFXPropertyBinding("UnityEngine.GraphicsBuffer"), SerializeField] |
||||
|
ExposedProperty _positionBufferProperty = "PositionBuffer"; |
||||
|
|
||||
|
[VFXPropertyBinding("UnityEngine.GraphicsBuffer"), SerializeField] |
||||
|
ExposedProperty _axisBufferProperty = "AxisBuffer"; |
||||
|
|
||||
|
[VFXPropertyBinding("UnityEngine.GraphicsBuffer"), SerializeField] |
||||
|
ExposedProperty _colorBufferProperty = "ColorBuffer"; |
||||
|
|
||||
|
public override bool IsValid(VisualEffect component) |
||||
|
=> SplatData != null && |
||||
|
component.HasUInt(_splatCountProperty) && |
||||
|
component.HasGraphicsBuffer(_positionBufferProperty) && |
||||
|
component.HasGraphicsBuffer(_axisBufferProperty) && |
||||
|
component.HasGraphicsBuffer(_colorBufferProperty); |
||||
|
|
||||
|
public override void UpdateBinding(VisualEffect component) |
||||
|
{ |
||||
|
component.SetUInt(_splatCountProperty, (uint)SplatData.SplatCount); |
||||
|
component.SetGraphicsBuffer(_positionBufferProperty, SplatData.PositionBuffer); |
||||
|
component.SetGraphicsBuffer(_axisBufferProperty, SplatData.AxisBuffer); |
||||
|
component.SetGraphicsBuffer(_colorBufferProperty, SplatData.ColorBuffer); |
||||
|
} |
||||
|
|
||||
|
public override string ToString() |
||||
|
=> $"Splat Data : {_splatCountProperty}, {_positionBufferProperty}, " |
||||
|
+ $"{_axisBufferProperty}, {_colorBufferProperty}"; |
||||
|
} |
||||
|
|
||||
|
} // namespace SplatVfx
|
@ -0,0 +1,11 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 6b23e4c8461b80e458b0acda332b8a17 |
||||
|
MonoImporter: |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
defaultReferences: [] |
||||
|
executionOrder: 0 |
||||
|
icon: {instanceID: 0} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,16 @@ |
|||||
|
{ |
||||
|
"name": "SplatVfx.Runtime", |
||||
|
"rootNamespace": "", |
||||
|
"references": [ |
||||
|
"GUID:d04eb9c554ad44ceab303cecf0c0cf82" |
||||
|
], |
||||
|
"includePlatforms": [], |
||||
|
"excludePlatforms": [], |
||||
|
"allowUnsafeCode": true, |
||||
|
"overrideReferences": false, |
||||
|
"precompiledReferences": [], |
||||
|
"autoReferenced": true, |
||||
|
"defineConstraints": [], |
||||
|
"versionDefines": [], |
||||
|
"noEngineReferences": false |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 57d6a1ae39d606347b1307f1eadefe70 |
||||
|
AssemblyDefinitionImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 2d7f462a7494efc41a164e16799dd783 |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,10 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: ba6fab3c458b65948b6b54b560dc6ad8 |
||||
|
ScriptedImporter: |
||||
|
internalIDToNameTable: [] |
||||
|
externalObjects: {} |
||||
|
serializedVersion: 2 |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
||||
|
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} |
@ -0,0 +1,8 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 71a7613a0b9d0914fa79a1406446691c |
||||
|
folderAsset: yes |
||||
|
DefaultImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 6ec2bd8fee604ee489e49fadaef11fe2 |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 4ce91597b36c2104481cf644dd8f0cd0 |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 98ff151d5676464419f3e5d8ec5ecb8b |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: fd4bd13ed1bfa804c90718dfbc02d3e8 |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: fd065fccc077e0e4aa25fcd2a1a8bf29 |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 8ada6dcd9d799a5448dee04183f48fd2 |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 687c12d75f307d746ba048bc8df6c99a |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
File diff suppressed because it is too large
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: c2390383b28322c469644e7f7e01ebb0 |
||||
|
VisualEffectImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
@ -0,0 +1,13 @@ |
|||||
|
{ |
||||
|
"author": "Keijiro Takahashi", |
||||
|
"dependencies": {}, |
||||
|
"description": "3D Gaussian Splatting support for VFX Graph", |
||||
|
"displayName": "Splat VFX", |
||||
|
"keywords": [ "unity" ], |
||||
|
"license": "Unlicense", |
||||
|
"name": "jp.keijiro.splat-vfx", |
||||
|
"repository": "github:keijiro/SplatVFX", |
||||
|
"unity": "2023.1", |
||||
|
"unityRelease": "0f1", |
||||
|
"version": "0.0.1" |
||||
|
} |
@ -0,0 +1,7 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: f7fb3e96e44041f41a351d435ccb5d50 |
||||
|
PackageManifestImporter: |
||||
|
externalObjects: {} |
||||
|
userData: |
||||
|
assetBundleName: |
||||
|
assetBundleVariant: |
Loading…
Reference in new issue