From f16fbc3984ee74f6770b33f59fdfe9ce41e54a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Fri, 24 Mar 2023 22:48:55 +0100 Subject: [PATCH] Separated window for game and editor --- .../src/EditWindows/GameViewportWindow.bf | 106 +++++++ .../src/EditWindows/SceneViewportWindow.bf | 84 +++--- GlitchyEditor/src/Editor.bf | 9 +- GlitchyEditor/src/EditorLayer.bf | 83 +++++- GlitchyEngine/src/World/Scene.bf | 262 +++--------------- GlitchyEngine/src/World/SceneRenderer.bf | 220 +++++++++++++++ 6 files changed, 493 insertions(+), 271 deletions(-) create mode 100644 GlitchyEditor/src/EditWindows/GameViewportWindow.bf create mode 100644 GlitchyEngine/src/World/SceneRenderer.bf diff --git a/GlitchyEditor/src/EditWindows/GameViewportWindow.bf b/GlitchyEditor/src/EditWindows/GameViewportWindow.bf new file mode 100644 index 0000000..271e7bf --- /dev/null +++ b/GlitchyEditor/src/EditWindows/GameViewportWindow.bf @@ -0,0 +1,106 @@ +using System; +using ImGui; +using GlitchyEngine.Renderer; +using GlitchyEngine.Math; +using GlitchyEngine; +using GlitchyEngine.World; +using ImGuizmo; +using GlitchyEngine.Events; + +namespace GlitchyEditor.EditWindows +{ + class GameViewportWindow : EditorWindow + { + public const String s_WindowTitle = "Game"; + + private ImGui.Vec2 _oldViewportSize = .(100, 100); + private bool _viewPortChanged; + + private bool _visible; + + private RenderTargetGroup _renderTarget ~ _?.ReleaseRef(); + + public Vector2 ViewportSize => (Vector2)_oldViewportSize; + // Occurs when the viewport is resized. + public Event> ViewportSizeChanged ~ _.Dispose(); + // Occurs when an entity was clicked. + public Event> EntityClicked ~ _.Dispose(); + + /// The render target that is shown in the viewport window. + public RenderTargetGroup RenderTarget + { + get => _renderTarget; + set + { + if(_renderTarget == value) + return; + + SetReference!(_renderTarget, value); + } + } + + public bool Visible => _visible; + + public this(Editor editor) + { + _editor = editor; + } + + protected override void InternalShow() + { + ImGui.PushStyleVar(.WindowPadding, ImGui.Vec2(1, 1)); + defer ImGui.PopStyleVar(); + + if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar)) + { + ImGui.End(); + + _visible = false; + return; + } + + _visible = true; + + let viewportSize = ImGui.GetContentRegionAvail(); + + if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton)) + { + let currentWindow = ImGui.GetCurrentWindow(); + ImGui.FocusWindow(currentWindow); + } + + _hasFocus = ImGui.IsWindowFocused(); + + if(_renderTarget != null) + { + ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize); + } + + ImGui.End(); + + if(_oldViewportSize != viewportSize) + { + ViewportSizeChanged.Invoke(this, (Vector2)viewportSize); + _viewPortChanged = true; + _oldViewportSize = viewportSize; + } + } + + /// Provides the ImGui Drop target and handles dropped payload. + private void HandleDropTarget() + { + if (ImGui.BeginDragDropTarget()) + { + ImGui.Payload* payload = ImGui.AcceptDragDropPayload("CONTENT_BROWSER_ITEM"); + + if (payload != null) + { + StringView path = .((char8*)payload.Data, (int)payload.DataSize); + _editor.RequestOpenScene(this, path); + } + + ImGui.EndDragDropTarget(); + } + } + } +} diff --git a/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf b/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf index f163d05..9eb428e 100644 --- a/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf +++ b/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf @@ -27,6 +27,8 @@ namespace GlitchyEditor.EditWindows private float _angleSnap = 45.0f; private bool _doSnap = false; + private bool _visible; + public uint32 SelectedEntityId {get; private set; } public bool SelectionChanged { get; private set; } @@ -52,6 +54,8 @@ namespace GlitchyEditor.EditWindows /// Gets or sets whether the editor functionality (gizmo, picking etc.) is enabled. public bool EditorMode { get; set; } = true + public bool Visible => _visible; + public this(Editor editor) { _editor = editor; @@ -65,9 +69,13 @@ namespace GlitchyEditor.EditWindows if(!ImGui.Begin(s_WindowTitle, &_open, .NoScrollbar | .MenuBar)) { ImGui.End(); + + _visible = false; return; } + _visible = true; + let viewportSize = ImGui.GetContentRegionAvail(); if(ImGui.IsWindowHovered() && Input.IsMouseButtonPressing(.RightButton)) @@ -78,30 +86,27 @@ namespace GlitchyEditor.EditWindows _hasFocus = ImGui.IsWindowFocused(); - if (EditorMode) + ShowMenuBar(); + + if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus) + WrapMouseInViewport(); + + // If we wrapped this frame we weren't hovering because the cursor has to be be out of bounds to wrap + _editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor); + + if (_hasFocus && !_editor.CurrentCamera.InUse) { - ShowMenuBar(); - - if (_editor.CurrentCamera.[Friend]BindMouse && _hasFocus) - WrapMouseInViewport(); + if (Input.IsKeyPressing(.Q)) + _gizmoType = .TRANSLATE; + if (Input.IsKeyPressing(.W)) + _gizmoType = .ROTATE; + if (Input.IsKeyPressing(.E)) + _gizmoType = .SCALE; - // If we wrapped this frame we weren't hovering because the cursor has to be be out of bounds to wrap - _editor.CurrentCamera.AllowMove = _hasFocus && (ImGui.IsWindowHovered() || _wrappedCursor); - - if (_hasFocus && !_editor.CurrentCamera.InUse) - { - if (Input.IsKeyPressing(.Q)) - _gizmoType = .TRANSLATE; - if (Input.IsKeyPressing(.W)) - _gizmoType = .ROTATE; - if (Input.IsKeyPressing(.E)) - _gizmoType = .SCALE; - - if (Input.IsKeyPressing(.G)) - _gizmoMode = .WORLD; - if (Input.IsKeyPressing(.L)) - _gizmoMode = .LOCAL; - } + if (Input.IsKeyPressing(.G)) + _gizmoMode = .WORLD; + if (Input.IsKeyPressing(.L)) + _gizmoMode = .LOCAL; } if(_renderTarget != null) @@ -111,14 +116,11 @@ namespace GlitchyEditor.EditWindows //ImGui.Image(_editor.CurrentScene.[Friend]_compositeTarget.GetViewBinding(0), viewportSize); } - if (EditorMode) - { - HandleDropTarget(); - - bool gizmoUsed = DrawImGuizmo(viewportSize); - - MousePicking(viewportSize, gizmoUsed); - } + HandleDropTarget(); + + bool gizmoUsed = DrawImGuizmo(viewportSize); + + MousePicking(viewportSize, gizmoUsed); ImGui.End(); @@ -156,25 +158,27 @@ namespace GlitchyEditor.EditWindows let winPos = (Vector2)ImGui.GetWindowPos(); let regionMin = winPos + (Vector2)ImGui.GetWindowContentRegionMin(); let regionMax = winPos + (Vector2)ImGui.GetWindowContentRegionMax(); - + + ImGui.DrawRect((.)regionMin, (.)regionMax, .(0, 255, 0)); + Vector2 newMousePos = mousePos; - if (mousePos.X < regionMin.X) + if (mousePos.X < regionMin.X + 1) { - newMousePos.X = regionMax.X - 1; + newMousePos.X = regionMax.X - 2; } else if (mousePos.X > regionMax.X - 1) { - newMousePos.X = regionMin.X + 1; + newMousePos.X = regionMin.X + 2; } - if (mousePos.Y < regionMin.Y) + if (mousePos.Y < regionMin.Y + 1) { - newMousePos.Y = regionMax.Y - 1; + newMousePos.Y = regionMax.Y - 100; } else if (mousePos.Y > regionMax.Y - 1) { - newMousePos.Y = regionMin.Y + 1; + newMousePos.Y = regionMin.Y + 10; } if (newMousePos != mousePos) @@ -193,8 +197,8 @@ namespace GlitchyEditor.EditWindows { Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin(); - int rtWidth = _editor.CurrentScene.[Friend]_compositeTarget.Width; - int rtHeight = _editor.CurrentScene.[Friend]_compositeTarget.Height; + int rtWidth = _editor.EditorSceneRenderer.CompositeTarget.Width; + int rtHeight = _editor.EditorSceneRenderer.CompositeTarget.Height; if (Input.IsMouseButtonPressing(.LeftButton) && ImGui.IsWindowHovered() && !gizmoUsed && !_editor.CurrentCamera.InUse && @@ -204,7 +208,7 @@ namespace GlitchyEditor.EditWindows { uint32 id = uint32.MaxValue; - _editor.CurrentScene.[Friend]_compositeTarget.GetData(&id, 1, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1); + _editor.EditorSceneRenderer.CompositeTarget.GetData(&id, 1, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1); SelectionChanged = true; SelectedEntityId = id; diff --git a/GlitchyEditor/src/Editor.bf b/GlitchyEditor/src/Editor.bf index e9bb3c0..6028201 100644 --- a/GlitchyEditor/src/Editor.bf +++ b/GlitchyEditor/src/Editor.bf @@ -17,7 +17,8 @@ namespace GlitchyEditor private EntityHierarchyWindow _entityHierarchyWindow ~ delete _; private ComponentEditWindow _componentEditWindow ~ delete _; - private SceneViewportWindow _sceneViewportWindow~ delete _; + private SceneViewportWindow _sceneViewportWindow ~ delete _; + private GameViewportWindow _gameViewportWindow ~ delete _; private ContentBrowserWindow _contentBrowserWindow ~ delete _; private PropertiesWindow _propertiesWindow ~ delete _; @@ -39,6 +40,7 @@ namespace GlitchyEditor public EntityHierarchyWindow EntityHierarchyWindow => _entityHierarchyWindow; public ComponentEditWindow ComponentEditWindow => _componentEditWindow; public SceneViewportWindow SceneViewportWindow => _sceneViewportWindow; + public GameViewportWindow GameViewportWindow => _gameViewportWindow; public ContentBrowserWindow ContentBrowserWindow => _contentBrowserWindow; public PropertiesWindow PropertiesWindow => _propertiesWindow; @@ -46,6 +48,9 @@ namespace GlitchyEditor public Event> RequestOpenScene ~ _.Dispose(); + public SceneRenderer GameSceneRenderer {get; set;} + public SceneRenderer EditorSceneRenderer {get; set;} + /// Creates a new editor for the given world public this(Scene scene, EditorContentManager contentManager) { @@ -58,6 +63,7 @@ namespace GlitchyEditor private void InitWindows() { _sceneViewportWindow = new SceneViewportWindow(this); + _gameViewportWindow = new GameViewportWindow(this); _entityHierarchyWindow = new EntityHierarchyWindow(this, _scene); _componentEditWindow = new ComponentEditWindow(_entityHierarchyWindow); _contentBrowserWindow = new ContentBrowserWindow((.)Application.Get().ContentManager); @@ -67,6 +73,7 @@ namespace GlitchyEditor public void Update() { _sceneViewportWindow.Show(); + _gameViewportWindow.Show(); _entityHierarchyWindow.Show(); _componentEditWindow.Show(); _contentBrowserWindow.Show(); diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 33bc16d..4ccb9e3 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -30,6 +30,9 @@ namespace GlitchyEditor Scene _activeScene ~ _?.ReleaseRef(); Scene _editorScene ~ _?.ReleaseRef(); + SceneRenderer _gameSceneRenderer ~ delete _; + SceneRenderer _editorSceneRenderer ~ delete _; + String _sceneFilePath = new String() ~ delete _; public String SceneFilePath @@ -47,7 +50,8 @@ namespace GlitchyEditor Editor _editor ~ delete _; RenderTargetGroup _cameraTarget ~ _.ReleaseRef(); - RenderTargetGroup _viewportTarget ~ _.ReleaseRef(); + RenderTargetGroup _editorViewportTarget ~ _.ReleaseRef(); + RenderTargetGroup _gameViewportTarget ~ _.ReleaseRef(); SettingsWindow _settingsWindow = new .() ~ delete _; @@ -83,6 +87,9 @@ namespace GlitchyEditor _editorScene = new Scene(); SetReference!(_activeScene, _editorScene); + _gameSceneRenderer = new SceneRenderer(); + _editorSceneRenderer = new SceneRenderer(); + _camera = EditorCamera(Vector3(3.5f, 1.25f, 2.75f), Quaternion.FromEulerAngles(MathHelper.ToRadians(40), MathHelper.ToRadians(25), 0), MathHelper.ToRadians(75), 0.1f, 1); _camera.RenderTarget = _cameraTarget; @@ -144,7 +151,15 @@ namespace GlitchyEditor DepthTargetDescription = .(.D24_UNorm_S8_UInt) }); - _viewportTarget = new RenderTargetGroup(.() + _editorViewportTarget = new RenderTargetGroup(.() + { + Width = 100, + Height = 100, + ColorTargetDescriptions = TargetDescription[]( + .(.R8G8B8A8_UNorm)) + }); + + _gameViewportTarget = new RenderTargetGroup(.() { Width = 100, Height = 100, @@ -167,8 +182,11 @@ namespace GlitchyEditor private void InitEditor() { _editor = new Editor(_editorScene, _contentManager); - _editor.SceneViewportWindow.ViewportSizeChanged.Add(new (s, e) => ViewportSizeChanged(s, e)); + _editor.SceneViewportWindow.ViewportSizeChanged.Add(new (s, e) => EditorViewportSizeChanged(s, e)); + _editor.GameViewportWindow.ViewportSizeChanged.Add(new (s, e) => GameViewportSizeChanged(s, e)); _editor.CurrentCamera = &_camera; + _editor.GameSceneRenderer = _gameSceneRenderer; + _editor.EditorSceneRenderer = _editorSceneRenderer; _editor.RequestOpenScene.Add(new (s, fileName) => { LoadSceneFile(fileName); @@ -177,22 +195,38 @@ namespace GlitchyEditor public override void Update(GameTime gameTime) { + Debug.Profiler.ProfileFunction!(); + _camera.Update(gameTime); _editor.CurrentScene = _activeScene; + + _activeScene.Update(gameTime, (_sceneState == .Edit) ? .Editor : .Runtime); // Clear the swapchain-buffer RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0); + + RenderCommand.SetBlendState(_alphaBlendState); + RenderCommand.SetDepthStencilState(_depthStencilState); + + if (_editor.SceneViewportWindow.Visible) + { + _editorSceneRenderer.Scene = _activeScene; - RenderCommand.Clear(_viewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0); + RenderCommand.Clear(_editorViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0); + _editorSceneRenderer.RenderEditor(gameTime, _camera, _editorViewportTarget, scope => DebugDraw3D, scope => DebugDraw2D); + } RenderCommand.SetBlendState(_alphaBlendState); RenderCommand.SetDepthStencilState(_depthStencilState); - if (_sceneState == .Edit) - _activeScene.UpdateEditor(gameTime, _camera, _viewportTarget, scope => DebugDraw3D, scope => DebugDraw2D); - else if (_sceneState == .Play) - _activeScene.UpdateRuntime(gameTime, _viewportTarget); + if (_editor.GameViewportWindow.Visible) + { + _gameSceneRenderer.Scene = _activeScene; + + RenderCommand.Clear(_gameViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0); + _gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget); + } RenderCommand.UnbindRenderTargets(); RenderCommand.SetRenderTarget(null, 0, true); @@ -301,7 +335,8 @@ namespace GlitchyEditor DrawMainMenuBar(); - _editor.SceneViewportWindow.RenderTarget = _viewportTarget; + _editor.SceneViewportWindow.RenderTarget = _editorViewportTarget; + _editor.GameViewportWindow.RenderTarget = _gameViewportTarget; _editor.Update(); @@ -381,6 +416,13 @@ namespace GlitchyEditor _sceneState = .Edit; _editor.CurrentScene = _activeScene; + + /* + * Update the viewport size because if the game windows size changed in + * "Game"-mode the updated aspect-rations will reset once we go back + * into "Editor"-mode (because Game-Mode works on a copy of the scene). + */ + GameViewportSizeChanged(null, _editor.GameViewportWindow.ViewportSize); } // Just for testing @@ -671,7 +713,7 @@ namespace GlitchyEditor return false; } - private void ViewportSizeChanged(Object sender, Vector2 viewportSize) + private void EditorViewportSizeChanged(Object sender, Vector2 viewportSize) { uint32 sizeX = (uint32)viewportSize.X; uint32 sizeY = (uint32)viewportSize.Y; @@ -679,11 +721,28 @@ namespace GlitchyEditor if(sizeX == 0 || sizeY == 0) return; - _viewportTarget.Resize(sizeX, sizeY); + _editorViewportTarget.Resize(sizeX, sizeY); _cameraTarget.Resize(sizeX, sizeY); - _activeScene.OnViewportResize(sizeX, sizeY); + //_activeScene.OnViewportResize(sizeX, sizeY); _camera.OnViewportResize(sizeX, sizeY); + + _editorSceneRenderer.OnViewportResize(sizeX, sizeY); + } + + private void GameViewportSizeChanged(Object sender, Vector2 viewportSize) + { + uint32 sizeX = (uint32)viewportSize.X; + uint32 sizeY = (uint32)viewportSize.Y; + + if(sizeX == 0 || sizeY == 0) + return; + + _gameViewportTarget.Resize(sizeX, sizeY); + + _activeScene.OnViewportResize(sizeX, sizeY); + + _gameSceneRenderer.OnViewportResize(sizeX, sizeY); } private bool OnKeyPressed(KeyPressedEvent e) diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 4cff69a..cdf6417 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -19,13 +19,6 @@ namespace GlitchyEngine.World private Dictionary _onComponentAddedHandlers = new .() ~ delete _; - private RenderTargetGroup _compositeTarget ~ _.ReleaseRef(); - - // Temporary target for camera. Needs to change as soon as we support multiple cameras - private RenderTargetGroup _cameraTarget ~ _.ReleaseRef(); - - private AssetHandle _gammaCorrectEffect; - private uint32 _viewportWidth, _viewportHeight; // Maps ids to the entities they represent. @@ -52,25 +45,6 @@ namespace GlitchyEngine.World cameraComponent.Camera.SetViewportSize(e.Scene._viewportWidth, e.Scene._viewportHeight); }); - - RenderTargetGroupDescription desc = .(100, 100, - TargetDescription[]( - RenderTargetFormat.R16G16B16A16_Float, - .(RenderTargetFormat.R32_UInt) {ClearColor = .UInt(uint32.MaxValue)}), - RenderTargetFormat.D24_UNorm_S8_UInt); - _compositeTarget = new RenderTargetGroup(desc); - - _cameraTarget = new RenderTargetGroup(.(){ - Width = 100, - Height = 100, - ColorTargetDescriptions = TargetDescription[]( - .(.R16G16B16A16_Float), - .(.R32_UInt) - ), - DepthTargetDescription = .(.D24_UNorm_S8_UInt) - }); - - _gammaCorrectEffect = Content.LoadAsset("Shaders/GammaCorrect.hlsl");//Application.Get().EffectLibrary.Load("content/Shaders/GammaCorrect.hlsl"); } public ~this() @@ -215,207 +189,62 @@ namespace GlitchyEngine.World _physicsWorld2D = null; } - public void UpdateRuntime(GameTime gameTime, RenderTargetGroup finalTarget) + public enum UpdateMode { - Debug.Profiler.ProfileRendererFunction!(); - - finalTarget.AddRef(); - - TransformSystem.Update(_ecsWorld); - - // Run scripts - for (var (entity, script) in _ecsWorld.Enumerate()) - { - if (script.Instance == null) - { - script.Instance = script.InstantiateFunction(); - script.Instance._entity = Entity(entity, this); - script.Instance.[Friend]OnCreate(); - } - - script.Instance.[Friend]OnUpdate(gameTime); - } - - // Update 2D physics - { - const int32 velocityIterations = 6; - const int32 positionIterations = 2; - const int32 particleIterations = 2; - - Box2D.World.Step(_physicsWorld2D, gameTime.DeltaTime, velocityIterations, positionIterations, particleIterations); - - // Retrieve transform from Box2D - for (var entry in _ecsWorld.Enumerate()) - { - Entity entity = .(entry.Entity, this); - - var transform = entity.Transform; - var rigidbody = entry.Component; - - b2Body* body = rigidbody.RuntimeBody; - b2Vec2 position = Box2D.Body.GetPosition(body); - float angle = Box2D.Body.GetAngle(body); - - transform.Position = .(position.x, position.y, transform.Position.Z); - transform.RotationEuler = .(transform.RotationEuler.XY, angle); - } - } - - // Find camera - Camera* primaryCamera = null; - Matrix primaryCameraTransform = default; - RenderTargetGroup renderTarget = null; - - for (var (entity, transform, camera) in _ecsWorld.Enumerate()) - { - if (camera.Primary)// && camera.RenderTarget != null) - { - primaryCamera = &camera.Camera; - primaryCameraTransform = transform.WorldTransform; - // TODO: bind render targets to cameras - // renderTarget = camera.RenderTarget..AddRef(); - } - } - - renderTarget = _cameraTarget..AddRef(); - - // 3D render - Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, _compositeTarget); - - for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate()) - { - Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); - } - - for (var (entity, transform, light) in _ecsWorld.Enumerate()) - { - Renderer.Submit(light.SceneLight, transform.WorldTransform); - } - - Renderer.EndScene(); - - renderTarget.ReleaseRef(); - - // TODO: alphablending (handle in Renderer2D) - // TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget - - RenderCommand.SetRenderTargetGroup(_compositeTarget); - RenderCommand.BindRenderTargets(); - - // Sprite renderer - Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront); - - for (var (entity, transform, sprite) in _ecsWorld.Enumerate()) - { - Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index); - } - - for (var (entity, transform, circle) in _ecsWorld.Enumerate()) - { - Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index); - } - - Renderer2D.EndScene(); - - // Gamma correct composit target and draw it into viewport - { - RenderCommand.UnbindRenderTargets(); - RenderCommand.SetRenderTargetGroup(finalTarget, false); - RenderCommand.BindRenderTargets(); - - Effect gammaEffect = Content.GetAsset(_gammaCorrectEffect); - - gammaEffect.SetTexture("Texture", _compositeTarget, 0); - // TODO: iiihhh - gammaEffect.ApplyChanges(); - gammaEffect.Bind(); - - FullscreenQuad.Draw(); - } - - finalTarget.ReleaseRef(); + Editor = 0x01, + Physics = 0x02, + Runtime = 0x04 | Physics, } - public void UpdateEditor(GameTime gameTime, EditorCamera camera, RenderTargetGroup viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D) + public void Update(GameTime gameTime, UpdateMode mode) { Debug.Profiler.ProfileRendererFunction!(); - viewportTarget.AddRef(); - TransformSystem.Update(_ecsWorld); - // 3D render - Renderer.BeginScene(camera, _compositeTarget); - - for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate()) + if (mode.HasFlag(.Runtime)) { - if (mesh.Mesh == .Invalid || meshRenderer.Material == .Invalid) - continue; - - Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); - } - - for (var (entity, transform, light) in _ecsWorld.Enumerate()) - { - Renderer.Submit(light.SceneLight, transform.WorldTransform); - } - - DebugDraw3D(); - - Renderer.EndScene(); - - // TODO: alphablending (handle in Renderer2D) - // TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget - - RenderCommand.SetRenderTargetGroup(_compositeTarget); - RenderCommand.BindRenderTargets(); - - // Sprite renderer - Renderer2D.BeginScene(camera, .BackToFront); - - for (var (entity, transform, sprite) in _ecsWorld.Enumerate()) - { - Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index); - } - - for (var (entity, transform, circle) in _ecsWorld.Enumerate()) - { - Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index); - } - - Renderer2D.DrawLine(Vector3.Zero, Vector3.Up, .Red); - Renderer2D.DrawLine(Vector3.Zero, Vector3(0, 0, 1), .Green); - Renderer2D.DrawRay(Vector3.Zero, Vector3(1, 0, 0), .Blue); - - Renderer2D.DrawRect(Vector2(2.0f, 1.0f), Vector2(1.0f, 2.0f), .Yellow); - - Renderer2D.DrawRect(Matrix.Translation(2, 2, 1) * Matrix.RotationZ(MathHelper.PiOverFour), .Purple); - - Renderer2D.EndScene(); - - Renderer2D.BeginScene(camera, .BackToFront); - - DrawDebug2D(); - - Renderer2D.EndScene(); - - // Gamma correct composit target and draw it into viewport - { - RenderCommand.UnbindRenderTargets(); - RenderCommand.SetRenderTargetGroup(viewportTarget, false); - RenderCommand.BindRenderTargets(); - - Effect gammaEffect = Content.GetAsset(_gammaCorrectEffect); - - gammaEffect.SetTexture("Texture", _compositeTarget, 0); - // TODO: iiihhh - gammaEffect.ApplyChanges(); - gammaEffect.Bind(); + // Run scripts + for (var (entity, script) in _ecsWorld.Enumerate()) + { + if (script.Instance == null) + { + script.Instance = script.InstantiateFunction(); + script.Instance._entity = Entity(entity, this); + script.Instance.[Friend]OnCreate(); + } - FullscreenQuad.Draw(); + script.Instance.[Friend]OnUpdate(gameTime); + } } + + if (mode.HasFlag(.Physics)) + { + // Update 2D physics + { + const int32 velocityIterations = 6; + const int32 positionIterations = 2; + const int32 particleIterations = 2; - viewportTarget.ReleaseRef(); + Box2D.World.Step(_physicsWorld2D, gameTime.DeltaTime, velocityIterations, positionIterations, particleIterations); + + // Retrieve transform from Box2D + for (var entry in _ecsWorld.Enumerate()) + { + Entity entity = .(entry.Entity, this); + + var transform = entity.Transform; + var rigidbody = entry.Component; + + b2Body* body = rigidbody.RuntimeBody; + b2Vec2 position = Box2D.Body.GetPosition(body); + float angle = Box2D.Body.GetAngle(body); + + transform.Position = .(position.x, position.y, transform.Position.Z); + transform.RotationEuler = .(transform.RotationEuler.XY, angle); + } + } + } } /// Creates a new Entity with the given name. @@ -479,9 +308,6 @@ namespace GlitchyEngine.World cameraComponent.Camera.SetViewportSize(width, height); } } - - _compositeTarget.Resize(_viewportWidth, _viewportHeight); - _cameraTarget.Resize(_viewportWidth, _viewportHeight); } private void OnComponentAdded(Entity entity, Type componentType, void* component) diff --git a/GlitchyEngine/src/World/SceneRenderer.bf b/GlitchyEngine/src/World/SceneRenderer.bf new file mode 100644 index 0000000..8b65406 --- /dev/null +++ b/GlitchyEngine/src/World/SceneRenderer.bf @@ -0,0 +1,220 @@ +using GlitchyEngine.Renderer; +using GlitchyEngine.Content; +using GlitchyEngine.Math; + +namespace GlitchyEngine.World; + +using internal GlitchyEngine.World; + +class SceneRenderer +{ + public Scene Scene { get; set; } + + private RenderTargetGroup _compositeTarget ~ _.ReleaseRef(); + + // Temporary target for camera. Needs to change as soon as we support multiple cameras + private RenderTargetGroup _cameraTarget ~ _.ReleaseRef(); + + private uint32 _viewportWidth; + private uint32 _viewportHeight; + + private AssetHandle _gammaCorrectEffect; + + public RenderTargetGroup CompositeTarget => _compositeTarget; + + public this() + { + RenderTargetGroupDescription desc = .(100, 100, + TargetDescription[]( + RenderTargetFormat.R16G16B16A16_Float, + .(RenderTargetFormat.R32_UInt) {ClearColor = .UInt(uint32.MaxValue)}), + RenderTargetFormat.D24_UNorm_S8_UInt); + _compositeTarget = new RenderTargetGroup(desc); + + _cameraTarget = new RenderTargetGroup(.(){ + Width = 100, + Height = 100, + ColorTargetDescriptions = TargetDescription[]( + .(.R16G16B16A16_Float), + .(.R32_UInt) + ), + DepthTargetDescription = .(.D24_UNorm_S8_UInt) + }); + + _gammaCorrectEffect = Content.LoadAsset("Shaders/GammaCorrect.hlsl");//Application.Get().EffectLibrary.Load("content/Shaders/GammaCorrect.hlsl"); + } + + /// Sets the size of the viewport into which the scene will be rendered. + public void OnViewportResize(uint32 width, uint32 height) + { + _viewportWidth = width; + _viewportHeight = height; + + _compositeTarget.Resize(_viewportWidth, _viewportHeight); + _cameraTarget.Resize(_viewportWidth, _viewportHeight); + } + + public void RenderRuntime(GameTime gameTime, RenderTargetGroup finalTarget) + { + Debug.Profiler.ProfileRendererFunction!(); + + // Find camera + Camera* primaryCamera = null; + Matrix primaryCameraTransform = default; + RenderTargetGroup renderTarget = null; + + for (var (entity, transform, camera) in Scene._ecsWorld.Enumerate()) + { + if (camera.Primary)// && camera.RenderTarget != null) + { + primaryCamera = &camera.Camera; + primaryCameraTransform = transform.WorldTransform; + // TODO: bind render targets to cameras + // renderTarget = camera.RenderTarget..AddRef(); + } + } + + if (primaryCamera == null) + return; + + finalTarget.AddRef(); + + renderTarget = _cameraTarget..AddRef(); + + // 3D render + Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, _compositeTarget); + + for (var (entity, transform, mesh, meshRenderer) in Scene._ecsWorld.Enumerate()) + { + Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); + } + + for (var (entity, transform, light) in Scene._ecsWorld.Enumerate()) + { + Renderer.Submit(light.SceneLight, transform.WorldTransform); + } + + Renderer.EndScene(); + + renderTarget.ReleaseRef(); + + // TODO: alphablending (handle in Renderer2D) + // TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget + + RenderCommand.SetRenderTargetGroup(_compositeTarget); + RenderCommand.BindRenderTargets(); + + // Sprite renderer + Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform, .BackToFront); + + for (var (entity, transform, sprite) in Scene._ecsWorld.Enumerate()) + { + Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index); + } + + for (var (entity, transform, circle) in Scene._ecsWorld.Enumerate()) + { + Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index); + } + + Renderer2D.EndScene(); + + // Gamma correct composit target and draw it into viewport + { + RenderCommand.UnbindRenderTargets(); + RenderCommand.SetRenderTargetGroup(finalTarget, false); + RenderCommand.BindRenderTargets(); + + Effect gammaEffect = Content.GetAsset(_gammaCorrectEffect); + + gammaEffect.SetTexture("Texture", _compositeTarget, 0); + // TODO: iiihhh + gammaEffect.ApplyChanges(); + gammaEffect.Bind(); + + FullscreenQuad.Draw(); + } + + finalTarget.ReleaseRef(); + } + + public void RenderEditor(GameTime gameTime, EditorCamera camera, RenderTargetGroup viewportTarget, delegate void() DebugDraw3D, delegate void() DrawDebug2D) + { + Debug.Profiler.ProfileRendererFunction!(); + + viewportTarget.AddRef(); + + // 3D render + Renderer.BeginScene(camera, _compositeTarget); + + for (var (entity, transform, mesh, meshRenderer) in Scene._ecsWorld.Enumerate()) + { + if (mesh.Mesh == .Invalid || meshRenderer.Material == .Invalid) + continue; + + Renderer.Submit(mesh.Mesh, meshRenderer.Material, entity, transform.WorldTransform); + } + + for (var (entity, transform, light) in Scene._ecsWorld.Enumerate()) + { + Renderer.Submit(light.SceneLight, transform.WorldTransform); + } + + DebugDraw3D(); + + Renderer.EndScene(); + + // TODO: alphablending (handle in Renderer2D) + // TODO: 2D-Postprocessing requires rendering into separate target instead of directly into compositeTarget + + RenderCommand.SetRenderTargetGroup(_compositeTarget); + RenderCommand.BindRenderTargets(); + + // Sprite renderer + Renderer2D.BeginScene(camera, .BackToFront); + + for (var (entity, transform, sprite) in Scene._ecsWorld.Enumerate()) + { + Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index); + } + + for (var (entity, transform, circle) in Scene._ecsWorld.Enumerate()) + { + Renderer2D.DrawCircle(transform.WorldTransform, circle, entity.Index); + } + + Renderer2D.DrawLine(Vector3.Zero, Vector3.Up, .Red); + Renderer2D.DrawLine(Vector3.Zero, Vector3(0, 0, 1), .Green); + Renderer2D.DrawRay(Vector3.Zero, Vector3(1, 0, 0), .Blue); + + Renderer2D.DrawRect(Vector2(2.0f, 1.0f), Vector2(1.0f, 2.0f), .Yellow); + + Renderer2D.DrawRect(Matrix.Translation(2, 2, 1) * Matrix.RotationZ(MathHelper.PiOverFour), .Purple); + + Renderer2D.EndScene(); + + Renderer2D.BeginScene(camera, .BackToFront); + + DrawDebug2D(); + + Renderer2D.EndScene(); + + // Gamma correct composit target and draw it into viewport + { + RenderCommand.UnbindRenderTargets(); + RenderCommand.SetRenderTargetGroup(viewportTarget, false); + RenderCommand.BindRenderTargets(); + + Effect gammaEffect = Content.GetAsset(_gammaCorrectEffect); + + gammaEffect.SetTexture("Texture", _compositeTarget, 0); + // TODO: iiihhh + gammaEffect.ApplyChanges(); + gammaEffect.Bind(); + + FullscreenQuad.Draw(); + } + + viewportTarget.ReleaseRef(); + } +}