last hope

This commit is contained in:
2025-01-09 06:37:12 +03:00
parent 353117f97a
commit d7678f19df
52 changed files with 1406 additions and 143 deletions

View File

@@ -15,6 +15,7 @@
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="TestUtil"/>
<InternalsVisibleTo Include="EngineTests"/>
<InternalsVisibleTo Include="PresenterConsole"/>
<InternalsVisibleTo Include="PresenterWpf"/>

View File

@@ -0,0 +1,41 @@
using Engine.Graphics;
using Engine.Input;
using Engine.Resource;
using Engine.Scene;
namespace Engine.Context;
/// <summary>
/// A context for the engine, providing access to the engine's services.
/// </summary>
public class EngineContext : IContext
{
public IInputHandler InputHandler => _engine.InputHandler!;
public IResourceManager AssetResourceManager => _engine.AssetResourceManager;
public ISceneManager SceneManager => _engine.SceneManager;
public IRenderer Renderer => _engine.Renderer;
public string DataFolder => _engine.DataFolder;
/// <summary>
/// The engine instance associated with this context.
/// </summary>
private readonly Engine _engine;
/// <summary>
/// Initializes a new instance of the <see cref="EngineContext"/> class.
/// </summary>
/// <param name="parEngine">The engine instance to use for this context.</param>
public EngineContext(Engine parEngine)
{
_engine = parEngine;
}
public void Close()
{
_engine.Close();
}
}

View File

@@ -0,0 +1,42 @@
using Engine.Graphics;
using Engine.Input;
using Engine.Resource;
using Engine.Scene;
namespace Engine.Context;
/// <summary>
/// Defines an interface for the engine's context, providing access to the engine's services.
/// </summary>
public interface IContext
{
/// <summary>
/// The input handler for the engine.
/// </summary>
public IInputHandler InputHandler { get; }
/// <summary>
/// The resource manager for the engine.
/// </summary>
public IResourceManager AssetResourceManager { get; }
/// <summary>
/// The scene manager for the engine.
/// </summary>
public ISceneManager SceneManager { get; }
/// <summary>
/// The renderer for the engine.
/// </summary>
public IRenderer Renderer { get; }
/// <summary>
/// The data folder for the engine.
/// </summary>
public string DataFolder { get; }
/// <summary>
/// Closes the engine, shutting down any running systems and freeing resources.
/// </summary>
public void Close();
}

View File

@@ -3,6 +3,7 @@ using System.Text;
using Engine.Asset;
using Engine.Asset.Font;
using Engine.Asset.Mesh;
using Engine.Context;
using Engine.Graphics;
using Engine.Graphics.Pipeline;
using Engine.Graphics.Pixel;
@@ -12,6 +13,7 @@ using Engine.Input;
using Engine.Resource;
using Engine.Resource.Loader;
using Engine.Scene;
using Engine.Util;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
@@ -33,7 +35,7 @@ public sealed class Engine
/// <summary>
/// The scene manager for managing and updating scenes.
/// </summary>
public SceneManager SceneManager { get; } = new();
public ISceneManager SceneManager => _sceneManager;
/// <summary>
/// The resource manager responsible for asset management.
@@ -87,6 +89,11 @@ public sealed class Engine
/// </summary>
internal Window Window { get; }
/// <summary>
/// The scene manager for managing and updating scenes.
/// </summary>
private readonly SceneManager _sceneManager = new();
/// <summary>
/// The logger instance used by the engine.
/// </summary>
@@ -154,6 +161,8 @@ public sealed class Engine
Renderer = new Renderer(this, parWidth, parHeight, settings);
Window = new Window(this, Renderer.NativeWindow, parHeadless);
EngineUtil.SetContext(new EngineContext(this));
}
/// <summary>
@@ -250,7 +259,7 @@ public sealed class Engine
}
}
SceneManager.Render();
_sceneManager.Render();
}
Monitor.Exit(_sceneLock);
@@ -283,7 +292,7 @@ public sealed class Engine
{
try
{
SceneManager.Update(deltaTime);
_sceneManager.Update(deltaTime);
}
catch (Exception ex)
{

View File

@@ -10,22 +10,22 @@ namespace Engine.Graphics;
/// <summary>
/// A generic renderer that supports rendering quads, meshes, and text.
/// </summary>
public class GenericRenderer : IRenderer
public class GenericRenderer : IGenericRenderer
{
/// <summary>
/// Provides functionality to render quads.
/// </summary>
public QuadRenderer QuadRenderer => _quadRenderer ??= new QuadRenderer(_engine, 1024 * 8);
public IQuadRenderer QuadRenderer => _quadRenderer ??= new QuadRenderer(_engine, 1024 * 8);
/// <summary>
/// Provides functionality to render any type of mesh.
/// </summary>
public AnyMeshRenderer AnyMeshRenderer => _anyMeshRenderer ??= new AnyMeshRenderer(_engine, 1024);
public IAnyMeshRenderer AnyMeshRenderer => _anyMeshRenderer ??= new AnyMeshRenderer(_engine, 1024);
/// <summary>
/// Provides functionality to render text.
/// </summary>
public TextRenderer TextRenderer => _textRenderer ??= new TextRenderer(_engine, 1024 * 8);
public ITextRenderer TextRenderer => _textRenderer ??= new TextRenderer(_engine, 1024 * 8);
/// <summary>
/// The framebuffer used for rendering.
@@ -73,13 +73,19 @@ public class GenericRenderer : IRenderer
.Build();
}
/// <inheritdoc/>
/// <summary>
/// Prepares the renderer for a new frame.
/// </summary>
public void StartFrame()
{
_frameStarted = true;
}
/// <inheritdoc/>
/// <summary>
/// Finalizes the rendering pipeline for the current frame.
/// </summary>
/// <param name="parProjectionMatrix">The projection matrix to use for rendering.</param>
/// <param name="parViewMatrix">The view matrix to use for rendering.</param>
public void EndFrame(in Matrix4 parProjectionMatrix, in Matrix4 parViewMatrix)
{
if (!_frameStarted)
@@ -115,7 +121,11 @@ public class GenericRenderer : IRenderer
_frameStarted = false;
}
/// <inheritdoc/>
/// <summary>
/// Resizes the renderer to accommodate changes in viewport dimensions.
/// </summary>
/// <param name="parWidth">The new width of the viewport.</param>
/// <param name="parHeight">The new height of the viewport.</param>
public void Resize(int parWidth, int parHeight)
{
_framebuffer.Resize(parWidth, parHeight);

View File

@@ -0,0 +1,26 @@
using Engine.Graphics.Render.Mesh;
using Engine.Graphics.Render.Quad;
using Engine.Graphics.Render.Text;
namespace Engine.Graphics;
/// <summary>
/// Interface defining the essential functionality for a renderer.
/// </summary>
public interface IGenericRenderer
{
/// <summary>
/// Provides functionality to render quads.
/// </summary>
public IQuadRenderer QuadRenderer { get; }
/// <summary>
/// Provides functionality to render any type of mesh.
/// </summary>
public IAnyMeshRenderer AnyMeshRenderer { get; }
/// <summary>
/// Provides functionality to render text.
/// </summary>
public ITextRenderer TextRenderer { get; }
}

View File

@@ -1,28 +1,14 @@
using OpenTK.Mathematics;
using Engine.Graphics.Pipeline;
namespace Engine.Graphics;
/// <summary>
/// Interface defining the essential functionality for a renderer.
/// </summary>
internal interface IRenderer
public interface IRenderer
{
/// <summary>
/// Prepares the renderer for a new frame.
/// Retrieves the renderer for the specified render layer.
/// </summary>
public void StartFrame();
/// <summary>
/// Finalizes the rendering pipeline for the current frame.
/// </summary>
/// <param name="parProjectionMatrix">The projection matrix to use for rendering.</param>
/// <param name="parViewMatrix">The view matrix to use for rendering.</param>
public void EndFrame(in Matrix4 parProjectionMatrix, in Matrix4 parViewMatrix);
/// <summary>
/// Resizes the renderer to accommodate changes in viewport dimensions.
/// </summary>
/// <param name="parWidth">The new width of the viewport.</param>
/// <param name="parHeight">The new height of the viewport.</param>
public void Resize(int parWidth, int parHeight);
/// <param name="parRenderLayer">The render layer to retrieve.</param>
/// <returns>The <see cref="GenericRenderer"/> for the specified render layer.</returns>
/// <exception cref="InvalidOperationException">Thrown if the render layer does not exist.</exception>
public IGenericRenderer this[RenderLayer parRenderLayer] { get; }
}

View File

@@ -7,7 +7,7 @@ namespace Engine.Graphics.Render.Mesh;
/// A renderer class that manages multiple meshes and delegates rendering to individual mesh renderers.
/// Handles batching of mesh instances and ensures that only the necessary mesh renderers are created.
/// </summary>
public class AnyMeshRenderer
public class AnyMeshRenderer : IAnyMeshRenderer
{
/// <summary>
/// A dictionary that maps each mesh to its corresponding <see cref="MeshRenderer"/>.
@@ -40,14 +40,8 @@ public class AnyMeshRenderer
_program = parEngine.EngineResourceManager.Load<Program>("shader/mesh");
}
/// <summary>
/// Commits an instance of a mesh to the renderer, adding it to the render queue with the specified model matrix and optional texture.
/// If the mesh is not already being tracked, a new <see cref="MeshRenderer"/> will be created for it.
/// </summary>
/// <param name="parMesh">The mesh to render.</param>
/// <param name="parModelMatrix">The model transformation matrix to apply to the mesh.</param>
/// <param name="parAlbedo">An optional texture to apply to the mesh. If null, no texture is applied.</param>
public void Commit(Asset.Mesh.Mesh parMesh, Matrix4 parModelMatrix, Texture.Texture? parAlbedo = null)
/// <inheritdoc/>
public void Commit(Asset.Mesh.Mesh parMesh, in Matrix4 parModelMatrix, Texture.Texture? parAlbedo = null)
{
if (_meshRenderers.TryGetValue(parMesh, out var meshRenderer))
{

View File

@@ -0,0 +1,18 @@
using OpenTK.Mathematics;
namespace Engine.Graphics.Render.Mesh;
/// <summary>
/// Defines an interface for a renderer that can render any type of mesh.
/// </summary>
public interface IAnyMeshRenderer
{
/// <summary>
/// Commits an instance of a mesh to the renderer, adding it to the render queue with the specified model matrix and optional texture.
/// If the mesh is not already being tracked, a new <see cref="MeshRenderer"/> will be created for it.
/// </summary>
/// <param name="parMesh">The mesh to render.</param>
/// <param name="parModelMatrix">The model transformation matrix to apply to the mesh.</param>
/// <param name="parAlbedo">An optional texture to apply to the mesh. If null, no texture is applied.</param>
public void Commit(Asset.Mesh.Mesh parMesh, in Matrix4 parModelMatrix, Texture.Texture? parAlbedo = null);
}

View File

@@ -52,7 +52,7 @@ public class MeshRenderer : InstancedRenderer<Asset.Mesh.Mesh.Vertex, MeshInstan
/// </summary>
/// <param name="parModelMatrix">The model transformation matrix for this instance.</param>
/// <param name="parTexture">An optional texture to apply to the mesh. If null, no texture is applied.</param>
public void Commit(Matrix4 parModelMatrix, Texture.Texture? parTexture = null)
public void Commit(in Matrix4 parModelMatrix, Texture.Texture? parTexture = null)
{
if (_queuedInstanceCount >= _instanceCount)
{

View File

@@ -0,0 +1,17 @@
using OpenTK.Mathematics;
namespace Engine.Graphics.Render.Quad;
/// <summary>
/// Defines an interface for a renderer that can render quads.
/// </summary>
public interface IQuadRenderer
{
/// <summary>
/// Commits an instance to the renderer, adding it to the queue with the specified model matrix, color, and optional texture.
/// </summary>
/// <param name="parModelMatrix">The model transformation matrix for this instance.</param>
/// <param name="parColor">The color to apply to this instance.</param>
/// <param name="parTexture">An optional texture to apply to the quad. If null, no texture is applied.</param>
public void Commit(in Matrix4 parModelMatrix, in Vector4 parColor, Texture.Texture? parTexture = null);
}

View File

@@ -9,7 +9,7 @@ namespace Engine.Graphics.Render.Quad;
/// A renderer class for rendering quadrilaterals (quads) using instancing.
/// Supports dynamic texture binding and manages the state for rendering multiple instances of quads.
/// </summary>
public class QuadRenderer : InstancedRenderer<QuadCommonVertex, QuadInstanceVertex>
public class QuadRenderer : InstancedRenderer<QuadCommonVertex, QuadInstanceVertex>, IQuadRenderer
{
/// <summary>
/// Maps textures to texture units with a limit of 16 texture units.
@@ -47,12 +47,7 @@ public class QuadRenderer : InstancedRenderer<QuadCommonVertex, QuadInstanceVert
{
}
/// <summary>
/// Commits an instance to the renderer, adding it to the queue with the specified model matrix, color, and optional texture.
/// </summary>
/// <param name="parModelMatrix">The model transformation matrix for this instance.</param>
/// <param name="parColor">The color to apply to this instance.</param>
/// <param name="parTexture">An optional texture to apply to the quad. If null, no texture is applied.</param>
/// <inheritdoc/>
public void Commit(in Matrix4 parModelMatrix, in Vector4 parColor, Texture.Texture? parTexture = null)
{
if (_queuedInstanceCount >= _instanceCount)

View File

@@ -0,0 +1,19 @@
using Engine.Asset.Font;
using OpenTK.Mathematics;
namespace Engine.Graphics.Render.Text;
/// <summary>
/// Defines an interface for a renderer that can render text.
/// </summary>
public interface ITextRenderer
{
/// <summary>
/// Commits a string of text to the renderer, creating the necessary glyphs and adding them to the render queue.
/// </summary>
/// <param name="parFont">The font to use for rendering the text.</param>
/// <param name="parText">The text string to render.</param>
/// <param name="parColor">The color to apply to the text.</param>
/// <param name="parModelMatrix">The model transformation matrix to apply to the text.</param>
public void Commit(Font parFont, string parText, in Vector4 parColor, in Matrix4 parModelMatrix);
}

View File

@@ -11,7 +11,7 @@ namespace Engine.Graphics.Render.Text;
/// A renderer class for rendering text using glyphs from a font atlas.
/// Handles dynamic font rendering with support for textures.
/// </summary>
public class TextRenderer
public class TextRenderer : ITextRenderer
{
/// <summary>
/// The shader program used for rendering the text.
@@ -80,14 +80,8 @@ public class TextRenderer
_vertexArray.BindVertexBuffer(_glyphVertexBuffer);
}
/// <summary>
/// Commits a string of text to the renderer, creating the necessary glyphs and adding them to the render queue.
/// </summary>
/// <param name="parFont">The font to use for rendering the text.</param>
/// <param name="parText">The text string to render.</param>
/// <param name="parColor">The color to apply to the text.</param>
/// <param name="parModelMatrix">The model transformation matrix to apply to the text.</param>
public void Commit(Font parFont, string parText, Vector4 parColor, in Matrix4 parModelMatrix)
/// <inheritdoc/>
public void Commit(Font parFont, string parText, in Vector4 parColor, in Matrix4 parModelMatrix)
{
if (_queuedCharacterCount >= _characterCount)
{

View File

@@ -10,7 +10,7 @@ namespace Engine.Graphics;
/// <summary>
/// Handles the rendering pipeline, manages render layers, and provides tools for rendering graphics in the engine.
/// </summary>
public class Renderer
public class Renderer : IRenderer
{
/// <summary>
/// The width of the viewport.
@@ -89,13 +89,8 @@ public class Renderer
}
}
/// <summary>
/// Retrieves the renderer for the specified render layer.
/// </summary>
/// <param name="parRenderLayer">The render layer to retrieve.</param>
/// <returns>The <see cref="GenericRenderer"/> for the specified render layer.</returns>
/// <exception cref="InvalidOperationException">Thrown if the render layer does not exist.</exception>
public GenericRenderer this[RenderLayer parRenderLayer]
/// <inheritdoc/>
public IGenericRenderer this[RenderLayer parRenderLayer]
{
get
{

View File

@@ -1,5 +1,6 @@
using Engine.Graphics.Pipeline;
using Engine.Graphics.Texture;
using Engine.Util;
using OpenTK.Mathematics;
namespace Engine.Scene.Component.BuiltIn.Renderer;
@@ -32,7 +33,7 @@ public class Box2DRenderer : Component
/// <inheritdoc/>
public override void Render()
{
Engine.Instance.Renderer[RenderLayer].QuadRenderer
EngineUtil.Renderer[RenderLayer].QuadRenderer
.Commit(GameObject.Transform.FullTransformMatrix, Color, Texture);
}
}

View File

@@ -1,6 +1,7 @@
using Engine.Asset.Mesh;
using Engine.Graphics.Pipeline;
using Engine.Graphics.Texture;
using Engine.Util;
namespace Engine.Scene.Component.BuiltIn.Renderer;
@@ -27,7 +28,7 @@ public class MeshRenderer : Component
/// <inheritdoc/>
public override void Render()
{
Engine.Instance.Renderer[RenderLayer].AnyMeshRenderer
EngineUtil.Renderer[RenderLayer].AnyMeshRenderer
.Commit(Mesh, GameObject.Transform.FullTransformMatrix, Albedo);
}
}

View File

@@ -1,5 +1,6 @@
using Engine.Asset.Font;
using Engine.Graphics.Pipeline;
using Engine.Util;
using OpenTK.Mathematics;
namespace Engine.Scene.Component.BuiltIn.Renderer;
@@ -12,7 +13,7 @@ public class TextRenderer : Component
/// <summary>
/// The font used for rendering the text.
/// </summary>
public Font Font { get; set; } = null!;
public Font? Font { get; set; }
/// <summary>
/// The color of the text.
@@ -37,12 +38,12 @@ public class TextRenderer : Component
/// <inheritdoc/>
public override void Render()
{
if (Text == null)
if (Text == null || Font == null)
{
return;
}
Engine.Instance.Renderer[RenderLayer].TextRenderer
EngineUtil.Renderer[RenderLayer].TextRenderer
.Commit(Font, Text, Color, GameObject.Transform.FullTransformMatrix);
}
}

View File

@@ -0,0 +1,18 @@
namespace Engine.Scene;
/// <summary>
/// Defines an interface for a scene manager that handles the current scene and scene transitions.
/// </summary>
public interface ISceneManager
{
/// <summary>
/// The current scene, or null if no scene is active.
/// </summary>
public Scene? CurrentScene { get; }
/// <summary>
/// Transitions to the specified scene.
/// </summary>
/// <param name="parScene">The generator function for the scene to transition to.</param>
public void TransitionTo(Func<Scene>? parScene);
}

View File

@@ -17,7 +17,7 @@ public class Scene : IUpdate, IRender
/// <summary>
/// The time scale for updating the scene. A value of 1.0 means normal speed.
/// </summary>
public float TimeScale { get; set; } = 1.0f;
public double TimeScale { get; set; } = 1.0;
/// <summary>
/// A hierarchy of game objects in the scene.
@@ -206,7 +206,7 @@ public class Scene : IUpdate, IRender
/// <summary>
/// Processes changes in the hierarchy and scene actions.
/// </summary>
private void ProcessChanges()
internal void ProcessChanges()
{
Hierarchy.ProcessChanges();

View File

@@ -3,7 +3,7 @@
/// <summary>
/// Manages the current scene in the game, handles scene transitions, and facilitates updating and rendering the current scene.
/// </summary>
public class SceneManager : IUpdate, IRender
public class SceneManager : ISceneManager, IUpdate, IRender
{
/// <summary>
/// The current scene being managed by the scene manager.

View File

@@ -1,4 +1,6 @@
using Engine.Input;
using Engine.Context;
using Engine.Graphics;
using Engine.Input;
using Engine.Resource;
using Engine.Scene;
@@ -13,38 +15,47 @@ public static class EngineUtil
/// <summary>
/// The engine's input handler, which processes user input.
/// </summary>
public static IInputHandler InputHandler => Engine.Instance.InputHandler!;
public static IInputHandler InputHandler => CONTEXT_INSTANCE.InputHandler;
/// <summary>
/// The engine's scene manager, which handles the current scene and scene transitions.
/// </summary>
public static SceneManager SceneManager => Engine.Instance.SceneManager;
public static ISceneManager SceneManager => CONTEXT_INSTANCE.SceneManager;
/// <summary>
/// The engine's asset resource manager, which handles loading and caching of assets.
/// </summary>
public static IResourceManager AssetResourceManager => Engine.Instance.AssetResourceManager;
public static IResourceManager AssetResourceManager => CONTEXT_INSTANCE.AssetResourceManager;
/// <summary>
/// The engine's renderer, which handles rendering operations.
/// </summary>
public static IRenderer Renderer => CONTEXT_INSTANCE.Renderer;
/// <summary>
/// The engine's data folder, which contains assets and other data files.
/// </summary>
public static string DataFolder => Engine.Instance.DataFolder;
/// <summary>
/// Creates a game object and adds it to the current scene.
/// </summary>
/// <param name="parGameObject">The game object to be added to the scene.</param>
public static void CreateObject(GameObject parGameObject)
{
var scene = Engine.Instance.SceneManager.CurrentScene!;
scene.Add(parGameObject);
}
public static string DataFolder => CONTEXT_INSTANCE.DataFolder;
/// <summary>
/// Closes the engine, shutting down any running systems and freeing resources.
/// </summary>
public static void Close()
{
Engine.Instance.Close();
CONTEXT_INSTANCE.Close();
}
/// <summary>
/// The engine's context, which provides access to the engine's services.
/// </summary>
private static IContext CONTEXT_INSTANCE;
/// <summary>
/// Sets the engine's context, allowing access to the engine's services.
/// </summary>
/// <param name="parContext">The context to use for the engine.</param>
internal static void SetContext(IContext parContext)
{
CONTEXT_INSTANCE = parContext;
}
}