Render extraction system & ECS/graphics refactor
Introduced RenderExtractionSystem for entity-based render data extraction. Added MeshInstance and MeshPalette components with shadow casting support. Refactored QueryBuilder API, SharedComponentStore, and component registration for clarity and flexibility. Updated SystemManager and SystemGroup to use SystemAPI. Replaced RenderingConfig with GraphicsEngineDesc/RenderSystemDesc. RenderFrame now uses CPU/GPU fence values for sync. Removed Camera.cs in favor of ECS-based rendering. Improved Material, RenderingLayerMask, Mesh, and RenderList APIs. Updated package references and fixed naming, error handling, and disposal issues.
This commit is contained in:
9
src/Runtime/Ghost.Engine/Common.cs
Normal file
9
src/Runtime/Ghost.Engine/Common.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Ghost.Engine;
|
||||
|
||||
public enum ShadowCastingMode
|
||||
{
|
||||
Off,
|
||||
On,
|
||||
TwoSided,
|
||||
ShadowsOnly
|
||||
}
|
||||
47
src/Runtime/Ghost.Engine/Components/MeshInstance.cs
Normal file
47
src/Runtime/Ghost.Engine/Components/MeshInstance.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Entities;
|
||||
using Ghost.Graphics.Core;
|
||||
using Misaki.HighPerformance.LowLevel.Collections;
|
||||
|
||||
namespace Ghost.Engine.Components;
|
||||
|
||||
public struct MeshPalette : ISharedComponent, IEquatable<MeshPalette>
|
||||
{
|
||||
public UnsafeArray<Handle<Mesh>> meshes;
|
||||
public UnsafeArray<Handle<Material>> materials;
|
||||
|
||||
public bool Equals(MeshPalette other)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is MeshPalette palette && Equals(palette);
|
||||
}
|
||||
|
||||
public static bool operator ==(MeshPalette left, MeshPalette right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
public static bool operator !=(MeshPalette left, MeshPalette right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
}
|
||||
|
||||
public struct MeshInstance : IComponent
|
||||
{
|
||||
public int meshIndex;
|
||||
public int materialIndex;
|
||||
public ShadowCastingMode shadowCastingMode;
|
||||
public RenderingLayerMask renderingLayerMask;
|
||||
public byte subMeshIndex;
|
||||
public bool staticShadowCaster;
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using Ghost.Entities;
|
||||
using Ghost.Graphics;
|
||||
using Ghost.Graphics.RHI;
|
||||
using Misaki.HighPerformance.Jobs;
|
||||
|
||||
namespace Ghost.Engine;
|
||||
@@ -30,7 +29,7 @@ internal sealed partial class EngineCore : IEngineContext
|
||||
_jobScheduler = new JobScheduler(Environment.ProcessorCount - 2); // We -2 here, one for main thread, one for render thread
|
||||
|
||||
// TODO: Remove the windows dependency from RenderSystem.
|
||||
var renderingConfig = new RenderingConfig
|
||||
var renderingConfig = new RenderSystemDesc
|
||||
{
|
||||
FrameBufferCount = 2,
|
||||
GraphicsAPI = GraphicsAPI.Direct3D12,
|
||||
@@ -49,4 +48,4 @@ internal sealed partial class EngineCore : IEngineContext
|
||||
{
|
||||
_jobScheduler.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
62
src/Runtime/Ghost.Engine/Systems/RenderExtractionSystem.cs
Normal file
62
src/Runtime/Ghost.Engine/Systems/RenderExtractionSystem.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Ghost.Core;
|
||||
using Ghost.Engine.Components;
|
||||
using Ghost.Entities;
|
||||
using Ghost.Graphics.Core;
|
||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
|
||||
namespace Ghost.Engine.Systems;
|
||||
|
||||
public class RenderExtractionSystem : ISystem
|
||||
{
|
||||
private Identifier<EntityQuery> _queryID;
|
||||
|
||||
public void Initialize(ref readonly SystemAPI systemAPI)
|
||||
{
|
||||
_queryID = new QueryBuilder()
|
||||
// TODO: We also need to filter by MeshPalette.
|
||||
.WithAll<MeshInstance, LocalToWorld>()
|
||||
.Build(systemAPI.World);
|
||||
}
|
||||
|
||||
public void Update(ref readonly SystemAPI systemAPI)
|
||||
{
|
||||
if (_queryID.IsInvalid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ref var query = ref systemAPI.World.ComponentManager.GetEntityQueryReference(_queryID);
|
||||
var renderList = new RenderList(1, 64, Allocator.Temp);
|
||||
|
||||
// TODO: We should extract the render record for each camera because different cameras may have different culling results.
|
||||
foreach (var chunk in query.GetChunkIterator())
|
||||
{
|
||||
var meshInstances = chunk.GetComponentData<MeshInstance>();
|
||||
var localToWorlds = chunk.GetComponentData<LocalToWorld>();
|
||||
|
||||
for (int i = 0; i < chunk.Count; i++)
|
||||
{
|
||||
ref readonly var meshInstance = ref meshInstances[i];
|
||||
ref readonly var localToWorld = ref localToWorlds[i];
|
||||
|
||||
renderList.Add(new RenderRecord
|
||||
{
|
||||
localToWorld = localToWorld.matrix,
|
||||
// TODO: Get mesh and material from palette. This requires some changes to ISharedComponent since it's now fully functional right now.
|
||||
// mesh = meshInstance.meshIndex,
|
||||
// material = meshInstance.materialIndex,
|
||||
renderingLayerMask = meshInstance.renderingLayerMask,
|
||||
subMeshIndex = meshInstance.subMeshIndex,
|
||||
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Send render list to render pipeline.
|
||||
}
|
||||
|
||||
public void Cleanup(ref readonly SystemAPI systemAPI)
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user