Terrain: Create buffers once with sane defaults, make sure they are always bound

This commit is contained in:
Matt Stevens
2025-12-12 12:38:53 +00:00
parent c570971a1d
commit 85802c7d35

View File

@@ -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; }
/// <summary>
/// Create buffers needed for terrain rendering, set sane empties, always bound
/// </summary>
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>() { 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>() { gpuTerrain } );
_so.Attributes.Set( "Terrain", TerrainBuffer );
Scene.RenderAttributes.Set( "Terrain", TerrainBuffer );
TerrainBuffer.SetData( new List<GPUTerrain>() { gpuTerrain } );
}
/// <summary>
@@ -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 );
}
}