You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4945 lines
219 KiB
C#

/******************************************************************************/
/*
Project - MudBun
Publisher - Long Bunny Labs
http://LongBunnyLabs.com
Author - Ming-Lun "Allen" Chou
http://AllenChou.net
*/
/******************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.XR;
namespace MudBun
{
[ExecuteInEditMode]
public abstract class MudRendererBase : MonoBehaviour
{
#region Events
public virtual void InvokeOnMeshGenerated(Mesh mesh) { }
#endregion
//-------------------------------------------------------------------------
#region Enums & Structs
public enum HardwareModeEnum
{
[InspectorName("GPU")] Gpu,
// [InspectorName("CPU")] Cpu,
}
public enum RenderModeEnum
{
FlatMesh = 0,
SmoothMesh = 1,
CircleSplats = 2,
QuadSplats = 3,
Decal = 4,
/*
[HideInInspector] RayMarchedSurface = 5,
[HideInInspector] RayTracedVoxels = 6,
*/
}
public enum RenderMaterialModeEnum
{
Static,
Dynamic,
}
public enum RayTracedVoxelModeEnum
{
FlatCubes,
FacetedCubes,
FlatSpheres,
SmoothSpheres,
Custom = 100,
}
public enum RayTracedVoxelPaddingModeEnum
{
None,
ByDistance,
Full,
}
public enum RenderModeCategoryEnum
{
Unknown = -1,
Mesh,
Splats,
Decal,
/*
RayMarchedSurface,
RayTracedVoxels,
*/
}
public enum MeshingModeEnum
{
MarchingCubes,
DualQuads,
SurfaceNets,
DualContouring,
}
public enum ComputeModeEnum
{
Auto,
Manual,
ManualNoRender,
EveryFrame,
TimeSliced
}
public enum TimeSliceModeEnum
{
ByFramesAutoOffset,
ByFramesManualOffset,
ByPeriodAutoOffset,
ByPeriodManualOffset,
}
public struct Const
{
public struct KernelIndex
{
public int ClearVoxelHashTable;
public int ClearAutoSmoothVertDataTable;
public int ClearVoxelCache;
public int RegisterTopNodes;
public int UpdateBranchingIndirectDispatchArgs;
public int AllocateChildNodes;
public int UpdateVoxelIndirectDispatchArgs;
public int GenerateFlatMarchingCubesMesh;
public int GenerateSmoothMarchingCubesMesh;
public int GenerateMarchingCubesSplats;
public int GenerateFlatMarchingCubesMesh2d;
public int GenerateSmoothMarchingCubesMesh2d;
public int GenerateMarchingCubesSplats2d;
public int UpdateMarchingCubesAutoSmoothIndirectDispatchArgs;
public int MarchingCubesUpdateAutoSmooth;
public int MarchingCubesComputeAutoSmooth;
public int GenerateDualQuads;
public int GenerateDualQuads2d;
public int UpdateDualMeshingIndirectDispatchArgs;
public int DualMeshingFlatMeshNormal;
public int DualMeshingSmoothMeshNormal;
public int DualMeshingFlatMeshNormal2d;
public int DualMeshingSmoothMeshNormal2d;
public int DualMeshingUpdateAutoSmooth;
public int DualMeshingComputeAutoSmooth;
public int DualMeshingUpdateSmoothCornerIndirectDispatchArgs;
public int DualMeshingSmoothCorner;
public int UpdateDualMeshingSplatsIndirectArgs;
public int ConvertDualMeshingSplats;
public int SurfaceNetsMovePoint;
public int SurfaceNetsMovePoint2d;
public int DualContouringMovePoint;
public int DualContouringMovePoint2d;
public int UpdateRayTracedVoxelIndirectDispatchArgs;
public int ComputeRayTracedVoxelGenPoints;
public int ComputeRayTracedVoxelGenPointsWithNormals;
public int GenerateNoiseCache;
public int RigBones;
public int GenerateSdf;
}
public static KernelIndex Kernel;
public static int TriTable;
public static int VertTable;
public static int TriTable2d;
public static int Brushes;
public static int BrushMaterials;
public static int NumBrushes;
public static int SurfaceShift;
public static int RenderMode;
public static int MeshingMode;
public static int RayTracedVoxelMode;
public static int RayTracedVoxelSizeMultiplier;
public static int RayTracedVoxelSmoothCubeNormal;
public static int RayTracedVoxelRadius;
public static int RayTracedVoxelPaddingMode;
public static int RayTracedVoxelInternalPaddingDistance;
public static int RayTracedVoxelSizeFadeDistance;
public static int NormalDifferentiationStep;
public static int NormalQuantization;
public static int Normal2dFadeDist;
public static int Normal2dStrength;
public static int EnableAutoSmooth;
public static int AutoSmoothMaxAngle;
public static int AutoSmoothVertDataTable;
public static int AutoSmoothVertDataPoolSize;
public static int EnableSmoothCorner;
public static int SmoothCornerSubdivision;
public static int SmoothCornerNormalBlur;
public static int SmoothCornerFade;
public static int InvertNormals;
public static int SplatSize;
public static int SplatSizeJitter;
public static int SplatNormalShift;
public static int SplatNormalShiftJitter;
public static int SplatColorJitter;
public static int SplatPositionJitter;
public static int SplatRotationJitter;
public static int SplatOrientationJitter;
public static int SplatOriginalNormalBlend;
public static int SplatJitterNoisiness;
public static int SplatCameraFacing;
public static int SplatNormalsMatchCameraFacing;
public static int SplatShadowsMatchCameraFacing;
public static int SplatScreenSpaceFlattening;
//public static int SplatSmoothNormalBlend;
public static int SurfaceNetsDualQuadsBlend;
public static int SurfaceNetsBinarySearchIterations;
public static int SurfaceNetsGradientDescentIterations;
public static int SurfaceNetsGradientDescentFactor;
public static int DualContouringDualQuadsBlend;
public static int DualContouringRelaxation;
public static int DualContouringSolverIterations;
public static int DualContouringBinarySearchIterations;
public static int DualContouringGradientDescentIterations;
public static int DualContouringGradientDescentFactor;
public static int AabbTree;
public static int AabbRoot;
public static int Enable2dMode;
public static int ForceAllBrushes;
public static int NumAllocations; // general allocation counters
public static int NodeHashTable;
public static int NodeHashTableSize;
public static int NodePool;
public static int NodePoolSize;
public static int NumNodesAllocated;
public static int UseVoxelCache;
public static int VoxelCacheIdTable;
public static int VoxelCache;
public static int VoxelCacheSize;
public static int BrushMaskPool;
public static int BrushMaskPoolSize;
public static int IndirectDispatchArgs;
public static int CurrentNodeDepth;
public static int CurrentNodeBranchingFactor;
public static int CurrentNodeSize;
public static int VoxelSize;
public static int VoxelTreeBranchingFactorsCompressed;
public static int VoxelNodeSizes;
public static int MaxNodeDepth;
public static int ChunkVoxelDensity;
public static int GenPoints;
public static int MaxGenPoints;
public static int IndirectDrawArgs;
public static int MasterColor;
public static int MasterEmission;
public static int MasterMetallic;
public static int MasterSmoothness;
public static int ScaleSign;
public static int LocalToWorld;
public static int LocalToWorldIt;
public static int LocalToWorldScale;
public static int WorldToLocal;
public static int WorldToLocalIt;
public static int NoiseCache;
public static int NoiseCacheDimension;
public static int NoiseCacheDensity;
public static int NoiseCachePeriod;
public static int SdfOutput;
public static int SdfOutputSize;
public static int SdfCenter;
public static int SdfDimension;
public static int MaxRayMarchSteps;
public static int RayMarchHitDistance;
public static int RayMarchMaxRayDistance;
public static int MeshGenerationAutoRiggingAlgorithm;
/*
public static int NumLightMarchSteps;
public static int RayMarchStepSize;
public static int RayMarchVolumeDensity;
public static int RayMarchVolumeBorderFade;
public static int RayMarchLightPositionType;
public static int RayMarchLightDirection;
public static int RayMarchAbsorption;
public static int RayMarchDarknesThreshold;
public static int RayMarchTransmittanceCurve;
public static int RayMarchNoiseEdgeFade;
public static int RayMarchNoiseThreshold;
public static int RayMarchNoiseScrollSpeed;
public static int RayMarchNoiseBaseOctaveSize;
public static int RayMarchNoiseNumOctaves;
public static int RayMarchNoiseOctaveOffsetFactor;
*/
public static int IsMeshRenderMaterial;
public static int IsSplatRenderMaterial;
public static int MaterialNeedsSdfProperties;
public static int MaterialNeedsRayMarchingProperties;
}
#endregion // end: Enums & Structs
//-------------------------------------------------------------------------
#region Global Consts
public static readonly int ThreadGroupExtent = 4;
public static readonly int ThreadGroupSize = ThreadGroupExtent * ThreadGroupExtent * ThreadGroupExtent;
public static readonly int ClearThreadGroupSize = 256;
private static int[] s_aVoxelTreeBranchingFactor = new int[] { 8, 8, 4 };
public static int[] VoxelTreeBranchingFactors => s_aVoxelTreeBranchingFactor;
public static int VoxelTreeBranchingFactorsComrpessed = (int) Codec.Pack8888((uint)s_aVoxelTreeBranchingFactor[0], (uint)s_aVoxelTreeBranchingFactor[1], (uint)s_aVoxelTreeBranchingFactor[2], 0);
public static int VoxelNodeDepth => VoxelTreeBranchingFactors.Length;
private static int s_chunkVoxelDensity = -1;
public static int ChunkVoxelDensity
{
get
{
if (s_chunkVoxelDensity < 0)
s_chunkVoxelDensity = VoxelTreeBranchingFactors.Aggregate((x, y) => x * y);
return s_chunkVoxelDensity;
}
}
// maximum allowed number of brushes per renderer
// NOTE: MaxBrushes must be a multiple of 32 (8 * sizeof(int))
// (MaxBrushes / 32) must be less than or equal to kMaxBrushMaskInts in BrushMaskDefs.cginc
// MaxBrushes must *NOT* be larger than 2^kAabbTreeNodeStackSize in AabbTreeDefs.cginc
public static readonly int MaxBrushes = 1024;
public static int MaxBrushMaskInts => MaxBrushes / 32;
public static int MaxBrushGroupDepth = 6;
private static int[] s_noiseCacheDimensionInts = new int[] { 256, 128, 256 };
public static int[] NoiseCacheDimensionInts => s_noiseCacheDimensionInts;
private static float[] s_noiseCacheDimensionFloats;
public static float[] NoiseCacheDimensionFloats
{
get
{
if (s_noiseCacheDimensionFloats == null)
s_noiseCacheDimensionFloats = NoiseCacheDimensionInts.Select(x => (float)x).ToArray();
return s_noiseCacheDimensionFloats;
}
}
public static readonly float NoiseCacheDensity = 32.0f;
private static float[] s_noiseCachePeriod;
public static float[] NoiseCachePeriod
{
get
{
if (s_noiseCachePeriod == null)
s_noiseCachePeriod = NoiseCacheDimensionInts.Select(x => x / NoiseCacheDensity).ToArray();
return s_noiseCachePeriod;
}
}
public int VoxelToVertexFactor
{
get
{
switch (RenderMode)
{
case RenderModeEnum.FlatMesh:
case RenderModeEnum.SmoothMesh:
return 3;
case RenderModeEnum.CircleSplats:
return 2;
case RenderModeEnum.QuadSplats:
return 3;
}
return 3;
}
}
#endregion // end: Global Consts
//-------------------------------------------------------------------------
#region Global Resources
private static bool s_globalResourcesValid = false;
protected static HashSet<MudRendererBase> s_renderers = new HashSet<MudRendererBase>();
protected static Dictionary<float, MudBrushBase> s_brushMap = new Dictionary<float, MudBrushBase>();
private static ComputeShader s_computeVoxelGen;
private static ComputeShader s_computeMarchingCubes;
private static ComputeShader s_computeDualMeshing;
private static ComputeShader s_computeSurfaceNets;
private static ComputeShader s_computeDualContouring;
private static ComputeShader s_computeRayTracedVoxels;
private static ComputeShader s_computeNoiseCache;
private static ComputeShader s_computeMeshLock;
private static ComputeShader s_computeSdfGen;
private static ComputeBuffer s_triTableBuffer;
private static ComputeBuffer s_vertTableBuffer;
private static ComputeBuffer s_triTable2dBuffer;
private static ComputeBuffer s_brushesBuffer;
private static ComputeBuffer s_brushMaterialBuffer;
private static ComputeBuffer s_aabbTreeBuffer;
private static ComputeBuffer s_dummyBuffer;
private static RenderTexture s_noiseCache;
public static RenderTexture NoiseCache => s_noiseCache;
/*
private static Texture s_noiseCache;
public static Texture NoiseCache
{
get
{
if (s_noiseCache != null)
return s_noiseCache;
s_noiseCache = ResourcesUtil.NoiseTexture;
return s_noiseCache;
}
}
*/
public static ResourcesUtil.RenderPipelineEnum RenderPipeline => ResourcesUtil.RenderPipeline;
public static int GlobalResourceGpuMemoryAllocated
{
get
{
int bytes = 0;
if (s_triTableBuffer != null)
bytes += s_triTableBuffer.stride * s_triTableBuffer.count;
if (s_vertTableBuffer != null)
bytes += s_vertTableBuffer.stride * s_vertTableBuffer.count;
if (s_triTable2dBuffer != null)
bytes += s_triTable2dBuffer.stride * s_triTable2dBuffer.count;
if (s_brushesBuffer != null)
bytes += s_brushesBuffer.stride * s_brushesBuffer.count;
if (s_brushMaterialBuffer != null)
bytes += s_brushMaterialBuffer.stride * s_brushMaterialBuffer.count;
if (s_aabbTreeBuffer != null)
bytes += s_aabbTreeBuffer.stride * s_aabbTreeBuffer.count;
if (s_noiseCache != null)
bytes += s_noiseCache.width * s_noiseCache.height * s_noiseCache.volumeDepth * sizeof(float);
if (s_dummyBuffer != null)
bytes += s_dummyBuffer.stride * s_dummyBuffer.count;
return bytes;
}
}
public static void ReloadAllShaders()
{
foreach (var renderer in s_renderers)
{
renderer.ReloadShaders();
}
}
#endregion // end: Global Resources
//-------------------------------------------------------------------------
#region Local Resources
private bool m_localResourcesValid = false;
protected NativeArray<SdfBrush> m_aSdfBrush;
protected NativeArray<SdfBrushMaterial> m_aSdfBrushMaterial;
protected Dictionary<int, int> m_sdfBrushMaterialIndexMap;
//[Header("Budgets")]
// base budgets
[Range(1, 2048)] public int MaxVoxelsK = 256;
[Range(16, 1024)] public int MaxChunks = 64;
private bool UseVoxelCache = false; // profiler says this doesn't really help with performance
// derived budgets
public int MaxVoxels => 1024 * MaxVoxelsK;
public int MaxVoxelNodes => 1024 * (MaxChunks + MaxVoxelsK);
public int MaxBrushMasks => 256 * MaxChunks;
public int MaxGenPoints => VoxelToVertexFactor * MaxVoxelNodes;
// only works in editor
public bool ShowGpuMemoryUsage = false;
public bool AutoAdjustBudgetsToHighWaterMarks = false;
[Range(0, 100)] public int AutoAdjustBudgetsToHighWaterMarksMarginPercent = 15;
private bool m_autoAdjustBudgetsToHighWaterMarks = false;
//[Header("Render")]
// local shader resources
[Range(0.1f, 100.0f)] public float VoxelDensity = 8.0f;
public float TopVoxelNodeSize
{
get
{
float size = ChunkVoxelDensity / VoxelDensity;
if (LockMeshIntermediateState != LockMeshIntermediateStateEnum.Idle)
size = ChunkVoxelDensity / MeshGenerationVoxelDensity;
return size * 1.0001f;
}
}
private float[] m_aNodeSize;
public float[] NodeSizes
{
get
{
if (m_aNodeSize == null || m_aNodeSize.Length != VoxelNodeDepth + 1)
m_aNodeSize = new float[VoxelNodeDepth + 1];
float nodeSize = TopVoxelNodeSize;
for (int depth = 0; depth < m_aNodeSize.Length; ++depth)
{
m_aNodeSize[depth] = nodeSize;
if (depth < VoxelNodeDepth)
nodeSize /= VoxelTreeBranchingFactors[depth];
}
return m_aNodeSize;
}
}
public Vector4 NodeSizesVector
{
get
{
var aNodeSize = NodeSizes;
int maxDepth = aNodeSize.Length;
Vector4 vec = Vector4.zero;
if (maxDepth > 0)
vec.x = aNodeSize[0];
if (maxDepth > 1)
vec.y = aNodeSize[1];
if (maxDepth > 2)
vec.z = aNodeSize[2];
if (maxDepth > 3)
vec.w = aNodeSize[3];
return vec;
}
}
public float VoxelSize
{
get
{
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Decal:
//case RenderModeCategoryEnum.RayMarchedSurface:
return 1e-5f;
}
return NodeSizes[VoxelNodeDepth];
}
}
private bool AllowSharedRWBuffers
{
get
{
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Metal) // Metal is weird
return false;
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Decal:
//case RenderModeCategoryEnum.RayMarchedSurface:
//case RenderModeCategoryEnum.RayTracedVoxels:
return false;
case RenderModeCategoryEnum.Splats:
/*
if (SplatSmoothNormalBlend > 0.0f)
return false;
*/
break;
}
return true;
}
}
private bool m_initialized = false;
private ComputeBuffer m_brushesBuffer;
private ComputeBuffer m_brushMaterialBuffer;
private ComputeBuffer m_aabbTreeBuffer;
private int m_aabbTreeBufferRoot;
private ComputeBuffer m_nodeHashTableBuffer;
protected ComputeBuffer m_nodePoolBuffer;
protected ComputeBuffer m_numNodesAllocatedBuffer;
private ComputeBuffer m_numAllocationsBuffer;
private ComputeBuffer m_voxelCacheIdTableBuffer;
private ComputeBuffer m_voxelCacheBuffer;
private ComputeBuffer m_brushMaskPoolBuffer;
private ComputeBuffer m_indirectDispatchArgsBuffer;
private ComputeBuffer m_autoSmoothVertDataTableBuffer;
protected ComputeBuffer m_genPointsBufferDefault;
protected ComputeBuffer m_indirectDrawArgsBufferDefault;
protected ComputeBuffer m_genPointsBufferOverride;
protected ComputeBuffer m_indirectDrawArgsBufferOverride;
protected ComputeBuffer m_genPointsBufferUsedForCompute;
protected ComputeBuffer m_indirectDrawArgsBufferUsedForCompute;
private NativeArray<int> m_indirectDrawArgsInitData;
private NativeArray<int> IndirectDrawArgsInitData
{
get
{
bool usingXr = false;
var aXrDisplaySubsystem = new List<XRDisplaySubsystem>();
SubsystemManager.GetInstances(aXrDisplaySubsystem);
foreach (var xrDisplay in aXrDisplaySubsystem)
{
if (xrDisplay.running)
{
usingXr = true;
break;
}
}
int numInstances = usingXr ? 2 : 1;
if (!m_indirectDrawArgsInitData.IsCreated)
{
m_indirectDrawArgsInitData = new NativeArray<int>(new int[] { 0, numInstances, 0, 0, 0, }, Allocator.Persistent);
}
m_indirectDrawArgsInitData[1] = numInstances;
return m_indirectDrawArgsInitData;
}
}
private static NativeArray<int> s_numAllocatoinsBufferInitData;
private static NativeArray<int> NumAllocatoinsBufferInitData
{
get
{
int desiredLength = VoxelTreeBranchingFactors.Length;
if (s_numAllocatoinsBufferInitData.IsCreated)
{
if (s_numAllocatoinsBufferInitData.Length == desiredLength)
return s_numAllocatoinsBufferInitData;
else
s_numAllocatoinsBufferInitData.Dispose();
}
s_numAllocatoinsBufferInitData = new NativeArray<int>(desiredLength, Allocator.Persistent, NativeArrayOptions.ClearMemory);
return s_numAllocatoinsBufferInitData;
}
}
private static NativeArray<int> s_unitIndirectDispatchArgsInitData;
private static NativeArray<int> UnitIndirectDispatchArgsInitData
{
get
{
if (s_unitIndirectDispatchArgsInitData.IsCreated)
return s_unitIndirectDispatchArgsInitData;
s_unitIndirectDispatchArgsInitData = new NativeArray<int>(new int[] { 1, 1, 1 }, Allocator.Persistent);
return s_unitIndirectDispatchArgsInitData;
}
}
private int[] m_numAllocationsBufferInitData;
private static readonly int NodeHashTableAllocationMultiplier = 2;
public int NodeHashTableSize
{
get
{
/*
switch (RenderMode)
{
case RenderModeEnum.RayTracedVoxels:
return MaxVoxels * NodeHashTableAllocationMultiplier;
}
*/
return MaxChunks * NodeHashTableAllocationMultiplier;
}
}
private static readonly int AutoSmoothVertDataAllocationMultiplier = 2;
public int AutoSmoothVertDataTableSize => MaxVoxels * AutoSmoothVertDataAllocationMultiplier;
public enum NumAllcationIndex
{
BrushMask,
VoxelCache,
VoxelHash,
AutoSmoothVertData,
}
private static bool s_warnedResourceAccessPerformanceImpact = false;
public long LocalResourceGpuMemoryAllocated
{
get
{
long bytes = 0;
if (!AllowSharedRWBuffers)
{
if (m_brushesBuffer != null)
bytes += m_brushesBuffer.stride * m_brushesBuffer.count;
if (m_brushMaterialBuffer != null)
bytes += m_brushMaterialBuffer.stride * m_brushMaterialBuffer.count;
if (m_aabbTreeBuffer != null)
bytes += m_aabbTreeBuffer.stride * m_aabbTreeBuffer.count;
}
if (m_nodePoolBuffer != null)
bytes += m_nodePoolBuffer.stride * ((long) m_nodePoolBuffer.count);
if (m_nodeHashTableBuffer != null)
bytes += m_nodeHashTableBuffer.stride * m_nodeHashTableBuffer.count;
if (m_numNodesAllocatedBuffer != null)
bytes += m_numNodesAllocatedBuffer.stride * m_numNodesAllocatedBuffer.count;
if (m_numAllocationsBuffer != null)
bytes += m_numAllocationsBuffer.stride * m_numAllocationsBuffer.count;
if (m_voxelCacheIdTableBuffer != null)
bytes += m_voxelCacheIdTableBuffer.stride * m_voxelCacheIdTableBuffer.count;
if (m_voxelCacheBuffer != null)
bytes += m_voxelCacheBuffer.stride * m_voxelCacheBuffer.count;
if (m_brushMaskPoolBuffer != null)
bytes += m_brushMaskPoolBuffer.stride * m_brushMaskPoolBuffer.count;
if (m_indirectDispatchArgsBuffer != null)
bytes += m_indirectDispatchArgsBuffer.stride * m_indirectDispatchArgsBuffer.count;
if (m_genPointsBufferDefault != null)
bytes += m_genPointsBufferDefault.stride * ((long)m_genPointsBufferDefault.count);
if (m_indirectDrawArgsBufferDefault != null)
bytes += m_indirectDrawArgsBufferDefault.stride * m_indirectDrawArgsBufferDefault.count;
if (m_autoSmoothVertDataTableBuffer != null)
bytes += m_autoSmoothVertDataTableBuffer.stride * m_autoSmoothVertDataTableBuffer.count;
if (!s_warnedResourceAccessPerformanceImpact && Application.isPlaying)
{
Debug.LogWarning("MudBun: Accessing resource usage impacts performance!");
s_warnedResourceAccessPerformanceImpact = true;
}
return bytes;
}
}
public long LocalResourceGpuMemoryUsed
{
get
{
long bytes = 0;
if (!AllowSharedRWBuffers)
{
if (m_brushesBuffer != null)
bytes += m_brushesBuffer.stride * m_brushesBuffer.count;
if (m_brushMaterialBuffer != null)
bytes += m_brushMaterialBuffer.stride * m_brushMaterialBuffer.count;
if (m_aabbTreeBuffer != null)
bytes += m_aabbTreeBuffer.stride * m_aabbTreeBuffer.count;
}
if (m_numNodesAllocatedBuffer != null)
{
bytes += m_numNodesAllocatedBuffer.stride * ((long)m_numNodesAllocatedBuffer.count);
var aNumNodesAllocated = new int[m_numNodesAllocatedBuffer.count];
m_numNodesAllocatedBuffer.GetData(aNumNodesAllocated);
int numTotalNodes = aNumNodesAllocated[0];
bytes += numTotalNodes * m_nodePoolBuffer.stride;
if (m_genPointsBufferDefault != null)
bytes += 6 * numTotalNodes * m_genPointsBufferDefault.stride;
}
int [] aNumAllocated = null;
if (m_numAllocationsBuffer != null)
{
aNumAllocated = new int[m_numAllocationsBuffer.count];
m_numAllocationsBuffer.GetData(aNumAllocated);
}
if (aNumAllocated != null)
{
if (m_nodeHashTableBuffer != null)
{
int numTotalHashes = aNumAllocated[(int) NumAllcationIndex.VoxelHash];
bytes += NodeHashTableAllocationMultiplier * numTotalHashes * m_nodeHashTableBuffer.stride;
}
if (m_autoSmoothVertDataTableBuffer != null)
{
int numSmoothVertData = aNumAllocated[(int) NumAllcationIndex.AutoSmoothVertData];
bytes += numSmoothVertData * m_autoSmoothVertDataTableBuffer.count;
}
}
if (m_numAllocationsBuffer != null)
bytes += m_numAllocationsBuffer.stride * m_numAllocationsBuffer.count;
if (m_voxelCacheIdTableBuffer != null)
bytes += m_voxelCacheIdTableBuffer.stride * m_voxelCacheIdTableBuffer.count;
if (m_voxelCacheBuffer != null)
bytes += m_voxelCacheBuffer.stride * m_voxelCacheBuffer.count;
if (m_brushMaskPoolBuffer != null)
bytes += m_brushMaskPoolBuffer.stride * m_brushMaskPoolBuffer.count;
if (m_indirectDispatchArgsBuffer != null)
bytes += m_indirectDispatchArgsBuffer.stride * m_indirectDispatchArgsBuffer.count;
if (m_indirectDrawArgsBufferDefault != null)
bytes += m_indirectDrawArgsBufferDefault.stride * m_indirectDrawArgsBufferDefault.count;
if (!s_warnedResourceAccessPerformanceImpact && Application.isPlaying)
{
Debug.LogWarning("MudBun: Accessing resource usage impacts performance!");
s_warnedResourceAccessPerformanceImpact = true;
}
return bytes;
}
}
public int NumVerticesAllocated => VoxelToVertexFactor * NumVoxelsAllocated;
public int NumVerticesGenerated
{
get
{
if (m_indirectDispatchArgsBuffer == null)
return 0;
int[] aIndirectDrawArgs = new int[5];
m_indirectDrawArgsBufferDefault.GetData(aIndirectDrawArgs);
if (!s_warnedResourceAccessPerformanceImpact && Application.isPlaying)
{
Debug.LogWarning("MudBun: Accessing resource usage impacts performance!");
s_warnedResourceAccessPerformanceImpact = true;
}
return aIndirectDrawArgs[0];
}
}
public int NumVoxelsAllocated => (m_nodePoolBuffer != null) ? MaxVoxels : 0;
public int NumChunksAllocated => (m_nodeHashTableBuffer != null) ? MaxChunks : 0;
public int NumVoxelsUsed
{
get
{
if (m_numNodesAllocatedBuffer == null)
return 0;
var aNumAllocated = new int[m_numNodesAllocatedBuffer.count];
m_numNodesAllocatedBuffer.GetData(aNumAllocated);
if (!s_warnedResourceAccessPerformanceImpact && Application.isPlaying)
{
Debug.LogWarning("MudBun: Accessing resource usage impacts performance!");
s_warnedResourceAccessPerformanceImpact = true;
}
return aNumAllocated[0];
}
}
public int NumChunksUsed
{
get
{
if (m_numAllocationsBuffer == null)
return 0;
var aNumAllocated = new int[m_numAllocationsBuffer.count];
m_numAllocationsBuffer.GetData(aNumAllocated);
int numTotalHashes = aNumAllocated[(int)NumAllcationIndex.VoxelHash];
if (!s_warnedResourceAccessPerformanceImpact && Application.isPlaying)
{
Debug.LogWarning("MudBun: Accessing resource usage impacts performance!");
s_warnedResourceAccessPerformanceImpact = true;
}
return numTotalHashes;
}
}
public bool ForceEvaluateAllBrushes = false;
private bool ShouldForceAllBrushes()
{
if (ForceEvaluateAllBrushes)
return true;
// trial version can't reference MudSolid
// should probably manually force this with the manual option anyway
/*
if (Enable2dMode)
{
if (Normal2dFade > MathUtil.Epsilon)
{
foreach (var b in m_aBrush)
{
var sb = (MudSolid) b;
if (sb.Operator == SdfBrush.OperatorEnum.Subtract)
return true;
}
}
}
*/
return false;
}
public bool Enable2dMode = false;
[Range(-1.0f, 1.0f)] public float SurfaceShift = 0.0f;
public HardwareModeEnum HardwareMode = HardwareModeEnum.Gpu;
public RenderModeEnum RenderMode = RenderModeEnum.SmoothMesh;
public RenderModeCategoryEnum RenderModeCategory
{
get
{
switch (RenderMode)
{
case RenderModeEnum.FlatMesh:
case RenderModeEnum.SmoothMesh:
return RenderModeCategoryEnum.Mesh;
case RenderModeEnum.CircleSplats:
case RenderModeEnum.QuadSplats:
return RenderModeCategoryEnum.Splats;
case RenderModeEnum.Decal:
return RenderModeCategoryEnum.Decal;
/*
case RenderModeEnum.RayMarchedSurface:
return RenderModeCategoryEnum.RayMarchedSurface;
case RenderModeEnum.RayTracedVoxels:
return RenderModeCategoryEnum.RayTracedVoxels;
*/
}
return RenderModeCategoryEnum.Mesh;
}
}
public MeshingModeEnum MeshingMode = MeshingModeEnum.MarchingCubes;
public RayTracedVoxelModeEnum RayTracedVoxelMode = RayTracedVoxelModeEnum.FlatCubes;
[Range(0.0f, 1.0f)] public float RayTracedVoxelSizeMultiplier = 1.0f;
[Range(0.0f, 1.0f)] public float RayTracedVoxelSmoothCubeNormal = 0.0f;
[Range(0.0f, 1.0f)] public float RayTracedVoxelSphereFullness = 0.0f;
public RayTracedVoxelPaddingModeEnum RayTracedVoxelPaddingMode = RayTracedVoxelPaddingModeEnum.ByDistance;
public float RayTracedVoxelInternalPaddingDistance = 0.0f;
public float RayTracedVoxelSizeFadeDistance = 0.0f;
private static RenderModeCategoryEnum GetMaterialRenderModeCategory(Material material)
{
if (material == null)
return RenderModeCategoryEnum.Unknown;
if (material.HasProperty(Const.IsMeshRenderMaterial))
return RenderModeCategoryEnum.Mesh;
if (material.HasProperty(Const.IsSplatRenderMaterial))
return RenderModeCategoryEnum.Splats;
return RenderModeCategoryEnum.Unknown;
}
private static bool MaterialNeedsSdfProperties(Material material)
{
if (material == null)
return false;
return material.HasProperty(Const.MaterialNeedsSdfProperties);
}
private static bool MaterialNeedsRayMarchingProperties(Material material)
{
if (material == null)
return false;
return material.HasProperty(Const.MaterialNeedsRayMarchingProperties);
}
private enum RenderGeometryTypeEnum
{
Unknown = -1,
Mesh,
BoxProxy,
Chunks,
}
private RenderGeometryTypeEnum RenderGeometryType
{
get
{
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Mesh:
case RenderModeCategoryEnum.Splats:
return RenderGeometryTypeEnum.Mesh;
case RenderModeCategoryEnum.Decal:
//case RenderModeCategoryEnum.RayMarchedSurface:
return RenderGeometryTypeEnum.BoxProxy;
/*
case RenderModeCategoryEnum.RayTracedVoxels:
return RenderGeometryTypeEnum.Chunks;
*/
}
return RenderGeometryTypeEnum.Unknown;
}
}
private bool RenderMaterialNeedsSdfProperties
{
get
{
if (MaterialNeedsSdfProperties(m_materialUsed))
return true;
return false;
}
}
private RenderGeometryTypeEnum m_prevRenderGeometryType = RenderGeometryTypeEnum.Unknown;
public bool ShowAdvancedNormalOptions = false;
[Range(0.0f, 1.0f)] public float SmoothNormalBlurRelative = 0.05f;
[Range(0.0f, 0.2f)] public float SmoothNormalBlurAbsolute = 0.0f;
public float NormalDifferentialStep => Mathf.Max(0.01f * VoxelSize, SmoothNormalBlurRelative * VoxelSize + SmoothNormalBlurAbsolute);
[Range(0.0f, 1.0f)] public float NormalQuantization = 0.0f;
[Range(0.0f, 1.0f)] public float Normal2dFade = 0.0f;
[Range(0.0f, 1.0f)] public float Normal2dStrength = 1.0f;
public bool EnableAutoSmoothing = false;
[Range(0.0f, 180.0f)] public float AutoSmoothingMaxAngle = 30.0f;
public bool EnableSmoothCorner = false;
[Range(1, 4)] public int SmoothCornerSubdivision = 2;
[Range(0.001f, 0.1f)] public float SmoothCornerNormalBlur = 0.02f;
[Range(0.0f, 1.0f)] public float SmoothCornerFade = 0.0f;
public bool InvertNormals = false;
private bool ShouldDoAutoSmoothing
{
get
{
if (!EnableAutoSmoothing)
return false;
if (Enable2dMode)
return false;
switch (MeshingMode)
{
case MeshingModeEnum.MarchingCubes:
case MeshingModeEnum.SurfaceNets:
case MeshingModeEnum.DualContouring:
switch (RenderMode)
{
case RenderModeEnum.FlatMesh:
case RenderModeEnum.SmoothMesh:
return true;
}
break;
}
return false;
}
}
public bool ShowAdvancedSplatOptions = false;
[Range(0.0f, 5.0f)] public float SplatSize = 1.0f;
[Range(0.0f, 1.0f)] public float SplatSizeJitter = 0.0f;
[Range(-1.0f, 1.0f)] public float SplatNormalShift = 0.0f;
[Range(0.0f, 1.0f)] public float SplatNormalShiftJitter = 1.0f;
[Range(0.0f, 1.0f)] public float SplatColorJitter = 0.0f;
[Range(0.0f, 1.0f)] public float SplatPositionJitter = 0.0f;
[Range(0.0f, 1.0f)] public float SplatRotationJitter = 0.0f;
[Range(0.0f, 1.0f)] public float SplatOrientationJitter = 0.0f;
[Range(0.0f, 1.0f)] public float SplatOriginalNormalBlend = 1.0f;
[Range(0.01f, 1.0f)] public float SplatJitterNoisiness = 1.0f;
[Range(0.0f, 1.0f)] public float SplatCameraFacing = 0.0f;
public bool SplatNormalsMatchCameraFacing = false;
public bool SplatShadowsMatchCameraFacing = false;
[Range(0.0f, 1.0f)] public float SplatScreenSpaceFlattening = 1.0f;
//[Range(0.0f, 1.0f)] public float SplatSmoothNormalBlend = 0.0f;
[Range(0.0f, 1.0f)] public float SurfaceNetsDualQuadsBlend = 0.0f;
public bool ShowAdvancedGeometryOptions = false;
//[Range(0, 10)] public int SurfaceNetsBinarySearchIterations = 0;
//[Range(0, 5)] public int SurfaceNetsGradientDescentIterations = 0;
//[Range(0.0f, 1.0f)] public float SurfaceNetsGradientDescentFactor = 1.0f;
public bool SurfaceNetsHighAccuracyMode = false;
[Range(0.0f, 1.0f)] public float DualContouringDualQuadsBlend = 0.0f;
[Range(0.0f, 1.0f)] public float DualContouringRelaxation = 0.0f;
[Range(0, 20)] public int DualContouringSolverIterations = 5;
//[Range(0, 10)] public int DualContouringBinarySearchIterations = 0;
//[Range(0, 5)] public int DualContouringGradientDescentIterations = 0;
//[Range(0.0f, 1.0f)] public float DualContouringGradientDescentFactor = 1.0f;
public bool DualContouringHighAccuracyMode = false;
public ShadowCastingMode CastShadows = ShadowCastingMode.On;
public bool ReceiveShadows = true;
public IList<MudBrushBase> Brushes => m_aBrush;
private List<MudBrushBase> m_aBrush = new List<MudBrushBase>();
private List<MudBrushBase> m_aBrushToProcess = new List<MudBrushBase>();
private bool m_needRescanBrushes = false;
private static readonly float AabbTreeFatBoundsRadius = 0.25f;
internal AabbTree<MudBrushBase> m_aabbTree;
private void ValidateAabbTree()
{
if (m_aabbTree != null)
return;
m_aabbTree = new AabbTree<MudBrushBase>(AabbTreeFatBoundsRadius);
}
//[Header("Material")]
private MudSharedMaterialBase m_usedSharedMaterial;
public MudSharedMaterialBase SharedMaterial;
[SerializeField] private Color m_masterColor = Color.white;
[SerializeField] private Color m_masterEmission = Color.white;
[SerializeField] [Range(0.0f, 1.0f)] private float m_masterMetallic = 1.0f;
[SerializeField] [Range(0.0f, 1.0f)] private float m_masterSmoothness = 1.0f;
public Color MasterColor { get => m_usedSharedMaterial ? m_usedSharedMaterial.Color : m_masterColor; set { m_masterColor = value; } }
public Color MasterEmission { get => m_usedSharedMaterial ? m_usedSharedMaterial.Emission : m_masterEmission; set { m_masterEmission = value; } }
public float MasterMetallic { get => m_usedSharedMaterial ? m_usedSharedMaterial.Metallic : m_masterMetallic; set { m_masterMetallic = value; } }
public float MasterSmoothness { get => m_usedSharedMaterial ? m_usedSharedMaterial.Smoothness : m_masterSmoothness; set { m_masterSmoothness = value; } }
public Material RenderMaterialMesh;
public Material RenderMaterialSplats;
public Material RenderMaterialDecal;
//public Material RenderMaterialRayMarchedSurface;
//public Material RenderMaterialRayTracedVoxels;
public Material RenderMaterial
{
get
{
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Mesh:
return RenderMaterialMesh;
case RenderModeCategoryEnum.Splats:
return RenderMaterialSplats;
case RenderModeCategoryEnum.Decal:
return RenderMaterialDecal;
/*
case RenderModeCategoryEnum.RayMarchedSurface:
return RenderMaterialRayMarchedSurface;
case RenderModeCategoryEnum.RayTracedVoxels:
return RenderMaterialRayTracedVoxels;
*/
}
return RenderMaterialMesh;
}
}
private Material m_materialCloned;
private Material m_materialUsed;
private MaterialPropertyBlock m_materialProps;
public MaterialPropertyBlock RenderMaterialPropertyBlock
{
get
{
if (m_materialProps != null)
return m_materialProps;
m_materialProps = new MaterialPropertyBlock();
return m_materialProps;
}
}
[Range(8, 256)] public int MaxRayMarchSteps = 64;
[Range(0.0f, 1.0f)] public float RayMarchAccuracy = 0.5f;
[Range(1.0f, 2e3f)] public float RayMarchMaxRayDistance = 1e3f;
[Range(0.1f, 10.0f)] public float RayMarchStepSize = 0.5f;
[Range(1, 16)] public int NumLightMarchSteps = 8;
//[Range(0.1f, 100.0f)] public float RayMarchDistance = 20.0f;
[Range(0.0f, 20.0f)] public float RayMarchVolumeDensity = 5.0f;
public Light RayMarchLight;
[Range(0.0f, 10.0f)] public float RayMarchVolumeAbsorption = 1.0f;
[Range(0.0f, 10.0f)] public float RayMarchLightAbsorption = 1.0f;
[Range(0.0f, 1.0f)] public float RayMarchDarknesThreshold = 0.1f;
[Range(0.0f, 10.0f)] public float RayMarchTransmittanceCurve = 0.0f;
public bool UseRayMarchNoise = false;
[Range(0.0f, 1.0f)] public float RayMarchNoiseThreshold = 0.2f;
[Range(0.0f, 10.0f)] public float RayMarchNoiseEdgeFade = 2.0f;
public Vector3 RayMarchNoiseScrollSpeed = Vector3.zero;
public Vector3 RayMarchNoiseBaseOctaveSize = Vector3.one;
[Range(1, 3)] public int RayMarchNoiseNumOctaves = 2;
public float RayMarchNoiseOctaveOffsetFactor = 0.5f;
private Sdf.EvalJob[] m_aEvalJob;
//[Header("Editor")]
public enum ClickSelectionEnum
{
None,
Gizmos,
Raycast,
[InspectorName("Raycast (Forced Zero-Blend Union)")] RaycastForcedZeroBlendUnion,
}
public ClickSelectionEnum ClickSelection = ClickSelectionEnum.Raycast;
//[Header("Debug")]
public bool AlwaysDrawGizmos = false;
public bool DrawRawBrushBounds = false;
public bool DrawComputeBrushBounds = false;
public bool DrawRenderBounds = false;
public bool DrawVoxelNodes = false;
[Range(-1, 3)] public int DrawVoxelNodesDepth = -1;
[Range(0.0f, 1.0f)] public float DrawVoxelNodesScale = 1.0f;
public Aabb RenderBounds
{
get
{
var bounds = RenderBoundsRs;
if (!bounds.IsEmpty) // don't expand if empty, or it might crash the GPU!
{
bounds.Expand(SurfaceShift);
bounds.Transform(transform);
}
return bounds;
}
}
public Aabb RenderBoundsRs => m_aabbTree.Bounds;
[SerializeField] [HideInInspector] private string m_firstTrackedVersion = "";
[SerializeField] [HideInInspector] private string m_previousTrackedVersion = "";
[SerializeField] [HideInInspector] private string m_currentTrackedVersion = "";
public string FirstTrackedVersion => m_firstTrackedVersion;
public string PreviousTrackedVersion => m_previousTrackedVersion;
public string CurrentTrackedVersion => m_currentTrackedVersion;
#endregion // end: Local Resources
//-------------------------------------------------------------------------
#region Mesh Utilities
public static readonly float MaxMeshGenerationVoxelDensityFreeVersion = 8.0f;
public static readonly int MaxMeshGenerationTrianglesFreeVersion = 4096;
public float MeshGenerationVoxelDensity
{
get
{
#if MUDBUN_FREE
return Mathf.Min(MaxMeshGenerationVoxelDensityFreeVersion, VoxelDensity);
#else
return VoxelDensity;
#endif
}
}
public enum RenderableMeshMode
{
None,
Procedural,
MeshRenderer,
}
public enum AutoRiggingAlgorithm
{
New, // not ready yet
Default, // will be Legacy once New is ready
}
public bool MeshGenerationCreateNewObject = false;
public bool MeshGenerationCreateCollider = false;
public bool MeshGenerationForceConvexCollider = false;
[Range(-1.0f, 1.0f)] public float MeshGenerationColliderSurfaceShift = 0.0f;
public bool MeshGenerationCreateRigidBody = false;
public bool GenerateColliderMeshAssetByEditor = true; // editor only
public string GenerateColliderMeshAssetByEditorName = ""; // editor only
#if MUDBUN_FREE
[Range(0.0f, 8.0f)] public float MeshGenerationColliderVoxelDensity = 4.0f;
#else
[Range(0.0f, 128.0f)] public float MeshGenerationColliderVoxelDensity = 4.0f;
#endif
public RenderableMeshMode MeshGenerationRenderableMeshMode = RenderableMeshMode.Procedural;
public bool MeshGenerationAutoRigging = false;
public AutoRiggingAlgorithm MeshGenerationAutoRiggingAlgorithm = AutoRiggingAlgorithm.Default;
[Range(1, 4)] public int MeshGenerationAutoRiggingMaxBonesPerVertex = 4;
public bool MeshGenerationGenerateTextureUV = false;
public bool MeshGenerationGenerateLightMapUV = false;
public bool MeshGenerationWeldVertices = false;
public bool MeshGenerationLockOnStart = false;
public bool GenerateMeshAssetByEditor = true; // editor only
public string GenerateMeshAssetByEditorName = ""; // editor only
public bool RecursiveLockMeshByEditor = true; // editor only
public bool RememberLockedMeshMaterialByEditor = true; // editor only
[SerializeField] [HideInInspector] public bool MeshGenerationLockOnStartByEditor = false; // editor only
[SerializeField] protected Material m_lastLockedMeshMaterial;
[Serializable]
private class TransformCache
{
public Transform Transform;
public Transform Parent;
public Vector3 GlobalPosition;
public Quaternion GlobalRotation;
public Vector3 LocalPosition;
public Quaternion LocalRotation;
public Vector3 LocalScale;
public bool HasBrushDescendants;
}
// order: parent->child
[SerializeField] [HideInInspector] private List<TransformCache> m_aBrushTransformCache;
[SerializeField] [HideInInspector] private List<TransformCache> m_aNestedRendereTransformCache;
private bool HashNonMudBunObjectInHierarchy(Transform t)
{
if (t == null)
return false;
if (t.TryGetComponent(out Collider _) || t.TryGetComponent(out Collider2D _))
return true;
if (t.TryGetComponent(out MeshRenderer _) || t.TryGetComponent(out SkinnedMeshRenderer _))
{
if (!t.TryGetComponent(out MudRendererBase r) || !r.MeshLocked)
{
if (r != null)
return true;
}
}
for (int i = 0; i < t.childCount; ++i)
{
if (HashNonMudBunObjectInHierarchy(t.GetChild(i)))
return true;
}
return false;
}
private bool HasBrushInHierarchy(Transform t)
{
if (t == null)
return false;
if (t.TryGetComponent(out MudBrushBase _))
return true;
for (int i = 0; i < t.childCount; ++i)
{
if (HasBrushInHierarchy(t.GetChild(i)))
return true;
}
return false;
}
private void DetectMixedHierarchy(Transform t)
{
if (!HasBrushInHierarchy(t) || !HashNonMudBunObjectInHierarchy(t))
return;
Debug.LogWarning
(
"WARNING: Mixed MudBun objects and non-MudBun objects in renderer hierarchy detected during auto-rigging. "
+ "This can cause issues when normalizing bones to a unit scale of (1, 1, 1).\n"
+ "Please follow this guideline: "
+ "Objects with mixed MudBun objects and non-MudBun objects in their hierarchy should have a unit scale of (1, 1, 1)."
);
}
private void CacheBoneTransforms()
{
m_aBrushTransformCache = new List<TransformCache>();
m_aNestedRendereTransformCache = new List<TransformCache>();
CacheBoneTransformsRecursive(transform);
DetectMixedHierarchy(transform);
}
private void NormalizeBoneTransforms()
{
if (m_aBrushTransformCache == null)
return;
// move nested renderers out of the way
foreach (var cache in m_aNestedRendereTransformCache)
{
cache.Transform.SetParent(null, true);
}
// set each bone's local scale to unit scale to avoid shearing in child bones
foreach (var cache in m_aBrushTransformCache)
{
if (cache.HasBrushDescendants)
{
cache.Transform.localScale = Vector3.one;
cache.Transform.position = cache.GlobalPosition;
cache.Transform.rotation = cache.GlobalRotation;
}
else
{
cache.Transform.position = cache.GlobalPosition;
cache.Transform.rotation = cache.GlobalRotation;
}
}
// put nested renderers back in hierarchy
foreach (var cache in m_aNestedRendereTransformCache)
{
cache.Transform.SetParent(cache.Parent, true);
cache.Transform.position = cache.GlobalPosition;
cache.Transform.rotation = cache.GlobalRotation;
}
}
private void CacheBoneTransformsRecursive(Transform t)
{
if (t == null)
return;
var cache =
new TransformCache()
{
Transform = t,
Parent = t.parent,
GlobalPosition = t.position,
GlobalRotation = t.rotation,
LocalPosition = t.localPosition,
LocalRotation = t.localRotation,
LocalScale = t.localScale,
HasBrushDescendants = HasBrushInHierarchy(t),
};
if (t != transform)
{
if (t.GetComponent<MudRendererBase>() == null)
{
m_aBrushTransformCache.Add(cache);
}
else
{
// renderer blocks recursion
m_aNestedRendereTransformCache.Add(cache);
return;
}
}
for (int i = 0; i < t.childCount; ++i)
{
var child = t.GetChild(i);
CacheBoneTransformsRecursive(t.GetChild(i));
}
}
private void RestoreBoneTransforms()
{
if (m_aBrushTransformCache == null)
return;
// move nested renderers out of the way
foreach (var cache in m_aNestedRendereTransformCache)
{
try
{
cache.Transform.SetParent(null, true);
}
catch (Exception)
{ }
}
// restore brush transforms
foreach (var cache in m_aBrushTransformCache)
{
try
{
cache.Transform.localScale = cache.LocalScale;
cache.Transform.localPosition = cache.LocalPosition;
cache.Transform.localRotation = cache.LocalRotation;
}
catch (Exception)
{ }
}
// restore nested renderer transforms
foreach (var cache in m_aNestedRendereTransformCache)
{
try
{
cache.Transform.SetParent(cache.Parent, true);
cache.Transform.localScale = cache.LocalScale;
cache.Transform.localPosition = cache.LocalPosition;
cache.Transform.localRotation = cache.LocalRotation;
}
catch (Exception)
{ }
}
m_aBrushTransformCache = null;
m_aNestedRendereTransformCache = null;
}
public enum GeneratedMeshType
{
Standard,
Compute,
Collider,
}
private class PendingMeshData
{
public Mesh Mesh;
public GeneratedMeshType MeshType;
public Transform RootBone;
public List<Transform> Bones;
public bool DoRigging;
public bool GenerateTextureUV;
public bool GenerateLightMapUV;
public bool WeldVertices;
public bool OptimizeMeshForRendering;
public bool Async;
public ComputeBuffer IndirectDrawArgsBuffer;
public ComputeBuffer GenPointsBuffer;
public void Dispose()
{
if (IndirectDrawArgsBuffer != null)
{
//IndirectDrawArgsBuffer.Release();
Janitor.Dispose(IndirectDrawArgsBuffer);
IndirectDrawArgsBuffer = null;
}
if (GenPointsBuffer != null)
{
//GenPointsBuffer.Release();
Janitor.Dispose(GenPointsBuffer);
GenPointsBuffer = null;
}
}
}
private Dictionary<AsyncGPUReadbackRequest, PendingMeshData> m_pendingMeshTable = new Dictionary<AsyncGPUReadbackRequest, PendingMeshData>();
public bool IsAnyMeshGenerationPending => m_pendingMeshTable != null && m_pendingMeshTable.Count > 0;
public bool IsMeshGenerationPending(Mesh mesh)
{
foreach (var pair in m_pendingMeshTable)
if (pair.Value.Mesh == mesh)
return true;
return false;
}
public void WaitForMeshGeneration(Mesh mesh)
{
foreach (var pair in m_pendingMeshTable)
{
if (pair.Value.Mesh != mesh)
continue;
pair.Key.WaitForCompletion();
break;
}
}
public Mesh GenerateMesh
(
GeneratedMeshType meshType,
bool async,
Mesh mesh = null,
bool generateTextureUV = false,
bool generateLightMapUV = false,
bool weldVertices = false,
bool optimizeMeshForRendering = false
)
{
Transform [] aBone;
return GenerateMesh(meshType, null, out aBone, async, mesh, generateTextureUV, generateLightMapUV, weldVertices, optimizeMeshForRendering);
}
public Mesh GenerateMesh
(
GeneratedMeshType meshType,
Transform rootBone,
out Transform [] aBone,
bool async,
Mesh mesh = null,
bool genreateTextureUV = false,
bool generateLightMapUV = false,
bool weldVertices = false,
bool optimizeMeshForRendering =false
)
{
aBone = null;
if (meshType == GeneratedMeshType.Compute)
return null;
UpdateComputeData();
ValidateLocalResources();
var prevRenderMode = RenderMode;
var prevMeshingMode = MeshingMode;
float prevVoxelDensity = VoxelDensity;
int prevMaxVoxelsK = MaxVoxelsK;
int prevMaxChunks = MaxChunks;
float prevSurfaceShift = SurfaceShift;
if (meshType == GeneratedMeshType.Collider)
{
RenderMode = RenderModeEnum.FlatMesh;
VoxelDensity = MeshGenerationColliderVoxelDensity;
SurfaceShift += MeshGenerationColliderSurfaceShift;
}
else
{
VoxelDensity = MeshGenerationVoxelDensity;
}
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Splats:
RenderMode = RenderModeEnum.FlatMesh;
break;
/*
case RenderModeCategoryEnum.RayMarchedSurface:
RenderMode = RenderModeEnum.FlatMesh;
MeshingMode = MeshingModeEnum.DualQuads;
break;
*/
}
// always override buffers to work in Metal
m_indirectDrawArgsBufferOverride = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments);
m_genPointsBufferOverride = new ComputeBuffer(MaxGenPoints, GenPoint.Stride);
var indirectDrawArgsBuffer = m_indirectDrawArgsBufferOverride;
var genPointsBuffer = m_genPointsBufferOverride;
indirectDrawArgsBuffer.SetData(IndirectDrawArgsInitData);
ForceCompute();
RenderMode = prevRenderMode;
MeshingMode = prevMeshingMode;
VoxelDensity = prevVoxelDensity;
MaxVoxelsK = prevMaxVoxelsK;
MaxChunks = prevMaxChunks;
SurfaceShift = prevSurfaceShift;
MarkNeedsCompute();
if (indirectDrawArgsBuffer == null)
return null;
if (genPointsBuffer == null)
return null;
if (mesh == null)
mesh = new Mesh();
var pendingMeshData =
new PendingMeshData()
{
Mesh = mesh,
MeshType = meshType,
RootBone = rootBone,
Bones = m_aBone,
DoRigging = m_doRigging,
GenerateTextureUV = genreateTextureUV,
GenerateLightMapUV = generateLightMapUV,
WeldVertices = weldVertices,
OptimizeMeshForRendering = optimizeMeshForRendering,
Async = async,
IndirectDrawArgsBuffer = indirectDrawArgsBuffer,
GenPointsBuffer = genPointsBuffer,
};
if (m_aBone != null)
{
aBone = m_aBone.ToArray();
m_aBone = null;
}
var request = AsyncGPUReadback.Request(pendingMeshData.IndirectDrawArgsBuffer, OnIndirectDrawArgsBufferRead);
m_pendingMeshTable.Add(request, pendingMeshData);
if (!async)
request.WaitForCompletion();
return mesh;
}
private void OnIndirectDrawArgsBufferRead(AsyncGPUReadbackRequest request)
{
PendingMeshData pendingMeshData;
bool dataFound = m_pendingMeshTable.TryGetValue(request, out pendingMeshData);
m_pendingMeshTable.Remove(request);
var aDrawArgs = request.GetData<int>();
if (!dataFound
|| aDrawArgs.Length <= 0
|| request.hasError)
{
if (pendingMeshData != null)
pendingMeshData.Dispose();
return;
}
int numVerts = aDrawArgs[0];
if (MudBun.IsFreeVersion)
numVerts = Mathf.Min(numVerts, 3 * MaxMeshGenerationTrianglesFreeVersion);
if (numVerts <= 0)
{
pendingMeshData.Dispose();
return;
}
var newRequest = AsyncGPUReadback.Request(pendingMeshData.GenPointsBuffer, numVerts * pendingMeshData.GenPointsBuffer.stride, 0, OnGenPointsBufferRead);
m_pendingMeshTable.Add(newRequest, pendingMeshData);
if (!pendingMeshData.Async)
newRequest.WaitForCompletion();
}
private void OnGenPointsBufferRead(AsyncGPUReadbackRequest request)
{
PendingMeshData pendingMeshData;
bool dataFound = m_pendingMeshTable.TryGetValue(request, out pendingMeshData);
m_pendingMeshTable.Remove(request);
if (!dataFound
|| request.hasError)
{
if (pendingMeshData != null)
pendingMeshData.Dispose();
return;
}
var aGenPoint = request.GetData<GenPoint>();
BuildMesh
(
pendingMeshData.Mesh,
pendingMeshData.MeshType,
aGenPoint,
pendingMeshData.RootBone,
pendingMeshData.Bones,
pendingMeshData.DoRigging,
pendingMeshData.GenerateTextureUV,
pendingMeshData.GenerateLightMapUV,
pendingMeshData.WeldVertices,
pendingMeshData.OptimizeMeshForRendering
);
if (pendingMeshData.Async
&& pendingMeshData.IndirectDrawArgsBuffer == m_indirectDrawArgsBufferDefault
&& pendingMeshData.GenPointsBuffer == m_genPointsBufferDefault
&& m_isMeshLocked)
{
DisposeLocalResources();
}
InvokeOnMeshGenerated(pendingMeshData.Mesh);
pendingMeshData.Dispose();
}
private void BuildMesh
(
Mesh mesh,
GeneratedMeshType meshType,
NativeArray<GenPoint> aGenPoint,
Transform rootBone,
List<Transform> bones,
bool doRigging,
bool generateTextureUV,
bool generateLightMapUV,
bool weldVertices,
bool optimizeMeshForRendering
)
{
int numVerts = aGenPoint.Length;
var aVertex = new NativeArray<Vector3>(numVerts, Allocator.Temp);
var aNormal = new NativeArray<Vector3>(numVerts, Allocator.Temp);
var aTangent = new NativeArray<Vector4>(numVerts, Allocator.Temp);
var aVertIndex = new NativeArray<int>(numVerts, Allocator.Temp);
bool invertNormals = InvertNormals && !Enable2dMode;
for (int i = 0; i < numVerts; ++i)
{
aVertex[i] = aGenPoint[i].PosNorm;
aNormal[i] = Codec.UnpackNormal(aGenPoint[i].PosNorm.w);
aTangent[i] = VectorUtil.FindOrthogonal(aNormal[i]);
aVertIndex[i] = invertNormals ? (3 * (i / 3) + 2 - (i % 3) ) : i;
}
mesh.Clear();
mesh.SetVertices(aVertex);
mesh.SetNormals(aNormal);
mesh.SetTangents(aTangent);
mesh.indexFormat = numVerts > 65535 ? IndexFormat.UInt32 : IndexFormat.UInt16;
mesh.SetIndices(aVertIndex, MeshTopology.Triangles, 0);
if (meshType == GeneratedMeshType.Standard)
{
Color [] aColor = new Color[numVerts];
Vector4 [] aEmissionHash = new Vector4[numVerts];
Vector2 [] aMetallicSmoothness = new Vector2[numVerts];
Vector4 [] aTextureWeight = new Vector4[numVerts];
BoneWeight [] aBoneWeight = null;
if (doRigging)
{
CacheBoneTransforms();
aBoneWeight = new BoneWeight[numVerts];
}
for (int i = 0; i < numVerts; ++i)
{
Color c = Codec.UnpackRgba(aGenPoint[i].Material.Color);
Color et = Codec.UnpackRgba(aGenPoint[i].Material.EmissionTightness);
/*
if (QualitySettings.activeColorSpace == ColorSpace.Linear)
{
float gamma = 2.2f;
aColor[i] =
new Color
(
Mathf.Pow(c.r * MasterColor.r, gamma),
Mathf.Pow(c.g * MasterColor.g, gamma),
Mathf.Pow(c.b * MasterColor.b, gamma),
c.a * MasterColor.a
);
aEmissionHash[i] =
new Vector4
(
Mathf.Pow(et.r * MasterEmission.r, gamma),
Mathf.Pow(et.g * MasterEmission.g, gamma),
Mathf.Pow(et.b * MasterEmission.b, gamma),
aGenPoint[i].Material.Hash
);
}
else
*/
{
aColor[i] = c * MasterColor;
aEmissionHash[i] =
new Vector4
(
et.r * MasterEmission.r,
et.g * MasterEmission.g,
et.b * MasterEmission.b,
aGenPoint[i].Material.Hash
);
}
Vector2 ms = Codec.UnpackSaturated(aGenPoint[i].Material.MetallicSmoothness);
aMetallicSmoothness[i] = new Vector2(ms.x * MasterMetallic, ms.y * MasterSmoothness);
aTextureWeight[i] = Codec.UnpackRgba(aGenPoint[i].Material.TextureWeight);
if (aBoneWeight != null)
{
aBoneWeight[i].boneIndex0 = aGenPoint[i].BoneIndex0;
aBoneWeight[i].boneIndex1 = aGenPoint[i].BoneIndex1;
aBoneWeight[i].boneIndex2 = aGenPoint[i].BoneIndex2;
aBoneWeight[i].boneIndex3 = aGenPoint[i].BoneIndex3;
Vector4 boneWeight = Codec.UnpackRgba(aGenPoint[i].BoneWeight);
for (int iWeightComp = 4; iWeightComp > MeshGenerationAutoRiggingMaxBonesPerVertex && iWeightComp >= 0; --iWeightComp)
boneWeight[iWeightComp - 1] = 0.0f;
if (aBoneWeight[i].boneIndex0 < 0)
{
aBoneWeight[i].boneIndex0 = 0;
boneWeight.x = 0.0f;
}
if (aBoneWeight[i].boneIndex1 < 0)
{
aBoneWeight[i].boneIndex1 = 0;
boneWeight.y = 0.0f;
}
if (aBoneWeight[i].boneIndex2 < 0)
{
aBoneWeight[i].boneIndex2 = 0;
boneWeight.z = 0.0f;
}
if (aBoneWeight[i].boneIndex3 < 0)
{
aBoneWeight[i].boneIndex3 = 0;
boneWeight.w = 0.0f;
}
boneWeight /= Mathf.Max(MathUtil.Epsilon, Vector4.Dot(boneWeight, Vector4.one));
aBoneWeight[i].weight0 = MathUtil.Saturate(boneWeight.x);
aBoneWeight[i].weight1 = MathUtil.Saturate(boneWeight.y);
aBoneWeight[i].weight2 = MathUtil.Saturate(boneWeight.z);
aBoneWeight[i].weight3 = MathUtil.Saturate(boneWeight.w);
}
}
mesh.SetColors(aColor);
mesh.SetUVs(MeshUtil.EmissionHashUvIndex, aEmissionHash);
mesh.SetUVs(MeshUtil.MetallicSmoothnessUvIndex, aMetallicSmoothness);
mesh.SetUVs(MeshUtil.TextureWeightIndex, aTextureWeight);
if (aBoneWeight != null
&& rootBone != null
&& bones != null)
{
NormalizeBoneTransforms();
mesh.boneWeights = aBoneWeight;
mesh.bindposes = bones.Select(x => x.worldToLocalMatrix * rootBone.localToWorldMatrix).ToArray();
}
bool uvGenerated = GenerateUV(mesh, generateTextureUV, generateLightMapUV);
if (weldVertices)
{
MeshUtil.Weld(mesh, (uvGenerated ? 0 : -1));
}
if (optimizeMeshForRendering)
{
mesh.Optimize();
}
}
}
public virtual void RectifyNonUnitScaledParents() { }
virtual protected bool GenerateUV(Mesh mesh, bool generateTextureUV, bool generateLightMapUV) { return false; }
[SerializeField] [HideInInspector] private bool m_isMeshLocked = false;
public bool MeshLocked => m_isMeshLocked;
protected enum LockMeshIntermediateStateEnum
{
Idle,
PreLock,
PostLock,
PreUnlock,
}
protected virtual LockMeshIntermediateStateEnum LockMeshIntermediateState => LockMeshIntermediateStateEnum.Idle;
protected bool m_doRigging = false;
public virtual Mesh AddCollider
(
GameObject go,
bool async,
Mesh mesh = null,
bool forceConvexCollider = false,
bool makeRigidBody = false
)
{
return null;
}
public virtual Mesh AddLockedStandardMesh
(
GameObject go,
bool autoRigging,
bool async,
Mesh mesh = null,
bool generateTextureUV = false,
bool generateLightMapUV = false,
bool weldVertices = false,
bool optimizeMeshForRendering = false
)
{
return null;
}
public virtual void LockMesh
(
bool autoRigging,
bool async,
Mesh mesh = null,
bool generateTextureUV = false,
bool generateLightMapUV = false,
bool weldVertices = false,
bool optimizeMeshForRendering = false
)
{
m_isMeshLocked = true;
}
public void RememberLockedMeshMaterial()
{
var meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer != null)
{
m_lastLockedMeshMaterial = meshRenderer.sharedMaterial;
}
else
{
var skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
if (skinnedMeshRenderer != null)
m_lastLockedMeshMaterial = skinnedMeshRenderer.sharedMaterial;
}
}
public virtual void UnlockMesh()
{
m_isMeshLocked = false;
MarkNeedsCompute();
RestoreBoneTransforms();
MarkNeedsCompute();
}
#endregion // end: Mesh Utilities
//-------------------------------------------------------------------------
#region SDF
public bool DrawGenerateSdfGizmos = false; // editor only
public string GenerateSdfByEditorName = ""; // editor only
public Vector3 GenerateSdfCenter = Vector3.zero;
public Vector3 GenerateSdfDimension = Vector3.one;
public Vector3Int GenerateSdfTextureSize = new Vector3Int(64, 64, 64);
[NonSerialized] protected List<Sdf.EvalJobHandle> m_jobQueue = new List<Sdf.EvalJobHandle>();
[NonSerialized] protected List<Sdf.EvalJobHandle> m_jobCompleteQueue = new List<Sdf.EvalJobHandle>();
public void ValidateAssetNames()
{
if (GenerateColliderMeshAssetByEditorName.Equals(""))
GenerateColliderMeshAssetByEditorName = $"{gameObject.name} Collider Mesh {(uint)gameObject.GetInstanceID()}";
if (GenerateMeshAssetByEditorName.Equals(""))
GenerateMeshAssetByEditorName = $"{gameObject.name} Mesh {(uint) gameObject.GetInstanceID()}";
if (GenerateSdfByEditorName.Equals(""))
GenerateSdfByEditorName = $"{gameObject.name} SDF {(uint) gameObject.GetInstanceID()}";
}
public virtual void GenerateSdf
(
RenderTexture sdf,
Vector3 origin,
Vector3 dimension
)
{
if (sdf == null)
return;
ValidateResources();
SetUpResources();
ComputeManager.SetTexture(Const.SdfOutput, sdf);
ComputeManager.SetInts(Const.SdfOutputSize, new int[] { sdf.width, sdf.height, sdf.volumeDepth });
ComputeManager.SetVector(Const.SdfCenter, origin);
ComputeManager.SetVector(Const.SdfDimension, dimension);
ComputeManager.Dispatch
(
s_computeSdfGen,
Const.Kernel.GenerateSdf,
(sdf.width + ThreadGroupExtent - 1) / ThreadGroupExtent,
(sdf.height + ThreadGroupExtent - 1) / ThreadGroupExtent,
(sdf.volumeDepth + ThreadGroupExtent - 1) / ThreadGroupExtent
);
}
public virtual void GenerateSdf
(
Texture3D sdf,
Vector3 origin,
Vector3 dimension
)
{
if (sdf == null)
return;
var rt = new RenderTexture(sdf.width, sdf.height, 0, RenderTextureFormat.RFloat);
rt.dimension = TextureDimension.Tex3D;
rt.volumeDepth = sdf.depth;
rt.enableRandomWrite = true;
rt.Create();
GenerateSdf(rt, origin, dimension);
TextureUtil.RenderTextureToTexture3D(sdf, rt);
rt.Release();
}
internal void UpdateComputeData()
{
Assert.True(m_initialized, "Renderer not initialized. Either an automatic call to OnEnable() or a manual call to Init() needs to be done before any computation.");
if (m_needRescanBrushes)
{
RescanBrushesImmediate();
m_needRescanBrushes = false;
}
UpdateNeedsCompute();
UpdateBrushData();
UpdateAabbTreeData();
}
public static MudBrushBase LookupBrush(float hash)
{
return s_brushMap.TryGetValue(hash, out var brush) ? brush : null;
}
#endregion // end: SDf
//-------------------------------------------------------------------------
#region Optimization
public bool UseCutoffVolume = false;
public Transform CutoffVolumeCenter;
public Vector3 CutoffVolumeSize = Vector3.one;
/*
public Transform OptimizationRendererReference;
public Transform OptimizationCameraRefernce;
public bool EnableDistanceLod = false;
public float DistanceLodStartDistance = 10.0f;
public float DistanceLodFadeDistance = 5.0f;
public float DistanceLodFarVoxelDensity = 4.0f;
public bool EnableDistanceFade = false;
public float DistanceFadeFarStartDistance = 10.0f;
public float DistanceFadeFarFadeDistance = 5.0f;
public float DistanceFadeNearStartDistance = 1.0f;
public float DistanceFadeNearEndDistance = 1.0f;
*/
#endregion // end: Optimization
//-------------------------------------------------------------------------
#region Callbacks
protected virtual void OnSharedMaterialChanged(UnityEngine.Object material) { }
protected virtual void InitBeforeFirstRenderer()
{
Sdf.InitEvalMap();
}
protected virtual void CleanUpAfterLastRenderer()
{
DisposeGlobalResources();
Sdf.DisposeEvalMap();
}
private void Start()
{
if ((MeshGenerationLockOnStart || (MeshGenerationLockOnStartByEditor && MeshGenerationRenderableMeshMode == RenderableMeshMode.Procedural))
&& Application.isPlaying
&& !m_isMeshLocked)
{
if (MeshGenerationCreateCollider)
AddCollider(gameObject, false, null, MeshGenerationForceConvexCollider, MeshGenerationCreateRigidBody);
MarkNeedsCompute();
LockMesh(MeshGenerationAutoRigging, false);
}
}
protected virtual void OnEnable() { Init(); }
protected virtual void OnDisable() { ShutDown();}
public void Init()
{
if (m_initialized)
return;
Janitor.Init();
if (s_renderers.Count == 0)
{
InitBeforeFirstRenderer();
}
s_renderers.Add(this);
m_rendererIndex = s_renderers.Count - 1;
m_needRescanBrushes = true;
MarkNeedsCompute();
m_aSdfBrush = new NativeArray<SdfBrush>(MaxBrushes, Allocator.Persistent);
m_aSdfBrushMaterial = new NativeArray<SdfBrushMaterial>(MaxBrushes, Allocator.Persistent);
m_sdfBrushMaterialIndexMap = new Dictionary<int, int>();
m_aabbTree = new AabbTree<MudBrushBase>(AabbTreeFatBoundsRadius);
MarkNeedsCompute();
MudSharedMaterialBase.OnSharedMaterialChanged += OnSharedMaterialChanged;
m_previousTrackedVersion = m_currentTrackedVersion;
m_currentTrackedVersion = MudBun.Version;
if (m_firstTrackedVersion.Equals(""))
m_firstTrackedVersion = m_currentTrackedVersion;
if (m_previousTrackedVersion.Equals(""))
m_previousTrackedVersion = m_currentTrackedVersion;
m_initialized = true;
}
public void ShutDown()
{
if (!m_initialized)
return;
m_initialized = false;
// complete lingering jobs
for (int i = 0; i < m_jobCompleteQueue.Count; ++i)
{
m_jobCompleteQueue[i].Complete();
}
m_jobCompleteQueue.Clear();
ClearBrushes();
DisposeLocalResources();
if (m_aSdfBrush.IsCreated)
m_aSdfBrush.Dispose();
if (m_aSdfBrushMaterial.IsCreated)
m_aSdfBrushMaterial.Dispose();
m_sdfBrushMaterialIndexMap = null;
m_aabbTree.Dispose();
m_aabbTree = null;
MudSharedMaterialBase.OnSharedMaterialChanged -= OnSharedMaterialChanged;
s_renderers.Remove(this);
m_rendererIndex = -1;
if (s_renderers.Count == 0)
{
CleanUpAfterLastRenderer();
}
}
protected virtual void OnValidate()
{
SanitizeParameters();
m_numVoxelsHighWaterMark = 0;
m_numChunksHighWaterMark = 0;
if (!m_isMeshLocked)
MarkNeedsCompute();
}
internal void OnBrushDisabled(MudBrushBase brush)
{
RemoveBrush(brush);
}
// SDF evaluation interface would need brush & AABB tree data ready before Compute()
// don't update it again for Compute() if they are already updated
private bool m_brushDataDirty = false;
private bool m_aabbTreeDirty = false;
public void MarkNeedsCompute()
{
m_needsCompute = true;
m_brushDataDirty = true;
m_aabbTreeDirty = true;
}
private bool m_needsCompute = false;
private bool UpdateNeedsCompute()
{
if (MeshLocked)
{
bool needsCompute = false;
if (MeshGenerationRenderableMeshMode == RenderableMeshMode.Procedural)
needsCompute = m_needsCompute;
m_needsCompute = false;
return needsCompute;
}
switch (ComputeMode)
{
case ComputeModeEnum.Auto:
break;
case ComputeModeEnum.Manual:
case ComputeModeEnum.ManualNoRender:
return m_needsCompute;
case ComputeModeEnum.EveryFrame:
MarkNeedsCompute();
return true;
case ComputeModeEnum.TimeSliced:
switch (TimeSliceMode)
{
case TimeSliceModeEnum.ByFramesAutoOffset:
if (((Time.frameCount + m_rendererIndex) % TimeSliceFrames) != 0)
return false;
break;
case TimeSliceModeEnum.ByFramesManualOffset:
if (((Time.frameCount + TimeSliceFramesOffset) % TimeSliceFrames) != 0)
return false;
break;
case TimeSliceModeEnum.ByPeriodAutoOffset:
{
int q = (int) Mathf.Floor((Time.time + Mathf.Repeat(m_rendererIndex * Time.deltaTime, TimeSlicePeriod)) / TimeSlicePeriod);
float qT = q * TimeSlicePeriod;
if (qT <= m_lastUpdateTimeSliceTime)
return false;
m_lastUpdateTimeSliceTime = qT;
break;
}
case TimeSliceModeEnum.ByPeriodManualOffset:
{
int q = (int) Mathf.Floor((Time.time + Mathf.Repeat(TimeSliceTimeOffset, TimeSlicePeriod)) / TimeSlicePeriod);
float qT = q * TimeSlicePeriod;
if (qT <= m_lastUpdateTimeSliceTime)
return false;
m_lastUpdateTimeSliceTime = qT;
break;
}
}
break;
}
if (m_needsCompute)
return true;
Profiler.BeginSample("UpdateNeedsCompute");
// check need for rendering geometry type change
if (m_needsCompute)
{
var currRenderGeometryType = RenderGeometryType;
bool renderGeometryTypeChanged = (currRenderGeometryType != m_prevRenderGeometryType);
m_prevRenderGeometryType = currRenderGeometryType;
if (renderGeometryTypeChanged)
m_needsCompute = true;
}
// check dirty brushes
if (!m_needsCompute)
{
foreach (var b in m_aBrush)
{
if (!b.m_dirty && !b.transform.hasChanged)
continue;
MarkNeedsCompute();
break;
}
}
// check animation
if (!m_needsCompute)
{
if (TryGetComponent(out Animation animation)
&& animation.isPlaying)
{
MarkNeedsCompute();
}
}
// check animator
if (!m_needsCompute)
{
if (TryGetComponent(out Animator animator)
&& animator.layerCount > 0)
{
var animState = animator.GetCurrentAnimatorStateInfo(0);
if (animState.length > 0.0f && animState.speed > 0.0f && animState.speedMultiplier > 0.0f)
MarkNeedsCompute();
}
}
if (m_needsCompute)
{
Profiler.BeginSample("Clear Transform Change Flags");
foreach (var b in m_aBrush)
{
b.m_dirty = false;
b.transform.hasChanged = false;
}
Profiler.EndSample();
}
Profiler.EndSample();
return m_needsCompute;
}
public RenderMaterialModeEnum RenderMaterialMode = RenderMaterialModeEnum.Static;
public void MarkRenderMaterialDirty() { m_renderMaterialDirty = true; }
private bool m_renderMaterialDirty = true;
protected virtual bool IsEditorBusy() { return false; }
private int m_numVoxelsHighWaterMark = 0;
private int m_numChunksHighWaterMark = 0;
private void TryAutoAdjustBudgets()
{
if (!Application.isEditor)
return;
if (!ShowGpuMemoryUsage)
{
m_autoAdjustBudgetsToHighWaterMarks = false;
return;
}
if (!AutoAdjustBudgetsToHighWaterMarks)
{
m_autoAdjustBudgetsToHighWaterMarks = false;
return;
}
Profiler.BeginSample("TryAutoAdjustBudgets");
if (AutoAdjustBudgetsToHighWaterMarks && !m_autoAdjustBudgetsToHighWaterMarks)
{
m_numVoxelsHighWaterMark = 0;
m_numChunksHighWaterMark = 0;
}
m_autoAdjustBudgetsToHighWaterMarks = AutoAdjustBudgetsToHighWaterMarks;
m_numVoxelsHighWaterMark = Mathf.Max(NumVoxelsUsed, m_numVoxelsHighWaterMark);
m_numChunksHighWaterMark = Mathf.Max(NumChunksUsed, m_numChunksHighWaterMark);
int effectiveNumVoxelsHighWaterMark = m_numVoxelsHighWaterMark;
if (ShouldDoAutoSmoothing && EnableSmoothCorner)
{
effectiveNumVoxelsHighWaterMark = Mathf.Max(effectiveNumVoxelsHighWaterMark, NumVerticesGenerated / VoxelToVertexFactor);
}
MaxVoxelsK = Mathf.Max(1, (int) Mathf.Ceil(effectiveNumVoxelsHighWaterMark * (1.0f + AutoAdjustBudgetsToHighWaterMarksMarginPercent / 100.0f) / 1024.0f));
MaxChunks = Mathf.Max(16, (int) Mathf.Ceil(m_numChunksHighWaterMark * (1.0f + AutoAdjustBudgetsToHighWaterMarksMarginPercent / 100.0f)));
Profiler.EndSample();
}
protected virtual bool PreUpdateValidate() { return true; }
protected void LateUpdate()
{
UpdateComputeData();
if (m_jobQueue.Count > 0)
{
// complete lingering jobs
for (int i = 0; i < m_jobCompleteQueue.Count; ++i)
{
m_jobCompleteQueue[i].Complete();
}
m_jobCompleteQueue.Clear();
// schedule queued jobs
for (int i = 0; i < m_jobQueue.Count; ++i)
{
m_jobQueue[i].Schedule(true);
m_jobCompleteQueue.Add(m_jobQueue[i]);
}
JobHandle.ScheduleBatchedJobs();
m_jobQueue.Clear();
}
if (!PreUpdateValidate())
return;
if (m_isMeshLocked)
{
switch (MeshGenerationRenderableMeshMode)
{
case RenderableMeshMode.Procedural:
// keep on rendering in procedural mode
break;
default:
return;
}
}
TryCompute();
switch (ComputeMode)
{
case ComputeModeEnum.ManualNoRender:
break;
default:
Render();
break;
}
}
public void ForceCompute()
{
TryCompute(true);
}
public virtual void ReloadShaders()
{
DisposeGlobalResources();
DisposeLocalResources();
MarkNeedsCompute();
}
private void TryCompute(bool forceCompute = false)
{
if (IsEditorBusy())
return;
TryAutoAdjustBudgets();
SanitizeParameters();
if (!ValidateResources())
return;
if (!s_globalResourcesValid || !m_localResourcesValid)
return;
if (forceCompute || m_needsCompute)
{
switch (HardwareMode)
{
case HardwareModeEnum.Gpu:
ComputeGpu();
break;
/*
case HardwareModeEnum.Cpu:
ComputeCpu();
break;
*/
}
m_needsCompute = false;
}
}
private void SanitizeParameters()
{
Validate.Range(-1, VoxelNodeDepth, ref DrawVoxelNodesDepth);
Validate.NonNegative(ref RayTracedVoxelInternalPaddingDistance);
Validate.NonNegative(ref RayTracedVoxelSizeFadeDistance);
}
#if MUDBUN_FREE
private static readonly int s_watermarkWidth = 300;
private static readonly int s_watermariHeight = 100;
private static readonly string s_watermarkStr = "iVBORw0KGgoAAAANSUhEUgAAAgAAAACACAYAAAB9V9ELAAAgAElEQVR4AeydB4BdRfX/7/bNlmxJ77vpPYQESAKEGHo1IL1JEaQIinR/goDCX0VARVERQRBQqkGQGpqQEEkoAQIhCUlI73032/f//cy75+Xmsft2k2wEzZzdeTN37syZmXPnnnPmTLkp9fX1gQdPAU8BTwFPAU8BT4HdiwKpu1dzfWs9BTwFPAU8BTwFPAWggFcAfD/wFPAU8BTwFPAU2A0p4BWA3fCh+yZ7CngKeAp4CngKeAXA9wFPAU8BTwFPAU+B3ZACXgHYDR+6b7KngKeAp4CngKeAVwB8H/AU8BTwFPAU8BTYDSngFYDd8KH7JnsKeAp4CngKeAp4BcD3AU8BTwFPAU8BT4HdkAJeAdgNH7pvsqeAp4CngKeAp4BXAHwf8BTwFPAU8BTwFNgNKeAVgN3wofsmewp4CngKeAp4CngFwPcBTwFPAU8BTwFPgd2QAl4B2A0fum+yp4CngKeAp4CngFcAfB/wFPAU8BTwFPAU2A0p4BWA3fCh+yZ7CngKeAp4CngKeAXA9wFPAU8BTwFPAU+B3ZACXgHYDR+6b7KngKeAp4CngKeAVwB8H/AU8BTwFPAU8BTYDSngFYDd8KH7JnsKeAp4CngKeAp4BcD3AU8BTwFPAU8BT4HdkAJeAdgNH7pvsqeAp4CngKeAp4BXAHwf8BTwFPAU8BTwFNgNKeAVgN3wofsmewp4CngKeAp4CngFwPcBTwFPAU8BTwFPgd2QAl4B2A0fum+yp4CngKeAp4CngFcAfB/wFPAU8BTwFPAU2A0p4BWA3fCh+yZ7CngKeAp4CngKeAXA9wFPAU8BTwFPAU+B3ZACXgHYDR+6b7KngKeAp4CngKeAVwB8H/AU8BTwFPAU8BTYDSngFYDd8KH7JnsKeAp4CngKeAp4BcD3AU8BTwFPAU8BT4HdkAJeAdgNH7pvsqeAp4CngKeAp4BXAHwf8BTwFPAU8BTwFNgNKZCe2OaUlJTEKH/tKeAp4CnwlaJAfX39V6o+vjKeAv+NFPAWgP/Gp+br7CngKeAp4CngKbCTFPiCBWA78TXXXODV9e0krE/uKeAp4CngKeApsCspsCMKQFToE7Zr862+JvTNT4y3a+97CngKeAp4CngKeAr8hymwPQqACXjzmT7AcW1+tPoI/jq5qB9VBqLhaD4f9hT4KlDA+nliXXy/TaSIv/YU8BT4r6RAcxUAY4b4uDQ5hD6+uagSAJPE1SY4FAJTCgynZ6giiocvnQLWH6lIQ2Hrp9yzMGmjYa49eAp4CngK/FdQoDkKgDFD/KjQz9A1Dhw4FAHS4EzQ1yic6EwpgHHiSO+ZqIjg4UujgPVbKkDYlFmLt77KfcKmxO5I/wUn4Pt8jA7+11PAU+BLokBzFACqZkzRhH2m4sxlKWyKgDFOE/LVuoerCp1dk440piiA3zNEEcHDf5wCJuTxzbJliq7do1Im+OmzKLXR64b6L3EG0XBiXLTfR8OWzvueAp4CngK7hAJNKQDGAPFhjqRH8GeHLkc+CgCOeNIAxiQR/JVyFaFPGGeKAEoAEGV80XDsbuw3kYkmXkfTRnFEw9E0PuwpkNi/rY+j0BLGWT+jT9NfEf4oCPjRe4Str1k8vjnyJALpwYuPi+LQpQdPAU8BT4FdR4GmFABKhikZMzThn6s4HApA7sEHHdT14IMO7L3vqNH9dV0/eeqU2c8//+LcV157bbmuEf7lcltCR5nEgRdFAIAJGiNMmfzy5PoMqRipKnXkqH1JZ0AYBzO1ePON+RpTJY/FBe9MmR4Pc6MpSBH6elVpS92WoL6+LsjKygxqqmuDpUtWB6mqWOJ5SRs2bAz2GbVX0H9A36ZQ+/tfEQpEDr2y/o3gp4+bo6+a4KZ/muIatWgp2gH3rS/i40yBMN9wkcH6e9QS5vqoDrnZrr4Ksv8ViDyT/5Um+XZ4CnxlKZCSyGsSXkBjYjBCRvmt5BD6reXyBYX33fPHY8aOHTs8PT09qKurc8IS3lddWR28+OKL79zy85+9OXvOnDVKXyaHIoCPMhC1CjCaMkbYEPOLMlSYaNRxDyAfzvDAYI3J2r1mKwJeARD1/sdBfZ2+Q1+ifyP0zZplli3iuAfQr1AA6LdRR5z1XwUdRN8bhD848KMKAPhw5MXRV63v6j3aPZWABP4jkjQMuyl5GiaGj/UU2EEKJFMATOjCvBgZRYU/CkDhB+++e2mPkh5ta2pqYFhhFeoVliTWT211TbB548bqJ5/6x5Sr/+8HbyoBwn9z6FAGcDBTRlRRRmjIrA4wTmOg1MecKQKKigt/Y6rmG2PdLiXAKwCQ9H8bJGysX9G/TcGNW7duu+22PQYOHNj1888/X/ezn/1s5vz58+m71m8JmyJA/zXhbX3S3huUCPBzTR82oL+jPEStCeDA6fWJv1C63H3AKwC7z7P2Lf3yKQBTSgYmgG0UYyOk3Kcn/v3k7j26t62urpY5PFXmepLGBH9QhxIgpwFWTn5exumnnHLAmFGj+t/4k588M+nVVz5XMvCZQLcyYgi2joZAR5yljTJUG5kRZ/lN0NuIDMZKGAfAWAFTLmJX/ne3pIAEjfU3/ERFIGfWrFnf6tev31Ajzumnn775mmuuefQ3v/nNrDC93TIrE9fgAR/9MmpRYM0M1/Rl7tMX6ZcoEOQxoG9G8Vm89z0FPAU8BVqcAlHm0xhyY44mgLOOPvLIHqP2GTWQkT98FOGflpbuXCqDqpC3porV1ddrLl2Bnj17dvjjXb87+8c/uuEAFVQo56YR5OfJYV2ICnUT+vhWLkwU0yzp8+UK5MBTHLqi8Jp40iSacY35powYMxIm7MFTwChAf7B+nvHAAw+Migp/EuXm5ubdfvvtp/fq1au9Lul/WArotyjFtnbAfPoy/ZU09HPXV08++eQ+jz322KGyJuwVxtNPyW/KAX2Uevj+KSJ48BTwFNi1FEC4JgMYUZQ5upHNUUccNRDBzyjfDaQUTkmFbwk0+o8NYmJDbTIrVVCXUh9kZmemnnXG6Qd279693TfPPWeiboWZFIolTxydc9/Ms6YAINhhvG5Uddihh3SU8pG6bNmysnffe2+t4s0sy3QD9cVkGwVnYo1G+PBuTQHr49bPU0tKSjo2RJGMjIzMf/3rX2d26dLlbt03i5P1JyxOxCHEEeimrLrFsloPc9jBBx+8v+IpJzjkkEOmDh8+/C8K2tQX+a0uvFdMzyW+D2T14CngKeAp0CIUiArgZAiNOcLc0jp26tAWziQjv5QA+RL6dbW1bhFgTI7rN4yPcjCnG8hC8LWxY4c+/tdHTxYKRkc4m3d1Ql3XMFAEf1T4M1oibeHoUaNKH3rggQkff/jBFQ/c9+eL7/vTPRc+/dTE7096/rmzrrr88jFKw4gr0RIArvgIy1sBRA0PUCDWlSP+P//5z08bI03nzp3bv/XWWxN03wl2+Qh6+q05WytDf3V99u233z5Zwn+srp3wlx/sscceo371q18NUxAl1b1X8pv7PiqpB08BTwFPgZ2jwI4wnJRUTfrXyvyPlK/TFrm62rqgFgVAzs39K56tc3UoBi6MNiCH1UD1xWqw18g9+/7j8Ymn6RJzatSkakqACX9bnAUzzb/6yiv3fvzRRy49/PDDRnfq1LFAg39ty0sNsrOzUofvuWffK77//eOffPTRU0Kc5DEGjVIBs42OslxdqE+Dbiu/VjYP/8MUMCWA0XyNTPRz33///Q8aa++oUaMGX3HFFQN1n77VkDPhnz9t2rST9tprr6EN4RoyZEg3xSP844pBQ+l8nKeAp4CnwK6gQHMVgCiDrPts3ucrndCXgEfgowTUhkqAUwS0HdAJf8XphiwE2h6oIJYCFAH+4HhDhw7uec9v7z5GQRQAmCajKhQAhL6NqPBhsrkXnH/eMCkAx7dq1SrVWR2cNpGq6YeYTKceKVqPsN9++w599KG/nqQ8DSkApgSo3lJakrnYgmyh2bUg5WO7oLm1aQSp9Dd0uIahubj/29NFzO
private static Texture2D s_watermark;
private void OnGUI()
{
switch (Event.current.type)
{
case EventType.Repaint:
//if (MudBun.IsFreeVersion)
{
if (s_watermark == null)
{
s_watermark = new Texture2D(s_watermarkWidth, s_watermariHeight);
s_watermark.LoadImage(Convert.FromBase64String(s_watermarkStr));
}
// just let one renderer draw
var itRenderer = s_renderers.GetEnumerator();
if (!itRenderer.MoveNext() || itRenderer.Current != this)
return;
Graphics.DrawTexture(new Rect(0.0f, Screen.height - s_watermark.height, s_watermark.width, s_watermark.height), s_watermark);
}
break;
}
}
#endif
#endregion // end: Callbacks
//-------------------------------------------------------------------------
#region Resources
private bool ValidateResources()
{
Profiler.BeginSample("ValidateResources");
if (m_needRescanBrushes)
{
RescanBrushesImmediate();
m_needRescanBrushes = false;
}
if (!ValidateGlobalResources())
return false;
if (!ValidateLocalResources())
return false;
/*
foreach (var b in m_aBrush)
b.ValidateMaterial();
*/
Profiler.EndSample();
return true;
}
private static bool s_shaderConstantIdPopulated = false;
public static void ValidateShaderConstantId()
{
if (s_shaderConstantIdPopulated)
return;
Const.TriTable = Shader.PropertyToID("triTable");
Const.VertTable = Shader.PropertyToID("vertTable");
Const.TriTable2d = Shader.PropertyToID("triTable2d");
Const.Brushes = Shader.PropertyToID("aBrush");
Const.BrushMaterials = Shader.PropertyToID("aBrushMaterial");
Const.NumBrushes = Shader.PropertyToID("numBrushes");
Const.SurfaceShift = Shader.PropertyToID("surfaceShift");
Const.RenderMode = Shader.PropertyToID("renderMode");
Const.MeshingMode = Shader.PropertyToID("meshingMode");
Const.RayTracedVoxelMode = Shader.PropertyToID("rayTracedVoxelMode");
Const.RayTracedVoxelSizeMultiplier = Shader.PropertyToID("rayTracedVoxelSizeMultiplier");
Const.RayTracedVoxelSmoothCubeNormal = Shader.PropertyToID("rayTracedVoxelSmoothCubeNormal");
Const.RayTracedVoxelRadius = Shader.PropertyToID("rayTracedVoxelRadius");
Const.RayTracedVoxelPaddingMode = Shader.PropertyToID("rayTracedVoxelPaddingMode");
Const.RayTracedVoxelInternalPaddingDistance = Shader.PropertyToID("rayTracedVoxelInternalPaddingDistance");
Const.RayTracedVoxelSizeFadeDistance = Shader.PropertyToID("rayTracedVoxelSizeFadeDistance");
Const.NormalDifferentiationStep = Shader.PropertyToID("normalDifferentiationStep");
Const.NormalQuantization = Shader.PropertyToID("normalQuantization");
Const.Normal2dFadeDist = Shader.PropertyToID("normal2dFadeDist");
Const.Normal2dStrength = Shader.PropertyToID("normal2dStrength");
Const.EnableAutoSmooth = Shader.PropertyToID("enableAutoSmooth");
Const.AutoSmoothMaxAngle = Shader.PropertyToID("autoSmoothMaxAngle");
Const.AutoSmoothVertDataTable = Shader.PropertyToID("autoSmoothVertDataTable");
Const.AutoSmoothVertDataPoolSize = Shader.PropertyToID("autoSmoothVertDataPoolSize");
Const.EnableSmoothCorner = Shader.PropertyToID("enableSmoothCorner");
Const.SmoothCornerSubdivision = Shader.PropertyToID("smoothCornerSubdivision");
Const.SmoothCornerNormalBlur = Shader.PropertyToID("smoothCornerNormalBlur");
Const.SmoothCornerFade = Shader.PropertyToID("smoothCornerFade");
Const.InvertNormals = Shader.PropertyToID("invertNormals");
Const.SplatSize = Shader.PropertyToID("splatSize");
Const.SplatSizeJitter = Shader.PropertyToID("splatSizeJitter");
Const.SplatNormalShift = Shader.PropertyToID("splatNormalShift");
Const.SplatNormalShiftJitter = Shader.PropertyToID("splatNormalShiftJitter");
Const.SplatPositionJitter = Shader.PropertyToID("splatPositionJitter");
Const.SplatColorJitter = Shader.PropertyToID("splatColorJitter");
Const.SplatRotationJitter = Shader.PropertyToID("splatRotationJitter");
Const.SplatOrientationJitter = Shader.PropertyToID("splatOrientationJitter");
Const.SplatOriginalNormalBlend = Shader.PropertyToID("splatOriginalNormalBlend");
Const.SplatJitterNoisiness = Shader.PropertyToID("splatJitterNoisiness");
Const.SplatCameraFacing = Shader.PropertyToID("splatCameraFacing");
Const.SplatNormalsMatchCameraFacing = Shader.PropertyToID("splatNormalsMatchCameraFacing");
Const.SplatShadowsMatchCameraFacing = Shader.PropertyToID("splatShadowsMatchCameraFacing");
Const.SplatScreenSpaceFlattening = Shader.PropertyToID("splatScreenSpaceFlattening");
//Const.SplatSmoothNormalBlend = Shader.PropertyToID("splatSmoothNormalBlend");
Const.SurfaceNetsDualQuadsBlend = Shader.PropertyToID("surfaceNetsDualQuadsBlend");
Const.SurfaceNetsBinarySearchIterations = Shader.PropertyToID("surfaceNetsBinarySearchIterations");
Const.SurfaceNetsGradientDescentIterations = Shader.PropertyToID("surfaceNetsGradientDescentIterations");
Const.SurfaceNetsGradientDescentFactor = Shader.PropertyToID("surfaceNetsGradientDescentFactor");
Const.DualContouringDualQuadsBlend = Shader.PropertyToID("dualContouringDualQuadsBlend");
Const.DualContouringRelaxation = Shader.PropertyToID("dualContouringRelaxation");
Const.DualContouringSolverIterations = Shader.PropertyToID("dualContouringSolverIterations");
Const.DualContouringBinarySearchIterations = Shader.PropertyToID("dualContouringBinarySearchIterations");
Const.DualContouringGradientDescentIterations = Shader.PropertyToID("dualContouringGradientDescentIterations");
Const.DualContouringGradientDescentFactor = Shader.PropertyToID("dualContouringGradientDescentFactor");
Const.AabbTree = Shader.PropertyToID("aabbTree");
Const.AabbRoot = Shader.PropertyToID("aabbRoot");
Const.Enable2dMode = Shader.PropertyToID("enable2dMode");
Const.ForceAllBrushes = Shader.PropertyToID("forceAllBrushes");
Const.NumAllocations = Shader.PropertyToID("aNumAllocation");
Const.NodeHashTable = Shader.PropertyToID("nodeHashTable");
Const.NodeHashTableSize = Shader.PropertyToID("nodeHashTableSize");
Const.NodePool = Shader.PropertyToID("nodePool");
Const.NodePoolSize = Shader.PropertyToID("nodePoolSize");
Const.NumNodesAllocated = Shader.PropertyToID("aNumNodesAllocated");
Const.UseVoxelCache = Shader.PropertyToID("useVoxelCache");
Const.VoxelCacheIdTable = Shader.PropertyToID("voxelCacheIdTable");
Const.VoxelCache = Shader.PropertyToID("voxelCache");
Const.VoxelCacheSize = Shader.PropertyToID("voxelCacheSize");
Const.BrushMaskPool = Shader.PropertyToID("brushMaskPool");
Const.BrushMaskPoolSize = Shader.PropertyToID("brushMaskPoolSize");
Const.IndirectDispatchArgs = Shader.PropertyToID("indirectDispatchArgs");
Const.CurrentNodeDepth = Shader.PropertyToID("currentNodeDepth");
Const.CurrentNodeBranchingFactor = Shader.PropertyToID("currentNodeBranchingFactor");
Const.CurrentNodeSize = Shader.PropertyToID("currentNodeSize");
Const.VoxelSize = Shader.PropertyToID("voxelSize");
Const.VoxelTreeBranchingFactorsCompressed = Shader.PropertyToID("voxelTreeBranchingFactorsCompressed");
Const.VoxelNodeSizes = Shader.PropertyToID("voxelNodeSizes");
Const.MaxNodeDepth = Shader.PropertyToID("maxNodeDepth");
Const.ChunkVoxelDensity = Shader.PropertyToID("chunkVoxelDensity");
Const.GenPoints = Shader.PropertyToID("aGenPoint");
Const.MaxGenPoints = Shader.PropertyToID("maxGenPoints");
Const.IndirectDrawArgs = Shader.PropertyToID("indirectDrawArgs");
Const.MasterColor = Shader.PropertyToID("_Color");
Const.MasterEmission = Shader.PropertyToID("_Emission");
Const.MasterMetallic = Shader.PropertyToID("_Metallic");
Const.MasterSmoothness = Shader.PropertyToID("_Smoothness");
Const.ScaleSign = Shader.PropertyToID("scaleSign");
Const.LocalToWorld = Shader.PropertyToID("localToWorld");
Const.LocalToWorldIt = Shader.PropertyToID("localToWorldIt");
Const.LocalToWorldScale = Shader.PropertyToID("localToWorldScale");
Const.WorldToLocal = Shader.PropertyToID("worldToLocal");
Const.WorldToLocalIt = Shader.PropertyToID("worldToLocalIt");
Const.NoiseCache = Shader.PropertyToID("noiseCache");
Const.NoiseCacheDimension = Shader.PropertyToID("noiseCacheDimension");
Const.NoiseCacheDensity = Shader.PropertyToID("noiseCacheDensity");
Const.NoiseCachePeriod = Shader.PropertyToID("noiseCachePeriod");
Const.SdfOutput = Shader.PropertyToID("sdfOutput");
Const.SdfOutputSize = Shader.PropertyToID("sdfOutputSize");
Const.SdfCenter = Shader.PropertyToID("sdfCenter");
Const.SdfDimension = Shader.PropertyToID("sdfDimension");
Const.MaxRayMarchSteps = Shader.PropertyToID("maxRayMarchSteps");
Const.RayMarchHitDistance = Shader.PropertyToID("rayMarchHitDistance");
Const.RayMarchMaxRayDistance = Shader.PropertyToID("rayMarchMaxRayDistance");
Const.MeshGenerationAutoRiggingAlgorithm = Shader.PropertyToID("autoRiggingAlgorithm");
/*
Const.NumLightMarchSteps = Shader.PropertyToID("numLightMarchSteps");
Const.RayMarchStepSize = Shader.PropertyToID("rayMarchStepSize");
Const.RayMarchVolumeDensity = Shader.PropertyToID("rayMarchVolumeDensity");
Const.RayMarchLightPositionType = Shader.PropertyToID("rayMarchLightPositionType");
Const.RayMarchLightDirection = Shader.PropertyToID("rayMarchLightDirection");
Const.RayMarchAbsorption = Shader.PropertyToID("rayMarchAbsorption");
Const.RayMarchDarknesThreshold = Shader.PropertyToID("rayMarchDarknesThreshold");
Const.RayMarchTransmittanceCurve = Shader.PropertyToID("rayMarchTransmittanceCurve");
Const.RayMarchNoiseEdgeFade = Shader.PropertyToID("rayMarchNoiseEdgeFade");
Const.RayMarchNoiseThreshold = Shader.PropertyToID("rayMarchNoiseThreshold");
Const.RayMarchNoiseScrollSpeed = Shader.PropertyToID("rayMarchNoiseScrollSpeed");
Const.RayMarchNoiseBaseOctaveSize = Shader.PropertyToID("rayMarchNoiseBaseOctaveSize");
Const.RayMarchNoiseNumOctaves = Shader.PropertyToID("rayMarchNoiseNumOctaves");
Const.RayMarchNoiseOctaveOffsetFactor = Shader.PropertyToID("rayMarchNoiseOctaveOffsetFactor");
*/
Const.IsMeshRenderMaterial = Shader.PropertyToID("_IsMeshRenderMaterial");
Const.IsSplatRenderMaterial = Shader.PropertyToID("_IsSplatRenderMaterial");
Const.MaterialNeedsSdfProperties= Shader.PropertyToID("_MaterialNeedsSdfProperties");
Const.MaterialNeedsRayMarchingProperties = Shader.PropertyToID("_MaterialNeedsRayMarchingProperties");
s_shaderConstantIdPopulated = true;
}
private static void RegisterCommonMeshingConstants(ComputeShader shader)
{
ComputeManager.RegisterConstantId(shader, Const.RenderMode);
ComputeManager.RegisterConstantId(shader, Const.MeshingMode);
ComputeManager.RegisterConstantId(shader, Const.NormalDifferentiationStep);
ComputeManager.RegisterConstantId(shader, Const.NormalQuantization);
ComputeManager.RegisterConstantId(shader, Const.Normal2dFadeDist);
ComputeManager.RegisterConstantId(shader, Const.Normal2dStrength);
ComputeManager.RegisterConstantId(shader, Const.EnableAutoSmooth);
ComputeManager.RegisterConstantId(shader, Const.AutoSmoothMaxAngle);
ComputeManager.RegisterConstantId(shader, Const.AutoSmoothVertDataTable);
ComputeManager.RegisterConstantId(shader, Const.AutoSmoothVertDataPoolSize);
ComputeManager.RegisterConstantId(shader, Const.EnableSmoothCorner);
ComputeManager.RegisterConstantId(shader, Const.SmoothCornerSubdivision);
ComputeManager.RegisterConstantId(shader, Const.SmoothCornerNormalBlur);
ComputeManager.RegisterConstantId(shader, Const.SmoothCornerFade);
ComputeManager.RegisterConstantId(shader, Const.InvertNormals);
ComputeManager.RegisterConstantId(shader, Const.NodeHashTableSize);
ComputeManager.RegisterConstantId(shader, Const.NodePoolSize);
ComputeManager.RegisterConstantId(shader, Const.UseVoxelCache);
ComputeManager.RegisterConstantId(shader, Const.VoxelCacheSize);
ComputeManager.RegisterConstantId(shader, Const.BrushMaskPoolSize);
ComputeManager.RegisterConstantId(shader, Const.Brushes);
ComputeManager.RegisterConstantId(shader, Const.NumBrushes);
ComputeManager.RegisterConstantId(shader, Const.BrushMaterials);
ComputeManager.RegisterConstantId(shader, Const.SurfaceShift);
ComputeManager.RegisterConstantId(shader, Const.AabbTree);
ComputeManager.RegisterConstantId(shader, Const.AabbRoot);
ComputeManager.RegisterConstantId(shader, Const.Enable2dMode);
ComputeManager.RegisterConstantId(shader, Const.ForceAllBrushes);
ComputeManager.RegisterConstantId(shader, Const.NodeHashTable);
ComputeManager.RegisterConstantId(shader, Const.NodePool);
ComputeManager.RegisterConstantId(shader, Const.NumNodesAllocated);
ComputeManager.RegisterConstantId(shader, Const.NumAllocations);
ComputeManager.RegisterConstantId(shader, Const.VoxelCacheIdTable);
ComputeManager.RegisterConstantId(shader, Const.VoxelCache);
ComputeManager.RegisterConstantId(shader, Const.BrushMaskPool);
ComputeManager.RegisterConstantId(shader, Const.IndirectDispatchArgs);
ComputeManager.RegisterConstantId(shader, Const.GenPoints);
ComputeManager.RegisterConstantId(shader, Const.IndirectDrawArgs);
ComputeManager.RegisterConstantId(shader, Const.VoxelSize);
ComputeManager.RegisterConstantId(shader, Const.VoxelTreeBranchingFactorsCompressed);
ComputeManager.RegisterConstantId(shader, Const.VoxelNodeSizes);
ComputeManager.RegisterConstantId(shader, Const.MaxNodeDepth);
ComputeManager.RegisterConstantId(shader, Const.ChunkVoxelDensity);
ComputeManager.RegisterConstantId(shader, Const.NoiseCache);
ComputeManager.RegisterConstantId(shader, Const.NoiseCacheDimension);
ComputeManager.RegisterConstantId(shader, Const.NoiseCacheDensity);
ComputeManager.RegisterConstantId(shader, Const.CurrentNodeDepth);
ComputeManager.RegisterConstantId(shader, Const.CurrentNodeBranchingFactor);
ComputeManager.RegisterConstantId(shader, Const.CurrentNodeSize);
}
public static bool ValidateComputeShaders()
{
if (s_computeVoxelGen != null
&& s_computeMarchingCubes != null
&& s_computeDualMeshing != null
&& s_computeNoiseCache != null
&& s_computeMeshLock != null)
return true;
ComputeManager.Reset();
ValidateShaderConstantId();
// voxel gen
{
s_computeVoxelGen = ResourcesUtil.VoxelGen;
if (s_computeVoxelGen == null)
return false;
ComputeManager.RegisterShader(s_computeVoxelGen);
Const.Kernel.ClearVoxelHashTable =
ComputeManager.RegisterKernel(s_computeVoxelGen, "clear_voxel_hash_table");
Const.Kernel.ClearAutoSmoothVertDataTable =
ComputeManager.RegisterKernel(s_computeVoxelGen, "clear_auto_smooth_vert_data_table");
Const.Kernel.ClearVoxelCache =
ComputeManager.RegisterKernel(s_computeVoxelGen, "clear_voxel_cache");
Const.Kernel.RegisterTopNodes =
ComputeManager.RegisterKernel(s_computeVoxelGen, "register_top_nodes");
Const.Kernel.UpdateBranchingIndirectDispatchArgs =
ComputeManager.RegisterKernel(s_computeVoxelGen, "update_branching_indirect_dispatch_args");
Const.Kernel.AllocateChildNodes =
ComputeManager.RegisterKernel(s_computeVoxelGen, "allocate_child_nodes");
Const.Kernel.UpdateVoxelIndirectDispatchArgs =
ComputeManager.RegisterKernel(s_computeVoxelGen, "update_voxel_indirect_dispatch_args");
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.RenderMode);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.RayTracedVoxelMode);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.RayTracedVoxelPaddingMode);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.RayTracedVoxelInternalPaddingDistance);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.RayTracedVoxelSizeFadeDistance);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NumBrushes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodeHashTableSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodePoolSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.BrushMaskPoolSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.Brushes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.BrushMaterials);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.SurfaceShift);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AabbTree);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AabbRoot);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.Enable2dMode);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.ForceAllBrushes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodeHashTable);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodePool);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NumNodesAllocated);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NumAllocations);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.BrushMaskPool);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.IndirectDispatchArgs);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.GenPoints);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.IndirectDrawArgs);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.VoxelSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.VoxelTreeBranchingFactorsCompressed);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.VoxelNodeSizes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.MaxNodeDepth);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.ChunkVoxelDensity);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NoiseCache);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NoiseCacheDimension);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NoiseCacheDensity);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.CurrentNodeDepth);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.CurrentNodeBranchingFactor);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.CurrentNodeSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NormalDifferentiationStep);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.EnableAutoSmooth);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AutoSmoothMaxAngle);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AutoSmoothVertDataTable);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AutoSmoothVertDataPoolSize);
} // end: voxel gen
// marching cubes
{
s_computeMarchingCubes = ResourcesUtil.MarchingCubes;
if (s_computeMarchingCubes == null)
return false;
ComputeManager.RegisterShader(s_computeMarchingCubes);
Const.Kernel.GenerateFlatMarchingCubesMesh =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "generate_flat_marching_cubes_mesh");
Const.Kernel.GenerateSmoothMarchingCubesMesh =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "generate_smooth_marching_cubes_mesh");
Const.Kernel.GenerateMarchingCubesSplats =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "generate_marching_splats");
Const.Kernel.GenerateFlatMarchingCubesMesh2d =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "generate_flat_marching_cubes_mesh_2d");
Const.Kernel.GenerateSmoothMarchingCubesMesh2d =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "generate_smooth_marching_cubes_mesh_2d");
Const.Kernel.GenerateMarchingCubesSplats2d =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "generate_marching_splats_2d");
Const.Kernel.UpdateMarchingCubesAutoSmoothIndirectDispatchArgs =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "update_marching_cubes_auto_smooth_indirect_dispatch_args");
Const.Kernel.MarchingCubesUpdateAutoSmooth =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "marching_cubes_update_auto_smooth");
Const.Kernel.MarchingCubesComputeAutoSmooth =
ComputeManager.RegisterKernel(s_computeMarchingCubes, "marching_cubes_compute_auto_smooth");
RegisterCommonMeshingConstants(s_computeMarchingCubes);
ComputeManager.RegisterConstantId(s_computeMarchingCubes, Const.TriTable);
ComputeManager.RegisterConstantId(s_computeMarchingCubes, Const.VertTable);
ComputeManager.RegisterConstantId(s_computeMarchingCubes, Const.TriTable2d);
}
// dual meshing
{
s_computeDualMeshing = ResourcesUtil.DualMeshing;
if (s_computeDualMeshing == null)
return false;
ComputeManager.RegisterShader(s_computeDualMeshing);
Const.Kernel.GenerateDualQuads =
ComputeManager.RegisterKernel(s_computeDualMeshing, "generate_dual_quads");
Const.Kernel.GenerateDualQuads2d =
ComputeManager.RegisterKernel(s_computeDualMeshing, "generate_dual_quads_2d");
Const.Kernel.UpdateDualMeshingIndirectDispatchArgs =
ComputeManager.RegisterKernel(s_computeDualMeshing, "update_dual_meshing_indirect_dispatch_args");
Const.Kernel.DualMeshingFlatMeshNormal =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_flat_mesh_normal");
Const.Kernel.DualMeshingSmoothMeshNormal =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_smooth_mesh_normal");
Const.Kernel.DualMeshingFlatMeshNormal2d =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_flat_mesh_normal_2d");
Const.Kernel.DualMeshingSmoothMeshNormal2d =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_smooth_mesh_normal_2d");
Const.Kernel.DualMeshingUpdateAutoSmooth =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_update_auto_smooth");
Const.Kernel.DualMeshingComputeAutoSmooth =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_compute_auto_smooth");
Const.Kernel.DualMeshingUpdateSmoothCornerIndirectDispatchArgs =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_udpate_auto_smooth_SmoothCorner_indirect_dispatch_args");
Const.Kernel.DualMeshingSmoothCorner =
ComputeManager.RegisterKernel(s_computeDualMeshing, "dual_meshing_auto_smooth_smooth_corner");
Const.Kernel.UpdateDualMeshingSplatsIndirectArgs =
ComputeManager.RegisterKernel(s_computeDualMeshing, "update_dual_meshing_splats_indirect_args");
Const.Kernel.ConvertDualMeshingSplats =
ComputeManager.RegisterKernel(s_computeDualMeshing, "convert_dual_meshing_splats");
RegisterCommonMeshingConstants(s_computeDualMeshing);
}
// surface nets
{
s_computeSurfaceNets = ResourcesUtil.SurfaceNets;
if (s_computeSurfaceNets == null)
return false;
ComputeManager.RegisterShader(s_computeSurfaceNets);
Const.Kernel.SurfaceNetsMovePoint =
ComputeManager.RegisterKernel(s_computeSurfaceNets, "surface_nets_move_point");
Const.Kernel.SurfaceNetsMovePoint2d =
ComputeManager.RegisterKernel(s_computeSurfaceNets, "surface_nets_move_point_2d");
RegisterCommonMeshingConstants(s_computeSurfaceNets);
ComputeManager.RegisterConstantId(s_computeSurfaceNets, Const.SurfaceNetsDualQuadsBlend);
ComputeManager.RegisterConstantId(s_computeSurfaceNets, Const.SurfaceNetsBinarySearchIterations);
ComputeManager.RegisterConstantId(s_computeSurfaceNets, Const.SurfaceNetsGradientDescentIterations);
ComputeManager.RegisterConstantId(s_computeSurfaceNets, Const.SurfaceNetsGradientDescentFactor);
}
// dual contouring
{
s_computeDualContouring = ResourcesUtil.DualContouring;
if (s_computeDualContouring == null)
return false;
ComputeManager.RegisterShader(s_computeDualContouring);
Const.Kernel.DualContouringMovePoint =
ComputeManager.RegisterKernel(s_computeDualContouring, "dual_contouring_move_point");
Const.Kernel.DualContouringMovePoint2d =
ComputeManager.RegisterKernel(s_computeDualContouring, "dual_contouring_move_point_2d");
RegisterCommonMeshingConstants(s_computeDualContouring);
ComputeManager.RegisterConstantId(s_computeDualContouring, Const.DualContouringDualQuadsBlend);
ComputeManager.RegisterConstantId(s_computeDualContouring, Const.DualContouringRelaxation);
ComputeManager.RegisterConstantId(s_computeDualContouring, Const.DualContouringSolverIterations);
ComputeManager.RegisterConstantId(s_computeDualContouring, Const.DualContouringBinarySearchIterations);
ComputeManager.RegisterConstantId(s_computeDualContouring, Const.DualContouringGradientDescentIterations);
ComputeManager.RegisterConstantId(s_computeDualContouring, Const.DualContouringGradientDescentFactor);
}
// ray-traced voxels
{
s_computeRayTracedVoxels = ResourcesUtil.RayTracedVoxels;
if (s_computeRayTracedVoxels == null)
return false;
ComputeManager.RegisterShader(s_computeRayTracedVoxels);
Const.Kernel.UpdateRayTracedVoxelIndirectDispatchArgs =
ComputeManager.RegisterKernel(s_computeRayTracedVoxels, "update_ray_traced_voxel_indirect_dispatch_args");
Const.Kernel.ComputeRayTracedVoxelGenPoints =
ComputeManager.RegisterKernel(s_computeRayTracedVoxels, "compute_ray_traced_voxel_gen_points");
Const.Kernel.ComputeRayTracedVoxelGenPointsWithNormals =
ComputeManager.RegisterKernel(s_computeRayTracedVoxels, "compute_ray_traced_voxel_gen_points_with_normals");
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RenderMode);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RayTracedVoxelMode);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RayTracedVoxelSizeMultiplier);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RayTracedVoxelSmoothCubeNormal);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RayTracedVoxelRadius);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RayTracedVoxelPaddingMode);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RayTracedVoxelInternalPaddingDistance);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.RayTracedVoxelSizeFadeDistance);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NumBrushes);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NodeHashTableSize);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NodePoolSize);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.BrushMaskPoolSize);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.Brushes);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.BrushMaterials);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.SurfaceShift);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.AabbTree);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.AabbRoot);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.ForceAllBrushes);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NodeHashTable);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NodePool);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NumNodesAllocated);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NumAllocations);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.BrushMaskPool);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.IndirectDispatchArgs);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.GenPoints);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.IndirectDrawArgs);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.VoxelSize);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.VoxelTreeBranchingFactorsCompressed);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.VoxelNodeSizes);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.MaxNodeDepth);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.ChunkVoxelDensity);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NoiseCache);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NoiseCacheDimension);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NoiseCacheDensity);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.CurrentNodeDepth);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.CurrentNodeBranchingFactor);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.CurrentNodeSize);
ComputeManager.RegisterConstantId(s_computeRayTracedVoxels, Const.NormalDifferentiationStep);
}
// noise cache
{
s_computeNoiseCache = ResourcesUtil.NoiseCache;
if (s_computeNoiseCache == null)
return false;
// switched to using based noise texture
ComputeManager.RegisterShader(s_computeNoiseCache);
Const.Kernel.GenerateNoiseCache =
ComputeManager.RegisterKernel(s_computeNoiseCache, "generate_noise_cache");
ComputeManager.RegisterConstantId(s_computeNoiseCache, Const.NoiseCache);
ComputeManager.RegisterConstantId(s_computeNoiseCache, Const.NoiseCacheDimension);
ComputeManager.RegisterConstantId(s_computeNoiseCache, Const.NoiseCacheDensity);
ComputeManager.RegisterConstantId(s_computeNoiseCache, Const.NoiseCachePeriod);
} // end: noise cache
// mesh lock
{
s_computeMeshLock = ResourcesUtil.MeshLock;
if (s_computeMeshLock == null)
return false;
ComputeManager.RegisterShader(s_computeMeshLock);
Const.Kernel.RigBones =
ComputeManager.RegisterKernel(s_computeMeshLock, "rig_bones");
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NumBrushes);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.BrushMaskPoolSize);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.Brushes);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.BrushMaterials);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.AabbTree);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.AabbRoot);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NodeHashTable);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NodePool);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NumNodesAllocated);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NumAllocations);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.VoxelCacheIdTable);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.VoxelCache);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.BrushMaskPool);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.IndirectDispatchArgs);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.GenPoints);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.MaxGenPoints);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.IndirectDrawArgs);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.VoxelSize);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.MaxNodeDepth);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.ChunkVoxelDensity);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NoiseCache);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NoiseCacheDimension);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.NoiseCacheDensity);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.CurrentNodeDepth);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.CurrentNodeBranchingFactor);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.CurrentNodeSize);
ComputeManager.RegisterConstantId(s_computeMeshLock, Const.MeshGenerationAutoRiggingAlgorithm);
} // end: mesh lock
// SDF gen
{
s_computeSdfGen = ResourcesUtil.SdfGen;
if (s_computeSdfGen == null)
return false;
ComputeManager.RegisterShader(s_computeSdfGen);
Const.Kernel.GenerateSdf =
ComputeManager.RegisterKernel(s_computeSdfGen, "generate_sdf");
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.SdfOutput);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.SdfOutputSize);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.SdfCenter);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.SdfDimension);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.Brushes);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.NumBrushes);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.BrushMaskPoolSize);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.Brushes);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.BrushMaterials);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.AabbTree);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.AabbRoot);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.NoiseCache);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.NoiseCacheDimension);
ComputeManager.RegisterConstantId(s_computeSdfGen, Const.NoiseCacheDensity);
} // end: SDF gen
ComputeManager.ActivateAllShaders();
// generate noise cache
{
if (s_noiseCache != null)
{
s_noiseCache.Release();
s_noiseCache = null;
}
s_noiseCache = new RenderTexture(NoiseCacheDimensionInts[0], NoiseCacheDimensionInts[1], 0, RenderTextureFormat.RFloat);
s_noiseCache.dimension = TextureDimension.Tex3D;
s_noiseCache.volumeDepth = NoiseCacheDimensionInts[2];
s_noiseCache.enableRandomWrite = true;
s_noiseCache.Create();
ComputeManager.SetTexture(Const.NoiseCache, s_noiseCache);
//ComputeManager.SetTexture(Const.NoiseCache, ResourcesUtil.NoiseTexture);
ComputeManager.SetInts(Const.NoiseCacheDimension, NoiseCacheDimensionInts);
ComputeManager.SetFloat(Const.NoiseCacheDensity, NoiseCacheDensity);
ComputeManager.SetFloats(Const.NoiseCachePeriod, NoiseCachePeriod);
ComputeManager.Dispatch
(
s_computeNoiseCache,
Const.Kernel.GenerateNoiseCache,
(s_noiseCache.width + ThreadGroupExtent - 1) / ThreadGroupExtent,
(s_noiseCache.height + ThreadGroupExtent - 1) / ThreadGroupExtent,
(s_noiseCache.volumeDepth + ThreadGroupExtent - 1) / ThreadGroupExtent
);
ComputeManager.Deactivate(s_computeNoiseCache);
} // end: generate noise cache
return true;
}
private bool ValidateGlobalResources()
{
Profiler.BeginSample("ValidateGlobalResources");
if (!ValidateComputeShaders())
return false;
if (s_triTableBuffer == null)
{
s_triTableBuffer = new ComputeBuffer(16 * 256, sizeof(int));
s_triTableBuffer.SetData(MarchingCubes.TriTable);
ComputeManager.SetBuffer(Const.TriTable, s_triTableBuffer);
m_needsCompute = true;
}
if (s_vertTableBuffer == null)
{
s_vertTableBuffer = new ComputeBuffer(2 * 12, sizeof(int));
s_vertTableBuffer.SetData(MarchingCubes.VertTable);
ComputeManager.SetBuffer(Const.VertTable, s_vertTableBuffer);
m_needsCompute = true;
}
if (s_triTable2dBuffer == null)
{
s_triTable2dBuffer = new ComputeBuffer(12 * 16, sizeof(int));
s_triTable2dBuffer.SetData(MarchingCubes.TriTable2d);
ComputeManager.SetBuffer(Const.TriTable2d, s_triTable2dBuffer);
m_needsCompute = true;
}
if (AllowSharedRWBuffers)
{
if (s_brushesBuffer == null)
{
s_brushesBuffer = new ComputeBuffer(MaxBrushes, SdfBrush.Stride);
m_needsCompute = true;
}
if (s_brushMaterialBuffer == null)
{
s_brushMaterialBuffer = new ComputeBuffer(MaxBrushes, SdfBrushMaterial.Stride);
m_needsCompute = true;
}
}
if (s_dummyBuffer == null)
{
s_dummyBuffer = new ComputeBuffer(4, sizeof(int));
}
Profiler.EndSample();
s_globalResourcesValid = true;
return true;
}
protected virtual bool ValidateLocalResources()
{
Profiler.BeginSample("ValidateLocalResources (Renderer Base)");
if (AllowSharedRWBuffers)
{
if (m_brushesBuffer != null
&& m_brushesBuffer != s_brushesBuffer)
{
//m_brushesBuffer.Release();
Janitor.Dispose(m_brushesBuffer);
m_needsCompute = true;
}
if (m_brushMaterialBuffer != null
&& m_brushMaterialBuffer != s_brushMaterialBuffer)
{
//m_brushMaterialBuffer.Release();
Janitor.Dispose(m_brushMaterialBuffer);
m_needsCompute = true;
}
if (m_aabbTreeBuffer != null
&& m_aabbTreeBuffer != s_aabbTreeBuffer)
{
//m_aabbTreeBuffer.Release();
Janitor.Dispose(m_aabbTreeBuffer);
m_needsCompute = true;
}
m_brushesBuffer = s_brushesBuffer;
m_brushMaterialBuffer = s_brushMaterialBuffer;
m_aabbTreeBuffer = s_aabbTreeBuffer;
}
else
{
if (m_brushesBuffer == null
|| m_brushesBuffer == s_brushesBuffer)
{
m_brushesBuffer = new ComputeBuffer(MaxBrushes, SdfBrush.Stride);
m_needsCompute = true;
}
if (m_brushMaterialBuffer == null
|| m_brushMaterialBuffer == s_brushMaterialBuffer)
{
m_brushMaterialBuffer = new ComputeBuffer(MaxBrushes, SdfBrushMaterial.Stride);
m_needsCompute = true;
}
if (m_aabbTreeBuffer == s_aabbTreeBuffer)
{
m_aabbTreeBuffer = null;
}
}
if (m_nodeHashTableBuffer == null
|| m_nodeHashTableBuffer.count != NodeHashTableSize)
{
if (m_nodeHashTableBuffer != null)
{
//m_nodeHashTableBuffer.Release();
Janitor.Dispose(m_nodeHashTableBuffer);
}
m_nodeHashTableBuffer = new ComputeBuffer(NodeHashTableSize, VoxelHashEntry.Stride);
m_needsCompute = true;
}
if (m_nodePoolBuffer == null
|| m_nodePoolBuffer.count != MaxVoxels)
{
if (m_nodePoolBuffer != null)
{
//m_nodePoolBuffer.Release();
Janitor.Dispose(m_nodePoolBuffer);
}
m_nodePoolBuffer = new ComputeBuffer(MaxVoxels, VoxelNode.Stride);
m_needsCompute = true;
}
int voxelCacheSize = MaxVoxels * 2;
if (UseVoxelCache)
{
if (m_voxelCacheIdTableBuffer == null
|| m_voxelCacheIdTableBuffer.count != voxelCacheSize)
{
if (m_voxelCacheIdTableBuffer != null)
{
//m_voxelCacheIdTableBuffer.Release();
//m_voxelCacheBuffer.Release();
Janitor.Dispose(m_voxelCacheIdTableBuffer);
Janitor.Dispose(m_voxelCacheBuffer);
}
m_voxelCacheIdTableBuffer = new ComputeBuffer(voxelCacheSize, sizeof(int));
m_voxelCacheBuffer = new ComputeBuffer(voxelCacheSize, 4 * sizeof(float));
m_needsCompute = true;
}
}
else if (m_voxelCacheBuffer != null)
{
//m_voxelCacheIdTableBuffer.Release();
//m_voxelCacheBuffer.Release();
Janitor.Dispose(m_voxelCacheIdTableBuffer);
Janitor.Dispose(m_voxelCacheBuffer);
m_voxelCacheIdTableBuffer = null;
m_voxelCacheBuffer = null;
}
if (m_brushMaskPoolBuffer == null
|| m_brushMaskPoolBuffer.count != MaxBrushMasks * MaxBrushMaskInts)
{
if (m_brushMaskPoolBuffer != null)
{
//m_brushMaskPoolBuffer.Release();
Janitor.Dispose(m_brushMaskPoolBuffer);
}
m_brushMaskPoolBuffer = new ComputeBuffer(MaxBrushMasks * MaxBrushMaskInts, sizeof(int));
m_needsCompute = true;
}
int maxGenPoints = MaxGenPoints;
if (m_genPointsBufferDefault == null
|| m_genPointsBufferDefault.count != maxGenPoints)
{
if (m_genPointsBufferDefault != null)
{
//m_numNodesAllocatedBuffer.Release();
//m_numAllocationsBuffer.Release();
//m_indirectDispatchArgsBuffer.Release();
//m_genPointsBufferDefault.Release();
//m_indirectDrawArgsBufferDefault.Release();
Janitor.Dispose(m_numNodesAllocatedBuffer);
Janitor.Dispose(m_numAllocationsBuffer);
Janitor.Dispose(m_indirectDispatchArgsBuffer);
Janitor.Dispose(m_genPointsBufferDefault);
Janitor.Dispose(m_indirectDrawArgsBufferDefault);
}
m_numNodesAllocatedBuffer = new ComputeBuffer(VoxelNodeDepth + 2, sizeof(int));
m_numAllocationsBuffer = new ComputeBuffer(4, sizeof(int));
m_indirectDispatchArgsBuffer = new ComputeBuffer(3, sizeof(int), ComputeBufferType.IndirectArguments);
m_genPointsBufferDefault = new ComputeBuffer(maxGenPoints, GenPoint.Stride);
m_indirectDrawArgsBufferDefault = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments);
m_needsCompute = true;
}
if (ShouldDoAutoSmoothing)
{
if (m_autoSmoothVertDataTableBuffer != null
&& m_autoSmoothVertDataTableBuffer.count != AutoSmoothVertDataTableSize)
{
//m_autoSmoothVertDataTableBuffer.Release();
Janitor.Dispose(m_autoSmoothVertDataTableBuffer);
m_autoSmoothVertDataTableBuffer = null;
}
if (m_autoSmoothVertDataTableBuffer == null)
{
m_autoSmoothVertDataTableBuffer = new ComputeBuffer(AutoSmoothVertDataTableSize, AutoSmoothVertData.Stride);
}
}
else
{
if (m_autoSmoothVertDataTableBuffer != null)
{
//m_autoSmoothVertDataTableBuffer.Release();
Janitor.Dispose(m_autoSmoothVertDataTableBuffer);
m_autoSmoothVertDataTableBuffer = null;
}
}
if (m_usedSharedMaterial != SharedMaterial)
{
m_usedSharedMaterial = SharedMaterial;
m_needsCompute = true;
}
Profiler.EndSample();
m_localResourcesValid = true;
return true;
}
protected static void DisposeGlobalResources()
{
s_globalResourcesValid = false;
s_computeVoxelGen = null;
if (s_triTableBuffer != null)
{
//s_triTableBuffer.Release();
Janitor.Dispose(s_triTableBuffer);
s_triTableBuffer = null;
}
if (s_vertTableBuffer != null)
{
//s_vertTableBuffer.Release();
Janitor.Dispose(s_vertTableBuffer);
s_vertTableBuffer = null;
}
if (s_triTable2dBuffer != null)
{
//s_triTable2dBuffer.Release();
Janitor.Dispose(s_triTable2dBuffer);
s_triTable2dBuffer = null;
}
if (s_brushesBuffer != null)
{
//s_brushesBuffer.Release();
Janitor.Dispose(s_brushesBuffer);
s_brushesBuffer = null;
}
if (s_brushMaterialBuffer != null)
{
//s_brushMaterialBuffer.Release();
Janitor.Dispose(s_brushMaterialBuffer);
s_brushMaterialBuffer = null;
}
if (s_aabbTreeBuffer != null)
{
//s_aabbTreeBuffer.Release();
Janitor.Dispose(s_aabbTreeBuffer);
s_aabbTreeBuffer = null;
}
if (s_dummyBuffer != null)
{
//s_dummyBuffer.Release();
Janitor.Dispose(s_dummyBuffer);
s_dummyBuffer = null;
}
if (s_numAllocatoinsBufferInitData.IsCreated)
s_numAllocatoinsBufferInitData.Dispose();
if (s_unitIndirectDispatchArgsInitData.IsCreated)
s_unitIndirectDispatchArgsInitData.Dispose();
}
protected void DisposeLocalResources()
{
m_localResourcesValid = false;
if (m_brushesBuffer != null
&& m_brushesBuffer != s_brushesBuffer)
{
//m_brushesBuffer.Release();
Janitor.Dispose(m_brushesBuffer);
m_brushesBuffer = null;
}
if (m_brushMaterialBuffer != null
&& m_brushMaterialBuffer != s_brushMaterialBuffer)
{
//m_brushMaterialBuffer.Release();
Janitor.Dispose(m_brushMaterialBuffer);
m_brushMaterialBuffer = null;
}
if (m_aabbTreeBuffer != null
&& m_aabbTreeBuffer != s_aabbTreeBuffer)
{
//m_aabbTreeBuffer.Release();
Janitor.Dispose(m_aabbTreeBuffer);
m_aabbTreeBuffer = null;
}
if (m_nodeHashTableBuffer != null)
{
//m_nodeHashTableBuffer.Release();
Janitor.Dispose(m_nodeHashTableBuffer);
m_nodeHashTableBuffer = null;
}
if (m_nodePoolBuffer != null)
{
//m_nodePoolBuffer.Release();
Janitor.Dispose(m_nodePoolBuffer);
m_nodePoolBuffer = null;
}
if (m_voxelCacheIdTableBuffer != null)
{
//m_voxelCacheIdTableBuffer.Release();
//m_voxelCacheBuffer.Release();
Janitor.Dispose(m_voxelCacheIdTableBuffer);
Janitor.Dispose(m_voxelCacheBuffer);
m_voxelCacheIdTableBuffer = null;
m_voxelCacheBuffer = null;
}
if (m_brushMaskPoolBuffer != null)
{
//m_brushMaskPoolBuffer.Release();
Janitor.Dispose(m_brushMaskPoolBuffer);
m_brushMaskPoolBuffer = null;
}
if (m_genPointsBufferDefault != null)
{
//m_numNodesAllocatedBuffer.Release();
//m_numAllocationsBuffer.Release();
//m_indirectDispatchArgsBuffer.Release();
//m_genPointsBufferDefault.Release();
//m_indirectDrawArgsBufferDefault.Release();
Janitor.Dispose(m_numNodesAllocatedBuffer);
Janitor.Dispose(m_numAllocationsBuffer);
Janitor.Dispose(m_indirectDispatchArgsBuffer);
Janitor.Dispose(m_genPointsBufferDefault);
Janitor.Dispose(m_indirectDrawArgsBufferDefault);
m_numNodesAllocatedBuffer = null;
m_numAllocationsBuffer = null;
m_indirectDispatchArgsBuffer = null;
m_genPointsBufferDefault = null;
m_indirectDrawArgsBufferDefault = null;
}
if (m_autoSmoothVertDataTableBuffer != null)
{
//m_autoSmoothVertDataTableBuffer.Release();
Janitor.Dispose(m_autoSmoothVertDataTableBuffer);
m_autoSmoothVertDataTableBuffer = null;
}
m_materialCloned = null;
m_materialUsed = null;
if (m_pendingMeshTable != null)
{
foreach (var pair in m_pendingMeshTable)
pair.Value.Dispose();
m_pendingMeshTable.Clear();
}
if (m_indirectDrawArgsInitData.IsCreated)
m_indirectDrawArgsInitData.Dispose();
}
#endregion // end: Resources
//-------------------------------------------------------------------------
#region Brushes
private static readonly string MaxBrushWarningMessage =
$"Maximum of {MaxBrushes} compute brushes per renderer exceeded (some brushes can count as more than one compute brushes).\n"
+ "You may try bumping the maximum compute brushes by following the instructions in comments above where MudRendererBase.MaxBrushes is declared, but beware of performance.";
public void AddBrush(MudBrushBase brush)
{
if (brush.m_renderer != null)
brush.m_renderer.RemoveBrush(brush);
brush.m_renderer = this;
ValidateAabbTree();
brush.UpdateProxies(m_aabbTree, brush.BoundsRs);
m_aabbTreeDirty = true;
m_aBrush.Add(brush);
m_aBrushToProcess.Add(brush);
s_brushMap[brush.GetFloatHash()] = brush;
Assert.True(m_aBrushToProcess.Count <= MaxBrushes, MaxBrushWarningMessage);
RescanBrushes();
}
public void RemoveBrush(MudBrushBase brush)
{
#if MUDBUN_DEV
Assert.True(brush.m_renderer != null, "Brush was never added.");
Assert.True(brush.m_renderer == this, "Brush was not added to this renderer.");
#endif
ValidateAabbTree();
brush.DestroyProxies(m_aabbTree);
m_aabbTreeDirty = true;
brush.m_renderer = null;
m_aBrush.Remove(brush);
m_aBrushToProcess.Remove(brush);
if (brush.IsBrushGroup)
m_aBrushToProcess.Remove(brush);
s_brushMap.Remove(brush.GetFloatHash());
RescanBrushes();
}
public void DestroyAllBrushes()
{
var aBrushCopy = Brushes.ToArray();
foreach (var b in aBrushCopy)
{
var m = b.GetComponent<MudMaterialBase>();
Destroy(b);
Destroy(m);
}
}
public void DestroyAllBrushesImmediate()
{
var aBrushCopy = Brushes.ToArray();
foreach (var b in aBrushCopy)
{
var m = b.GetComponent<MudMaterialBase>();
DestroyImmediate(b);
DestroyImmediate(m);
}
}
public virtual void NotifyHierarchyChange()
{
RescanBrushes();
}
private void ClearBrushes()
{
ValidateAabbTree();
foreach (var brush in m_aBrush)
{
brush.m_renderer = null;
brush.DestroyProxies(m_aabbTree);
}
m_aBrush.Clear();
m_aBrushToProcess.Clear();
RescanBrushes();
}
public void RescanBrushes()
{
m_needRescanBrushes = true;
}
public void RescanBrushesImmediate()
{
ClearBrushes();
ScanHierarchyRecursive(transform);
ValidateBrushSetHash();
}
private int ComputeBrushListHash()
{
int hash = 0;
for (int iBrush = 0, numBrushes = m_aBrushToProcess.Count; iBrush < numBrushes; ++iBrush)
{
var brush = m_aBrushToProcess[iBrush];
hash = Codec.HashConcat(hash, brush.GetInstanceID());
}
return hash;
}
private int m_brushSetHash = -1;
private void ValidateBrushSetHash()
{
int brushListHash = ComputeBrushListHash();
if (brushListHash != m_brushSetHash)
{
MarkNeedsCompute();
m_brushSetHash = brushListHash;
m_brushDataDirty = true;
}
}
private int m_brushGroupDepth = 0;
private void ScanHierarchyRecursive(Transform parent)
{
if (parent == null)
return;
parent.TryGetComponent(out MudBrushBase parentBrush);
bool parentIsGroup = (parentBrush != null && parentBrush.IsBrushGroup && parentBrush.isActiveAndEnabled);
if (parentIsGroup)
{
++m_brushGroupDepth;
if (m_brushGroupDepth >= MaxBrushGroupDepth)
Assert.Warn($"MudBun: Exceeded maximum group depth of {MaxBrushGroupDepth}!");
}
for (int iChild = 0; iChild < parent.childCount; ++iChild)
{
var child = parent.GetChild(iChild);
// renderer blocks recursion
if (child.TryGetComponent(out MudRendererBase _))
continue;
if (child.TryGetComponent(out MudBrushBase brush) && brush.isActiveAndEnabled)
AddBrush(brush);
ScanHierarchyRecursive(child);
}
if (parentIsGroup)
{
m_aBrushToProcess.Add(parentBrush);
--m_brushGroupDepth;
}
}
private void SetUpResources()
{
Profiler.BeginSample("SetUpResources");
WriteResources();
BindComputeResources();
Profiler.EndSample();
}
private void UpdateActivePreCompute()
{
if (m_doRigging)
ComputeManager.Activate(s_computeMeshLock);
else
ComputeManager.Deactivate(s_computeMeshLock);
switch (MeshingMode)
{
case MeshingModeEnum.MarchingCubes:
ComputeManager.Activate(s_computeMarchingCubes);
ComputeManager.Deactivate(s_computeDualMeshing);
ComputeManager.Deactivate(s_computeSurfaceNets);
ComputeManager.Deactivate(s_computeDualContouring);
break;
case MeshingModeEnum.DualQuads:
ComputeManager.Activate(s_computeDualMeshing);
ComputeManager.Deactivate(s_computeMarchingCubes);
ComputeManager.Deactivate(s_computeSurfaceNets);
ComputeManager.Deactivate(s_computeDualContouring);
break;
case MeshingModeEnum.SurfaceNets:
ComputeManager.Activate(s_computeDualMeshing);
ComputeManager.Activate(s_computeSurfaceNets);
ComputeManager.Deactivate(s_computeMarchingCubes);
ComputeManager.Deactivate(s_computeDualContouring);
break;
case MeshingModeEnum.DualContouring:
ComputeManager.Activate(s_computeDualMeshing);
ComputeManager.Activate(s_computeDualContouring);
ComputeManager.Deactivate(s_computeMarchingCubes);
ComputeManager.Deactivate(s_computeSurfaceNets);
break;
}
/*
if (RenderModeCategory == RenderModeCategoryEnum.RayTracedVoxels)
ComputeManager.Activate(s_computeRayTracedVoxels);
else
*/
ComputeManager.Deactivate(s_computeRayTracedVoxels);
}
private void UpdateActivePostCompute()
{
if (m_doRigging)
ComputeManager.Deactivate(s_computeMeshLock);
}
private bool ValidateAabbTreeBuffer(ref ComputeBuffer aabbTreeBuffer)
{
if (m_aabbTreeBuffer != null
&& m_aabbTreeBuffer.count >= m_aabbTree.Capacity)
return false;
if (aabbTreeBuffer != null)
aabbTreeBuffer.Release();
aabbTreeBuffer = new ComputeBuffer(m_aabbTree.Capacity, AabbTree<MudBrushBase>.NodePod.Stride);
return true;
}
private void ValidateRenderMaterial()
{
Material material = null;
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Mesh:
material = RenderMaterialMesh;
break;
case RenderModeCategoryEnum.Splats:
material = RenderMaterialSplats;
break;
case RenderModeCategoryEnum.Decal:
material = RenderMaterialDecal;
break;
/*
case RenderModeCategoryEnum.RayMarchedSurface:
material = RenderMaterialRayMarchedSurface;
break;
case RenderModeCategoryEnum.RayTracedVoxels:
material = RenderMaterialRayTracedVoxels;
break;
*/
}
{
Profiler.BeginSample("Copy Render Material Properties");
if (m_materialCloned != material)
{
m_materialUsed = new Material(material);
m_materialCloned = material;
if (!Application.isEditor)
{
m_renderMaterialDirty = true;
}
}
if (Application.isEditor)
{
// need to do this constantly in editor because the user can change the referenced material
// TODO: timeslice this when in play mode
m_renderMaterialDirty = true;
}
if (RenderMaterialMode == RenderMaterialModeEnum.Dynamic)
{
m_renderMaterialDirty = true;
}
if (m_renderMaterialDirty)
{
m_materialUsed.CopyPropertiesFromMaterial(m_materialCloned);
m_materialUsed.enableInstancing = true;
m_renderMaterialDirty = false;
}
Profiler.EndSample();
}
m_materialUsed.EnableKeyword("MUDBUN_PROCEDURAL");
switch (RenderMode)
{
case RenderModeEnum.QuadSplats:
m_materialUsed.EnableKeyword("MUDBUN_QUAD_SPLATS");
break;
default:
m_materialUsed.DisableKeyword("MUDBUN_QUAD_SPLATS");
break;
}
}
protected virtual bool ShouldHighlightBrushFromSelection(MudBrushBase brush)
{
return false;
}
private void UpdateBrushData()
{
if (!m_brushDataDirty && !m_doRigging)
return;
// need to complete queued jobs before writing to native arrays again
for (int i = 0; i < m_jobCompleteQueue.Count; ++i)
{
m_jobCompleteQueue[i].Complete();
}
m_jobCompleteQueue.Clear();
Profiler.BeginSample("UpdateBrushData");
m_numSdfBrushes = 0;
m_numSdfMaterials = 0;
m_sdfBrushMaterialIndexMap.Clear();
m_aBone = (m_doRigging ? new List<Transform>() : null);
for (int iBrush = 0, numBrushes = m_aBrushToProcess.Count; iBrush < numBrushes; ++iBrush)
{
var brush = m_aBrushToProcess[iBrush];
Profiler.BeginSample("Each Brush");
brush.m_iSdfBrush = m_numSdfBrushes;
Profiler.BeginSample("Fill Material");
int materialIndex = -1;
bool selectionHighlight = ShouldHighlightBrushFromSelection(brush);
/*
if (selectionHighlight)
{
materialIndex = m_numSdfMaterials;
m_sdfBrushMaterialIndexMap[0] = materialIndex;
var mat = m_aSdfBrushMaterial[m_numSdfMaterials];
brush.FillBrushMaterialData(ref mat);
var color = mat.Color;
color.r = Mathf.Min(1.0f, color.r + 0.1f);
color.g = Mathf.Min(1.0f, color.g + 0.1f);
color.b = Mathf.Min(1.0f, color.b + 0.1f);
mat.Color = color;
var emissionHash = mat.EmissionHash;
emissionHash.r = Mathf.Min(1.0f, emissionHash.r + 0.1f);
emissionHash.g = Mathf.Min(1.0f, emissionHash.g + 0.1f);
emissionHash.b = Mathf.Min(1.0f, emissionHash.b + 0.1f);
mat.EmissionHash = emissionHash;
m_aSdfBrushMaterial[m_numSdfMaterials] = mat;
++m_numSdfMaterials;
}
else
*/
{
if (brush.UsesMaterial
&& !m_sdfBrushMaterialIndexMap.TryGetValue(brush.MaterialHash, out materialIndex))
{
materialIndex = m_numSdfMaterials;
m_sdfBrushMaterialIndexMap.Add(brush.MaterialHash, materialIndex);
var mat = m_aSdfBrushMaterial[m_numSdfMaterials];
brush.FillBrushMaterialData(ref mat);
m_aSdfBrushMaterial[m_numSdfMaterials] = mat;
++m_numSdfMaterials;
}
}
#if MUDBUN_DEV
Assert.True(!brush.UsesMaterial || materialIndex >= 0);
#endif
Profiler.EndSample();
Profiler.BeginSample("Fill Compute Data");
int numNewBrushes =
(!brush.IsBrushGroup || !brush.m_preChildrenFlag)
? brush.FillComputeData(m_aSdfBrush, m_numSdfBrushes, (brush.CountAsBone ? m_aBone : null))
: brush.FillComputeDataPostChildren(m_aSdfBrush, m_numSdfBrushes);
Profiler.EndSample();
Profiler.BeginSample("Fill Brush Data");
float hash = brush.GetFloatHash();
for (int iNewBrush = 0; iNewBrush < numNewBrushes; ++iNewBrush)
{
int iSdfBrush = m_numSdfBrushes + iNewBrush;
var b = m_aSdfBrush[iSdfBrush];
b.Index = iSdfBrush;
if (!brush.IsBrushGroup || !brush.m_preChildrenFlag)
brush.FillBrushData(ref b, iSdfBrush);
else
brush.FillBrushDataPostChildren(ref b, iSdfBrush);
b.MaterialIndex = materialIndex;
b.Hash =
selectionHighlight
? -hash // encode selection highlight in negative hash sign
: hash;
m_aSdfBrush[iSdfBrush] = b;
}
Profiler.EndSample();
m_numSdfBrushes += numNewBrushes;
if (brush.IsBrushGroup)
brush.m_preChildrenFlag = !brush.m_preChildrenFlag;
Profiler.EndSample();
}
m_brushDataDirty = false;
Profiler.EndSample();
}
private void UpdateAabbTreeData()
{
if (!m_aabbTreeDirty)
return;
Profiler.BeginSample("UpdateAabbTree");
Aabb successorModifierBounds = Aabb.Empty;
Aabb accumulatedBounds = Aabb.Empty;
Aabb groupBounds = Aabb.Empty;
var groupSymmetry = MudSolid.SymmetryMode.None;
foreach (var brush in m_aBrushToProcess)
{
Aabb opBounds = brush.BoundsRs;
if (brush.IsBrushGroup)
{
if (!brush.m_preChildrenFlag)
{
// begin group
m_brushGroupBoundsStack.Push(groupBounds);
m_accumulatedBoundsStack.Push(accumulatedBounds);
m_brushGroupSymmetryStack.Push(groupSymmetry);
groupBounds = Aabb.Empty;
accumulatedBounds = Aabb.Empty;
groupSymmetry = ((MudBrushGroup) brush).Symmetry;
}
else
{
// end group
opBounds = groupBounds;
opBounds.Expand(m_aabbTree.FatBoundsRadius);
groupBounds = m_brushGroupBoundsStack.Pop();
accumulatedBounds = m_accumulatedBoundsStack.Pop();
groupSymmetry = m_brushGroupSymmetryStack.Pop();
}
brush.m_preChildrenFlag = !brush.m_preChildrenFlag;
}
if (groupSymmetry != MudSolid.SymmetryMode.None)
opBounds = MudSolid.SymmetryBounds(groupSymmetry, opBounds);
if (opBounds.IsEmpty)
{
if (brush.IsBrushGroup)
brush.UpdateProxies(m_aabbTree, opBounds);
continue;
}
if (brush.IsSuccessorModifier)
successorModifierBounds.Include(opBounds);
opBounds.Include(successorModifierBounds);
accumulatedBounds.Include(opBounds);
groupBounds.Include(opBounds);
if (brush.ShouldUseAccumulatedBounds)
opBounds = accumulatedBounds;
opBounds.Expand(brush.BoundsRsPadding);
accumulatedBounds.Include(opBounds);
groupBounds.Include(opBounds);
brush.UpdateProxies(m_aabbTree, opBounds);
}
m_aabbTree.UpdatePods();
m_aabbTreeDirty = false;
Profiler.EndSample();
}
protected int m_numSdfBrushes;
protected int m_numSdfMaterials;
protected List<Transform> m_aBone;
private Stack<Aabb> m_brushGroupBoundsStack = new Stack<Aabb>();
private Stack<Aabb> m_accumulatedBoundsStack = new Stack<Aabb>();
private Stack<MudSolid.SymmetryMode> m_brushGroupSymmetryStack = new Stack<MudSolid.SymmetryMode>();
private void WriteResources()
{
Profiler.BeginSample("WriteResources");
Profiler.BeginSample("Brushes");
if (m_materialUsed == null)
ValidateRenderMaterial();
float effectiveSurfaceShift = SurfaceShift + 1e-5f; // tiny offset to fix voxel edges perfectly lining up with zero isosurface
if (RenderModeCategory == RenderModeCategoryEnum.Decal)
effectiveSurfaceShift += 0.5f * VoxelSize;
Profiler.BeginSample("Set Brush Data");
m_brushesBuffer.SetData(m_aSdfBrush, 0, 0, m_numSdfBrushes);
Profiler.EndSample();
Profiler.BeginSample("Set Material Data");
m_brushMaterialBuffer.SetData(m_aSdfBrushMaterial, 0, 0, m_numSdfMaterials);
Profiler.EndSample();
ComputeManager.SetInt(Const.NumBrushes, m_numSdfBrushes);
ComputeManager.SetFloat(Const.SurfaceShift, effectiveSurfaceShift);
ComputeManager.SetInt(Const.RenderMode, (int) RenderMode);
ComputeManager.SetInt(Const.MeshingMode, (int) MeshingMode);
ComputeManager.SetInt(Const.RayTracedVoxelMode, (int) RayTracedVoxelMode);
ComputeManager.SetFloat(Const.RayTracedVoxelSizeMultiplier, RayTracedVoxelSizeMultiplier);
ComputeManager.SetInt(Const.RayTracedVoxelPaddingMode, (int) RayTracedVoxelPaddingMode);
ComputeManager.SetFloat(Const.RayTracedVoxelSmoothCubeNormal, RayTracedVoxelSmoothCubeNormal);
ComputeManager.SetFloat(Const.RayTracedVoxelRadius, 1.0f + 0.733f * RayTracedVoxelSphereFullness);
ComputeManager.SetInt(Const.RayTracedVoxelPaddingMode, (int) RayTracedVoxelPaddingMode);
ComputeManager.SetFloat(Const.RayTracedVoxelInternalPaddingDistance, RayTracedVoxelInternalPaddingDistance);
ComputeManager.SetFloat(Const.RayTracedVoxelSizeFadeDistance, RayTracedVoxelSizeFadeDistance);
ComputeManager.SetFloat(Const.NormalDifferentiationStep, NormalDifferentialStep);
ComputeManager.SetFloat(Const.NormalQuantization, NormalQuantization);
ComputeManager.SetFloat(Const.Normal2dFadeDist, Normal2dFade);
ComputeManager.SetFloat(Const.Normal2dStrength, Normal2dStrength);
bool shouldDoAutoSmoothing = ShouldDoAutoSmoothing;
ComputeManager.SetBool(Const.EnableAutoSmooth, shouldDoAutoSmoothing);
ComputeManager.SetFloat(Const.AutoSmoothMaxAngle, AutoSmoothingMaxAngle * MathUtil.Deg2Rad);
ComputeManager.SetBuffer(Const.AutoSmoothVertDataTable, (shouldDoAutoSmoothing && m_autoSmoothVertDataTableBuffer != null) ? m_autoSmoothVertDataTableBuffer : s_dummyBuffer);
ComputeManager.SetInt(Const.AutoSmoothVertDataPoolSize, (shouldDoAutoSmoothing && m_autoSmoothVertDataTableBuffer != null) ? m_autoSmoothVertDataTableBuffer.count : 0);
ComputeManager.SetBool(Const.EnableSmoothCorner, EnableSmoothCorner);
ComputeManager.SetInt(Const.SmoothCornerSubdivision, SmoothCornerSubdivision);
ComputeManager.SetFloat(Const.SmoothCornerNormalBlur, 0.05f * VoxelSize + SmoothCornerNormalBlur);
ComputeManager.SetFloat(Const.SmoothCornerFade, SmoothCornerFade);
ComputeManager.SetInt(Const.InvertNormals, (InvertNormals && !Enable2dMode ? 1 : 0));
Profiler.EndSample();
Profiler.BeginSample("BVH");
bool needComputeFromAabbTree = false;
if (AllowSharedRWBuffers)
{
needComputeFromAabbTree = ValidateAabbTreeBuffer(ref s_aabbTreeBuffer);
m_aabbTreeBuffer = s_aabbTreeBuffer;
}
else
{
needComputeFromAabbTree = ValidateAabbTreeBuffer(ref m_aabbTreeBuffer);
}
if (needComputeFromAabbTree)
{
m_needsCompute = true;
}
m_aabbTree.FillComputeBuffer(m_aabbTreeBuffer);
m_aabbTreeBufferRoot = m_aabbTree.Root;
Profiler.EndSample();
Profiler.BeginSample("Voxel Tree");
ComputeManager.SetInt(Const.NodeHashTableSize, m_nodeHashTableBuffer.count);
// general allocation counters
m_numAllocationsBuffer.SetData(NumAllocatoinsBufferInitData);
// node pool
ComputeManager.SetInt(Const.NodePoolSize, m_nodePoolBuffer.count);
if (m_numAllocationsBufferInitData == null || m_numAllocationsBufferInitData.Length != m_numNodesAllocatedBuffer.count)
m_numAllocationsBufferInitData = new int[m_numNodesAllocatedBuffer.count];
for (int depth = 0; depth < m_numAllocationsBufferInitData.Length; ++depth)
m_numAllocationsBufferInitData[depth] = 0;
m_numNodesAllocatedBuffer.SetData(m_numAllocationsBufferInitData);
// voxel cache
ComputeManager.SetBool(Const.UseVoxelCache, UseVoxelCache);
ComputeManager.SetInt(Const.VoxelCacheSize, (m_voxelCacheBuffer != null ? m_voxelCacheBuffer.count : 0));
// brush bit masks
ComputeManager.SetInt(Const.BrushMaskPoolSize, MaxBrushMasks);
// dispatch args
m_indirectDispatchArgsBuffer.SetData(UnitIndirectDispatchArgsInitData);
Profiler.EndSample();
Profiler.BeginSample("Indirect Draw Args");
// indirect draw args
m_indirectDrawArgsBufferDefault.SetData(IndirectDrawArgsInitData);
if (m_indirectDrawArgsBufferOverride != null)
m_indirectDrawArgsBufferOverride.SetData(IndirectDrawArgsInitData);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.RenderMode);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NumBrushes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodeHashTableSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodePoolSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.BrushMaskPoolSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.Brushes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.BrushMaterials);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.SurfaceShift);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AabbTree);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AabbRoot);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.Enable2dMode);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.ForceAllBrushes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodeHashTable);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NodePool);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NumNodesAllocated);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NumAllocations);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.BrushMaskPool);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.IndirectDispatchArgs);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.GenPoints);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.IndirectDrawArgs);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.VoxelSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.VoxelTreeBranchingFactorsCompressed);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.VoxelNodeSizes);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.MaxNodeDepth);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.ChunkVoxelDensity);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NoiseCache);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NoiseCacheDimension);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NoiseCacheDensity);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.CurrentNodeDepth);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.CurrentNodeBranchingFactor);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.CurrentNodeSize);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.NormalDifferentiationStep);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.EnableAutoSmooth);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AutoSmoothMaxAngle);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AutoSmoothVertDataTable);
ComputeManager.RegisterConstantId(s_computeVoxelGen, Const.AutoSmoothVertDataPoolSize);
Profiler.EndSample();
Profiler.EndSample();
}
private void BindComputeResources()
{
Profiler.BeginSample("BindComputeResources");
m_genPointsBufferUsedForCompute = m_genPointsBufferOverride != null ? m_genPointsBufferOverride : m_genPointsBufferDefault;
m_indirectDrawArgsBufferUsedForCompute = m_indirectDrawArgsBufferOverride != null ? m_indirectDrawArgsBufferOverride : m_indirectDrawArgsBufferDefault;
ComputeManager.SetBuffer(Const.Brushes, m_brushesBuffer);
ComputeManager.SetBuffer(Const.BrushMaterials, m_brushMaterialBuffer);
ComputeManager.SetBuffer(Const.AabbTree, m_aabbTreeBuffer);
ComputeManager.SetInt(Const.AabbRoot, m_aabbTreeBufferRoot);
ComputeManager.SetBuffer(Const.NodeHashTable, m_nodeHashTableBuffer);
ComputeManager.SetBuffer(Const.NodePool, m_nodePoolBuffer);
ComputeManager.SetBuffer(Const.NumNodesAllocated, m_numNodesAllocatedBuffer);
ComputeManager.SetBuffer(Const.NumAllocations, m_numAllocationsBuffer);
ComputeManager.SetBuffer(Const.VoxelCacheIdTable, UseVoxelCache ? m_voxelCacheIdTableBuffer : m_numAllocationsBuffer);
ComputeManager.SetBuffer(Const.VoxelCache, UseVoxelCache ? m_voxelCacheBuffer : m_numAllocationsBuffer);
ComputeManager.SetBuffer(Const.BrushMaskPool, m_brushMaskPoolBuffer);
ComputeManager.SetBuffer(Const.IndirectDispatchArgs, m_indirectDispatchArgsBuffer);
ComputeManager.SetBuffer(Const.GenPoints, m_genPointsBufferUsedForCompute);
ComputeManager.SetBuffer(Const.IndirectDrawArgs, m_indirectDrawArgsBufferUsedForCompute);
ComputeManager.SetBool(Const.Enable2dMode, Enable2dMode);
ComputeManager.SetBool(Const.ForceAllBrushes, ShouldForceAllBrushes());
ComputeManager.SetFloat(Const.VoxelSize, VoxelSize);
ComputeManager.SetInt(Const.VoxelTreeBranchingFactorsCompressed, VoxelTreeBranchingFactorsComrpessed);
ComputeManager.SetVector(Const.VoxelNodeSizes, NodeSizesVector);
ComputeManager.SetInt(Const.MaxNodeDepth, VoxelNodeDepth);
ComputeManager.SetInt(Const.ChunkVoxelDensity, ChunkVoxelDensity);
ComputeManager.SetInt(Const.MaxGenPoints, MaxGenPoints);
ComputeManager.SetTexture(Const.NoiseCache, s_noiseCache);
//ComputeManager.SetTexture(Const.NoiseCache, NoiseCache);
ComputeManager.SetFloats(Const.NoiseCacheDimension, NoiseCacheDimensionFloats);
ComputeManager.SetFloat(Const.NoiseCacheDensity, NoiseCacheDensity);
ComputeManager.SetInt(Const.MeshGenerationAutoRiggingAlgorithm, (int) MeshGenerationAutoRiggingAlgorithm);
switch (MeshingMode)
{
case MeshingModeEnum.SurfaceNets:
ComputeManager.SetFloat(Const.SurfaceNetsDualQuadsBlend, SurfaceNetsDualQuadsBlend);
/*
ComputeManager.SetInt(Const.SurfaceNetsBinarySearchIterations, SurfaceNetsBinarySearchIterations);
ComputeManager.SetInt(Const.SurfaceNetsGradientDescentIterations, SurfaceNetsGradientDescentIterations);
ComputeManager.SetFloat(Const.SurfaceNetsGradientDescentFactor, SurfaceNetsGradientDescentFactor);
*/
/*
if (SurfaceNetsHighAccuracyMode)
{
ComputeManager.SetInt(Const.SurfaceNetsBinarySearchIterations, 6);
ComputeManager.SetInt(Const.SurfaceNetsGradientDescentIterations, 1);
ComputeManager.SetFloat(Const.SurfaceNetsGradientDescentFactor, 1.0f);
}
else
{
ComputeManager.SetInt(Const.SurfaceNetsBinarySearchIterations, 0);
ComputeManager.SetInt(Const.SurfaceNetsGradientDescentIterations, 0);
ComputeManager.SetFloat(Const.SurfaceNetsGradientDescentFactor, 0.0f);
}
*/
break;
case MeshingModeEnum.DualContouring:
ComputeManager.SetFloat(Const.DualContouringDualQuadsBlend, DualContouringDualQuadsBlend);
ComputeManager.SetFloat(Const.DualContouringRelaxation, 0.15f + 0.85f * DualContouringRelaxation);
//ComputeManager.SetInt(Const.DualContouringSolverIterations, DualContouringSolverIterations);
/*
ComputeManager.SetInt(Const.DualContouringBinarySearchIterations, DualContouringBinarySearchIterations);
ComputeManager.SetInt(Const.DualContouringGradientDescentIterations, DualContouringGradientDescentIterations);
ComputeManager.SetFloat(Const.DualContouringGradientDescentFactor, DualContouringGradientDescentFactor);
*/
if (DualContouringHighAccuracyMode)
{
ComputeManager.SetInt(Const.DualContouringSolverIterations, 0);
ComputeManager.SetInt(Const.DualContouringBinarySearchIterations, 10);
ComputeManager.SetInt(Const.DualContouringGradientDescentIterations, 1);
ComputeManager.SetFloat(Const.DualContouringGradientDescentFactor, 1.0f);
}
else
{
ComputeManager.SetInt(Const.DualContouringSolverIterations, 0);
ComputeManager.SetInt(Const.DualContouringBinarySearchIterations, 0);
ComputeManager.SetInt(Const.DualContouringGradientDescentIterations, 0);
ComputeManager.SetFloat(Const.DualContouringGradientDescentFactor, 0.0f);
}
break;
}
Profiler.EndSample();
}
private void BindRenderResources()
{
Profiler.BeginSample("BindRenderResources");
if (m_materialProps == null)
{
m_materialProps = new MaterialPropertyBlock();
m_needsCompute = true;
}
m_materialProps.SetBuffer(Const.GenPoints, m_genPointsBufferDefault);
m_materialProps.SetVector(Const.MasterColor, MasterColor);
m_materialProps.SetVector(Const.MasterEmission, MasterEmission);
m_materialProps.SetFloat(Const.MasterMetallic, MasterMetallic);
m_materialProps.SetFloat(Const.MasterSmoothness, MasterSmoothness);
m_materialProps.SetInt(Const.InvertNormals, (InvertNormals && !Enable2dMode ? 1 : 0));
m_materialProps.SetInt(Const.Enable2dMode, Enable2dMode ? 1 : 0);
m_materialProps.SetFloat(Const.VoxelSize, VoxelSize);
m_materialProps.SetInt(Const.VoxelTreeBranchingFactorsCompressed, VoxelTreeBranchingFactorsComrpessed);
m_materialProps.SetVector(Const.VoxelNodeSizes, NodeSizesVector);
m_materialProps.SetFloat(Const.SplatSize, SplatSize * (1.5f / VoxelDensity));
m_materialProps.SetFloat(Const.SplatSizeJitter, SplatSizeJitter);
m_materialProps.SetFloat(Const.SplatNormalShift, SplatNormalShift);
m_materialProps.SetFloat(Const.SplatNormalShiftJitter, SplatNormalShiftJitter);
m_materialProps.SetFloat(Const.SplatColorJitter, SplatColorJitter);
m_materialProps.SetFloat(Const.SplatPositionJitter, SplatPositionJitter);
m_materialProps.SetFloat(Const.SplatRotationJitter, SplatRotationJitter);
m_materialProps.SetFloat(Const.SplatOrientationJitter, SplatOrientationJitter);
m_materialProps.SetFloat(Const.SplatOriginalNormalBlend, SplatOriginalNormalBlend);
m_materialProps.SetFloat(Const.SplatJitterNoisiness, SplatJitterNoisiness);
m_materialProps.SetFloat(Const.SplatCameraFacing, SplatCameraFacing);
m_materialProps.SetInt(Const.SplatNormalsMatchCameraFacing, SplatNormalsMatchCameraFacing ? 1 : 0);
m_materialProps.SetInt(Const.SplatShadowsMatchCameraFacing, SplatShadowsMatchCameraFacing ? 1 : 0);
m_materialProps.SetFloat(Const.SplatScreenSpaceFlattening, SplatScreenSpaceFlattening);
//m_materialProps.SetFloat(Const.SplatSmoothNormalBlend, SplatSmoothNormalBlend);
Vector3 scale = transform.localToWorldMatrix.lossyScale;
m_materialProps.SetInt(Const.ScaleSign, (scale.x * scale.y * scale.z) >= 0.0f ? 1 : -1);
m_materialProps.SetMatrix(Const.LocalToWorld, transform.localToWorldMatrix);
m_materialProps.SetMatrix(Const.LocalToWorldIt, transform.localToWorldMatrix.inverse.transpose);
m_materialProps.SetVector(Const.LocalToWorldScale, transform.localScale);
m_materialProps.SetMatrix(Const.WorldToLocal, transform.worldToLocalMatrix);
m_materialProps.SetMatrix(Const.WorldToLocalIt, transform.worldToLocalMatrix.inverse.transpose);
m_materialProps.SetInt(Const.RenderMode, (int) RenderMode);
m_materialProps.SetInt(Const.MeshingMode, (int) MeshingMode);
m_materialProps.SetInt(Const.RayTracedVoxelMode, (int) RayTracedVoxelMode);
m_materialProps.SetFloat(Const.RayTracedVoxelSizeMultiplier, RayTracedVoxelSizeMultiplier);
m_materialProps.SetFloat(Const.RayTracedVoxelSmoothCubeNormal, RayTracedVoxelSmoothCubeNormal);
m_materialProps.SetFloat(Const.RayTracedVoxelRadius, 1.0f + 0.733f * RayTracedVoxelSphereFullness);
m_materialProps.SetInt(Const.RayTracedVoxelPaddingMode, (int) RayTracedVoxelPaddingMode);
m_materialProps.SetInt(Const.RayTracedVoxelPaddingMode, (int)RayTracedVoxelPaddingMode);
m_materialProps.SetFloat(Const.RayTracedVoxelInternalPaddingDistance, RayTracedVoxelInternalPaddingDistance);
m_materialProps.SetFloat(Const.RayTracedVoxelSizeFadeDistance, RayTracedVoxelSizeFadeDistance);
m_materialProps.SetFloat(Const.NormalQuantization, NormalQuantization);
m_materialProps.SetFloat(Const.Normal2dFadeDist, Normal2dFade);
m_materialProps.SetFloat(Const.Normal2dStrength, Normal2dStrength);
m_materialProps.SetFloat(Const.AutoSmoothMaxAngle, EnableAutoSmoothing ? AutoSmoothingMaxAngle * MathUtil.Deg2Rad : -1.0f);
//if (MaterialNeedsSdfProperties(m_materialUsed))
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Decal:
//case RenderModeCategoryEnum.RayMarchedSurface:
//case RenderModeCategoryEnum.RayTracedVoxels:
m_materialProps.SetBuffer(Const.NodeHashTable, m_nodeHashTableBuffer);
m_materialProps.SetInt(Const.NodeHashTableSize, m_nodeHashTableBuffer.count);
m_materialProps.SetBuffer(Const.NodePool, m_nodePoolBuffer);
m_materialProps.SetBuffer(Const.VoxelCacheIdTable, UseVoxelCache ? m_voxelCacheIdTableBuffer : m_numAllocationsBuffer);
m_materialProps.SetBuffer(Const.VoxelCache, UseVoxelCache ? m_voxelCacheBuffer : m_numAllocationsBuffer);
m_materialProps.SetBuffer(Const.BrushMaskPool, m_brushMaskPoolBuffer);
m_materialProps.SetBuffer(Const.Brushes, m_brushesBuffer);
m_materialProps.SetBuffer(Const.BrushMaterials, m_brushMaterialBuffer);
m_materialProps.SetInt(Const.NumBrushes, m_numSdfBrushes);
m_materialProps.SetBuffer(Const.AabbTree, m_aabbTreeBuffer);
m_materialProps.SetInt(Const.AabbRoot, m_aabbTreeBufferRoot);
m_materialProps.SetTexture(Const.NoiseCache, NoiseCache);
m_materialProps.SetVector(Const.NoiseCacheDimension, new Vector4(NoiseCacheDimensionFloats[0], NoiseCacheDimensionFloats[1], NoiseCacheDimensionFloats[2]));
m_materialProps.SetFloat(Const.NoiseCacheDensity, NoiseCacheDensity);
m_materialProps.SetFloat(Const.SurfaceShift, SurfaceShift);
//if (MaterialNeedsRayMarchingProperties(m_materialUsed))
if (false /* RenderModeCategory == RenderModeCategoryEnum.RayMarchedSurface */)
{
/*
m_materialProps.SetInt(Const.MaxRayMarchSteps, MaxRayMarchSteps);
m_materialProps.SetFloat(Const.RayMarchHitDistance, 1e-1f * Mathf.Pow(1e-1f, 2.0f * RayMarchAccuracy));
m_materialProps.SetFloat(Const.RayMarchMaxRayDistance, RayMarchMaxRayDistance);
*/
/*
m_materialProps.SetFloat(Const.RayMarchStepSize, RayMarchDistance / Mathf.Max(1, MaxRayMarchSteps));
m_materialProps.SetFloat(Const.RayMarchStepSize, RayMarchStepSize);
m_materialProps.SetInt(Const.NumLightMarchSteps, NumLightMarchSteps);
m_materialProps.SetFloat(Const.RayMarchVolumeDensity, RayMarchVolumeDensity);
if (RayMarchLight != null)
{
Vector3 lightPos = RayMarchLight.transform.position;
m_materialProps.SetVector(Const.RayMarchLightPositionType, new Vector4(lightPos.x, lightPos.y, lightPos.z, (int) RayMarchLight.type));
m_materialProps.SetVector(Const.RayMarchLightDirection, RayMarchLight.transform.forward);
}
else
{
m_materialProps.SetVector(Const.RayMarchLightPositionType, new Vector4(0.0f, 0.0f, 0.0f, (int) LightType.Directional));
m_materialProps.SetVector(Const.RayMarchLightDirection, Vector3.down);
}
m_materialProps.SetVector(Const.RayMarchAbsorption, new Vector4(RayMarchVolumeAbsorption, RayMarchLightAbsorption));
m_materialProps.SetFloat(Const.RayMarchDarknesThreshold, RayMarchDarknesThreshold);
m_materialProps.SetFloat(Const.RayMarchTransmittanceCurve, RayMarchTransmittanceCurve);
m_materialProps.SetFloat(Const.RayMarchNoiseEdgeFade, RayMarchNoiseEdgeFade);
m_materialProps.SetFloat(Const.RayMarchNoiseThreshold, UseRayMarchNoise ? RayMarchNoiseThreshold : 0.0f);
m_materialProps.SetVector(Const.RayMarchNoiseScrollSpeed, RayMarchNoiseScrollSpeed);
m_materialProps.SetVector(Const.RayMarchNoiseBaseOctaveSize, RayMarchNoiseBaseOctaveSize);
m_materialProps.SetInt(Const.RayMarchNoiseNumOctaves, RayMarchNoiseNumOctaves);
m_materialProps.SetFloat(Const.RayMarchNoiseOctaveOffsetFactor, RayMarchNoiseOctaveOffsetFactor);
*/
}
break;
}
Profiler.EndSample();
}
#endregion // end: Brushes
//-------------------------------------------------------------------------
#region Core
public ComputeModeEnum ComputeMode = ComputeModeEnum.Auto;
public TimeSliceModeEnum TimeSliceMode = TimeSliceModeEnum.ByPeriodAutoOffset;
[Min(1)] public int TimeSliceFrames = 3;
public int TimeSliceFramesOffset = 0;
[Min(0.0001f)] public float TimeSlicePeriod = 0.05f;
public float TimeSliceTimeOffset = 0;
private float m_lastUpdateTimeSliceTime = -1.0f;
private int m_rendererIndex = -1;
private void SetComputeNodeDepth(int depth)
{
ComputeManager.SetInt(Const.CurrentNodeDepth, depth);
ComputeManager.SetInt(Const.CurrentNodeBranchingFactor, (depth < VoxelNodeDepth ? VoxelTreeBranchingFactors[depth] : 0));
ComputeManager.SetFloat(Const.CurrentNodeSize, NodeSizes[depth]);
}
private void ComputeGpu()
{
Profiler.BeginSample("Compute (GPU)");
UpdateActivePreCompute();
SetUpResources();
Profiler.BeginSample("Core Dispatch");
ComputeManager.Dispatch
(
s_computeVoxelGen,
Const.Kernel.ClearVoxelHashTable,
Mathf.Max(1, (m_nodeHashTableBuffer.count + ClearThreadGroupSize - 1) / ClearThreadGroupSize), 1, 1
);
if (ShouldDoAutoSmoothing)
{
ComputeManager.Dispatch
(
s_computeVoxelGen,
Const.Kernel.ClearAutoSmoothVertDataTable,
Mathf.Max(1, (m_autoSmoothVertDataTableBuffer.count + ClearThreadGroupSize - 1) / ClearThreadGroupSize), 1, 1
);
}
if (UseVoxelCache)
{
ComputeManager.Dispatch
(
s_computeVoxelGen,
Const.Kernel.ClearVoxelCache,
Mathf.Max(1, (m_voxelCacheIdTableBuffer.count + ClearThreadGroupSize - 1) / ClearThreadGroupSize), 1, 1
);
}
SetComputeNodeDepth(0);
ComputeManager.Dispatch
(
s_computeVoxelGen,
Const.Kernel.RegisterTopNodes,
Mathf.Max(1, (m_numSdfBrushes + ThreadGroupSize - 1) / ThreadGroupSize), 1, 1
);
for (int depth = 0; depth < VoxelNodeDepth; ++depth)
{
SetComputeNodeDepth(depth);
ComputeManager.Dispatch(s_computeVoxelGen, Const.Kernel.UpdateBranchingIndirectDispatchArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeVoxelGen, Const.Kernel.AllocateChildNodes, m_indirectDispatchArgsBuffer);
}
SetComputeNodeDepth(VoxelNodeDepth);
ComputeManager.Dispatch(s_computeVoxelGen, Const.Kernel.UpdateVoxelIndirectDispatchArgs, 1, 1, 1);
switch (RenderModeCategory)
{
case RenderModeCategoryEnum.Mesh:
case RenderModeCategoryEnum.Splats:
case RenderModeCategoryEnum.Decal:
switch (MeshingMode)
{
case MeshingModeEnum.MarchingCubes:
switch (RenderMode)
{
case RenderModeEnum.FlatMesh:
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.GenerateFlatMarchingCubesMesh2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.GenerateFlatMarchingCubesMesh, m_indirectDispatchArgsBuffer);
if (ShouldDoAutoSmoothing)
{
ComputeManager.Dispatch(s_computeMarchingCubes, Const.Kernel.UpdateMarchingCubesAutoSmoothIndirectDispatchArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.MarchingCubesUpdateAutoSmooth, m_indirectDispatchArgsBuffer);
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.MarchingCubesComputeAutoSmooth, m_indirectDispatchArgsBuffer);
}
break;
case RenderModeEnum.SmoothMesh:
if (ShouldDoAutoSmoothing)
{
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.GenerateFlatMarchingCubesMesh, m_indirectDispatchArgsBuffer);
ComputeManager.Dispatch(s_computeMarchingCubes, Const.Kernel.UpdateMarchingCubesAutoSmoothIndirectDispatchArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.MarchingCubesUpdateAutoSmooth, m_indirectDispatchArgsBuffer);
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.MarchingCubesComputeAutoSmooth, m_indirectDispatchArgsBuffer);
}
else
{
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.GenerateSmoothMarchingCubesMesh2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.GenerateSmoothMarchingCubesMesh, m_indirectDispatchArgsBuffer);
}
break;
case RenderModeEnum.CircleSplats:
case RenderModeEnum.QuadSplats:
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.GenerateMarchingCubesSplats2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeMarchingCubes, Const.Kernel.GenerateMarchingCubesSplats, m_indirectDispatchArgsBuffer);
break;
}
break;
case MeshingModeEnum.DualQuads:
if (Enable2dMode)
{
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.GenerateDualQuads2d, m_indirectDispatchArgsBuffer);
}
else
{
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.GenerateDualQuads, m_indirectDispatchArgsBuffer);
switch (RenderMode)
{
case RenderModeEnum.FlatMesh:
// do nothing
break;
case RenderModeEnum.SmoothMesh:
ComputeManager.Dispatch(s_computeDualMeshing, Const.Kernel.UpdateDualMeshingIndirectDispatchArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingSmoothMeshNormal, m_indirectDispatchArgsBuffer);
break;
}
}
break;
case MeshingModeEnum.SurfaceNets:
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.GenerateDualQuads2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.GenerateDualQuads, m_indirectDispatchArgsBuffer);
ComputeManager.Dispatch(s_computeDualMeshing, Const.Kernel.UpdateDualMeshingIndirectDispatchArgs, 1, 1, 1);
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeSurfaceNets, Const.Kernel.SurfaceNetsMovePoint2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeSurfaceNets, Const.Kernel.SurfaceNetsMovePoint, m_indirectDispatchArgsBuffer);
switch (RenderMode)
{
case RenderModeEnum.FlatMesh:
if (ShouldDoAutoSmoothing)
{
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingUpdateAutoSmooth, m_indirectDispatchArgsBuffer);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingComputeAutoSmooth, m_indirectDispatchArgsBuffer);
}
else
{
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingFlatMeshNormal2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingFlatMeshNormal, m_indirectDispatchArgsBuffer);
}
break;
case RenderModeEnum.SmoothMesh:
if (ShouldDoAutoSmoothing)
{
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingUpdateAutoSmooth, m_indirectDispatchArgsBuffer);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingComputeAutoSmooth, m_indirectDispatchArgsBuffer);
}
else
{
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingSmoothMeshNormal2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingSmoothMeshNormal, m_indirectDispatchArgsBuffer);
}
break;
case RenderModeEnum.CircleSplats:
case RenderModeEnum.QuadSplats:
ComputeManager.Dispatch(s_computeDualMeshing, Const.Kernel.UpdateDualMeshingSplatsIndirectArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.ConvertDualMeshingSplats, m_indirectDispatchArgsBuffer);
break;
}
break;
case MeshingModeEnum.DualContouring:
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.GenerateDualQuads2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.GenerateDualQuads, m_indirectDispatchArgsBuffer);
ComputeManager.Dispatch(s_computeDualMeshing, Const.Kernel.UpdateDualMeshingIndirectDispatchArgs, 1, 1, 1);
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeDualContouring, Const.Kernel.DualContouringMovePoint2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeDualContouring, Const.Kernel.DualContouringMovePoint, m_indirectDispatchArgsBuffer);
switch (RenderMode)
{
case RenderModeEnum.FlatMesh:
if (ShouldDoAutoSmoothing)
{
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingUpdateAutoSmooth, m_indirectDispatchArgsBuffer);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingComputeAutoSmooth, m_indirectDispatchArgsBuffer);
if (EnableSmoothCorner)
{
ComputeManager.Dispatch(s_computeDualMeshing, Const.Kernel.DualMeshingUpdateSmoothCornerIndirectDispatchArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingSmoothCorner, m_indirectDispatchArgsBuffer);
}
}
else
{
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingFlatMeshNormal2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingFlatMeshNormal, m_indirectDispatchArgsBuffer);
}
break;
case RenderModeEnum.SmoothMesh:
if (ShouldDoAutoSmoothing)
{
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingUpdateAutoSmooth, m_indirectDispatchArgsBuffer);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingComputeAutoSmooth, m_indirectDispatchArgsBuffer);
if (EnableSmoothCorner)
{
ComputeManager.Dispatch(s_computeDualMeshing, Const.Kernel.DualMeshingUpdateSmoothCornerIndirectDispatchArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingSmoothCorner, m_indirectDispatchArgsBuffer);
}
}
else
{
if (Enable2dMode)
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingSmoothMeshNormal2d, m_indirectDispatchArgsBuffer);
else
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.DualMeshingSmoothMeshNormal, m_indirectDispatchArgsBuffer);
}
break;
case RenderModeEnum.CircleSplats:
case RenderModeEnum.QuadSplats:
ComputeManager.Dispatch(s_computeDualMeshing, Const.Kernel.UpdateDualMeshingSplatsIndirectArgs, 1, 1, 1);
ComputeManager.DispatchIndirect(s_computeDualMeshing, Const.Kernel.ConvertDualMeshingSplats, m_indirectDispatchArgsBuffer);
break;
}
break;
}
break;
// done in voxel gen
/*
case RenderModeCategoryEnum.RayTracedVoxels:
ComputeManager.Dispatch(s_computeRayTracedVoxels, Const.Kernel.UpdateRayTracedVoxelIndirectDispatchArgs, 1, 1, 1);
switch(RayTracedVoxelMode)
{
case RayTracedVoxelModeEnum.CubesFaceted:
ComputeManager.DispatchIndirect(s_computeRayTracedVoxels, Const.Kernel.ComputeRayTracedVoxelGenPoints, m_indirectDispatchArgsBuffer);
break;
case RayTracedVoxelModeEnum.CubesFlat:
ComputeManager.DispatchIndirect(s_computeRayTracedVoxels, Const.Kernel.ComputeRayTracedVoxelGenPointsWithNormals, m_indirectDispatchArgsBuffer);
break;
}
break;
*/
}
Profiler.EndSample();
if (MudBun.IsFreeVersion)
{
if (LockMeshIntermediateState != LockMeshIntermediateStateEnum.Idle
&& m_indirectDrawArgsBufferUsedForCompute != null)
{
int[] aIndirectDrawArgs = new int[5];
m_indirectDrawArgsBufferUsedForCompute.GetData(aIndirectDrawArgs);
aIndirectDrawArgs[0] = Mathf.Min(aIndirectDrawArgs[0], 3 * MaxMeshGenerationTrianglesFreeVersion);
m_indirectDrawArgsBufferUsedForCompute.SetData(aIndirectDrawArgs);
}
}
if (m_doRigging)
{
Profiler.BeginSample("Rigging Dispatch");
ComputeManager.SetBuffer(Const.IndirectDrawArgs, m_indirectDrawArgsBufferUsedForCompute);
ComputeManager.SetBuffer(Const.GenPoints, m_genPointsBufferUsedForCompute);
ComputeManager.SetBuffer(Const.BrushMaterials, m_brushMaterialBuffer);
ComputeManager.SetBuffer(Const.Brushes, m_brushesBuffer);
ComputeManager.SetTexture(Const.NoiseCache, NoiseCache);
ComputeManager.SetInt(Const.NumBrushes, m_numSdfBrushes);
int[] aIndirectDrawArgs = new int[5];
m_indirectDrawArgsBufferUsedForCompute.GetData(aIndirectDrawArgs);
ComputeManager.Dispatch
(
s_computeMeshLock,
Const.Kernel.RigBones,
(aIndirectDrawArgs[0] + ThreadGroupSize - 1) / ThreadGroupSize, 1, 1
);
Profiler.EndSample();
}
// only use buffer overrides once
if (m_genPointsBufferOverride != null)
m_genPointsBufferOverride = null;
if (m_indirectDrawArgsBufferOverride != null)
m_indirectDrawArgsBufferOverride = null;
UpdateActivePostCompute();
Profiler.EndSample();
}
private void ComputeCpu()
{
Profiler.BeginSample("Compute (CPU)");
// TODO
Profiler.EndSample();
}
private Mesh m_renderBoxProxy;
private void Render()
{
if (IsEditorBusy())
return;
if (m_indirectDrawArgsBufferDefault == null)
return;
if (!s_globalResourcesValid || !m_localResourcesValid)
return;
Profiler.BeginSample("Render");
ValidateRenderMaterial();
BindRenderResources();
Aabb renderBounds = RenderBounds;
if (renderBounds.IsEmpty)
{
renderBounds.Min = -Vector3.one;
renderBounds.Max = Vector3.one;
}
switch (RenderGeometryType)
{
case RenderGeometryTypeEnum.Mesh:
case RenderGeometryTypeEnum.Chunks:
Graphics.DrawProceduralIndirect
(
m_materialUsed,
new Bounds(renderBounds.Center, renderBounds.Size),
MeshTopology.Triangles,
m_indirectDrawArgsBufferDefault,
0,
null,
m_materialProps,
CastShadows,
ReceiveShadows,
gameObject.layer
);
break;
case RenderGeometryTypeEnum.BoxProxy:
MeshUtil.UpdateRenderBoxProxy(ref m_renderBoxProxy, renderBounds);
Graphics.DrawMesh
(
m_renderBoxProxy,
Matrix4x4.identity,
m_materialUsed,
gameObject.layer,
null,
0,
m_materialProps,
CastShadows,
ReceiveShadows
);
break;
}
Profiler.EndSample();
}
#endregion // end: Core
}
}