diff --git a/engine/Sandbox.Engine/Scene/Components/Terrain/Terrain.Rendering.cs b/engine/Sandbox.Engine/Scene/Components/Terrain/Terrain.Rendering.cs index d1868da6..5b32815a 100644 --- a/engine/Sandbox.Engine/Scene/Components/Terrain/Terrain.Rendering.cs +++ b/engine/Sandbox.Engine/Scene/Components/Terrain/Terrain.Rendering.cs @@ -1,4 +1,5 @@ -using System.Runtime.InteropServices; +using ExCSS; +using System.Runtime.InteropServices; using static Sandbox.ModelRenderer; namespace Sandbox; @@ -17,11 +18,54 @@ public partial class Terrain private SceneObject _so { get; set; } + /// + /// Create buffers needed for terrain rendering, set sane empties, always bound + /// + void CreateBuffers() + { + TerrainBuffer ??= new( 1 ); + MaterialsBuffer ??= new( 64 ); + + var gpuTerrain = new GPUTerrain() + { + Transform = Matrix.Identity, + TransformInv = Matrix.Identity, + HeightMapTextureID = 0, + ControlMapTextureID = 0, + Resolution = 1024, + HeightScale = 1024, + HeightBlending = false, + HeightBlendSharpness = 0 + }; + + var gpuMaterials = new GPUTerrainMaterial[64]; + for ( int i = 0; i < 64; i++ ) + { + gpuMaterials[i] = new GPUTerrainMaterial + { + BCRTextureID = 0, + NHOTextureID = 0, + UVScale = 1.0f, + Metalness = 0.0f, + NormalStrength = 1.0f, + HeightBlendStrength = 1.0f, + DisplacementScale = 0.0f, + Flags = TerrainFlags.None, + }; + } + + TerrainBuffer.SetData( new List() { gpuTerrain } ); + MaterialsBuffer.SetData( gpuMaterials ); + } + void CreateClipmapSceneObject() { if ( !Active || Application.IsHeadless ) return; + // These get created once + CreateBuffers(); + Assert.NotNull( Scene ); _so?.Delete(); @@ -48,6 +92,13 @@ public partial class Terrain // If we have no textures, push a grid texture (SUCKS) _so.Attributes.SetCombo( "D_GRID", Storage?.Materials.Count == 0 ); + _so.Attributes.Set( "Terrain", TerrainBuffer ); + _so.Attributes.Set( "TerrainMaterials", MaterialsBuffer ); + + // We want these accessible globally too, probably + Scene.RenderAttributes.Set( "Terrain", TerrainBuffer ); + Scene.RenderAttributes.Set( "TerrainMaterials", MaterialsBuffer ); + _clipMapLodLevels = ClipMapLodLevels; _clipMapLodExtentTexels = ClipMapLodExtentTexels; _subdivisionFactor = SubdivisionFactor; @@ -98,9 +149,6 @@ public partial class Terrain if ( Storage is null ) return; - if ( TerrainBuffer is null ) - TerrainBuffer = new( 1 ); - var transform = Matrix.FromTransform( WorldTransform ); var gpuTerrain = new GPUTerrain() @@ -116,10 +164,7 @@ public partial class Terrain }; // Upload to the GPU buffer - TerrainBuffer?.SetData( new List() { gpuTerrain } ); - - _so.Attributes.Set( "Terrain", TerrainBuffer ); - Scene.RenderAttributes.Set( "Terrain", TerrainBuffer ); + TerrainBuffer.SetData( new List() { gpuTerrain } ); } /// @@ -134,17 +179,8 @@ public partial class Terrain if ( Storage is null ) return; - // Support up to 32 materials for indexed splatmap - int materialCount = Math.Max( 4, Math.Min( Storage.Materials.Count, 32 ) ); - - if ( MaterialsBuffer is null || MaterialsBuffer.ElementCount != materialCount ) - { - MaterialsBuffer?.Dispose(); - MaterialsBuffer = new( materialCount ); - } - - var gpuMaterials = new GPUTerrainMaterial[materialCount]; - for ( int i = 0; i < materialCount; i++ ) + var gpuMaterials = new GPUTerrainMaterial[64]; + for ( int i = 0; i < 64; i++ ) { var layer = Storage.Materials.ElementAtOrDefault( i ); @@ -161,12 +197,9 @@ public partial class Terrain }; } - MaterialsBuffer?.SetData( gpuMaterials ); - - _so.Attributes.Set( "TerrainMaterials", MaterialsBuffer ); - Scene.RenderAttributes.Set( "TerrainMaterials", MaterialsBuffer ); + MaterialsBuffer.SetData( gpuMaterials ); // If we have no textures, push a grid texture (SUCKS) - _so.Attributes.SetCombo( "D_GRID", Storage?.Materials.Count == 0 ); + _so.Attributes.SetCombo( "D_GRID", Storage.Materials.Count == 0 ); } }