From d212576719ba18a1ca65e6fd188a75a1d2ebe397 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20L=C3=BCbe=C3=9F?= Date: Sat, 28 May 2022 15:42:48 +0200 Subject: [PATCH] Render EntityIDs (breaks post processing) --- .../content/Shaders/spritebatch.hlsl | 34 ++++- .../src/EditWindows/SceneViewportWindow.bf | 17 +-- GlitchyEditor/src/EditorLayer.bf | 33 +++-- GlitchyEngine/src/ImGui/ImGuiLayer.bf | 2 + .../DX11/Renderer/Dx11RenderTarget.bf | 23 +++ .../Platform/DX11/Renderer/Dx11RendererAPI.bf | 25 +++- GlitchyEngine/src/Renderer/BufferVariable.bf | 3 +- GlitchyEngine/src/Renderer/FullscreenQuad.bf | 18 ++- GlitchyEngine/src/Renderer/RenderCommand.bf | 15 +- GlitchyEngine/src/Renderer/RenderTarget.bf | 25 +++- GlitchyEngine/src/Renderer/Renderer.bf | 138 +++--------------- GlitchyEngine/src/Renderer/Renderer2D.bf | 75 +++++++--- GlitchyEngine/src/Renderer/RendererAPI.bf | 2 +- GlitchyEngine/src/World/Components.bf | 4 +- GlitchyEngine/src/World/EcsEntity.bf | 4 +- GlitchyEngine/src/World/EditorCamera.bf | 4 +- GlitchyEngine/src/World/Scene.bf | 11 +- 17 files changed, 242 insertions(+), 191 deletions(-) diff --git a/GlitchyEditor/content/Shaders/spritebatch.hlsl b/GlitchyEditor/content/Shaders/spritebatch.hlsl index be544ec..3adacbf 100644 --- a/GlitchyEditor/content/Shaders/spritebatch.hlsl +++ b/GlitchyEditor/content/Shaders/spritebatch.hlsl @@ -1,3 +1,5 @@ +#define EDITOR + Texture2D Texture : register(t0); SamplerState Sampler : register(s0); @@ -13,6 +15,9 @@ struct VS_Input float4x4 Transform : TRANSFORM; float4 Color : COLOR; float4 UVTransform : TEXCOORD1; +#ifdef EDITOR + uint EntityId : ENTITYID; +#endif }; struct PS_Input @@ -20,6 +25,9 @@ struct PS_Input float4 Position : SV_Position; float2 Texcoord : TEXCOORD; float4 Color : COLOR; +#ifdef EDITOR + nointerpolation uint EntityId : ENTITYID; +#endif }; PS_Input VS(VS_Input input) @@ -30,12 +38,34 @@ PS_Input VS(VS_Input input) output.Texcoord = input.UVTransform.xy + input.UVTransform.zw * input.Texcoord; output.Color = input.Color; +#ifdef EDITOR + output.EntityId = input.EntityId; +#endif + return output; } -float4 PS(PS_Input input) : SV_Target0 +struct PS_Output { - return Texture.Sample(Sampler, input.Texcoord) * input.Color; + float4 Color : SV_Target0; +#ifdef EDITOR + uint EntityId : SV_TARGET1; +#endif +}; + +PS_Output PS(PS_Input input) +{ + PS_Output output; + + output.Color = Texture.Sample(Sampler, input.Texcoord) * input.Color; + + clip(output.Color.a - 0.001f); + +#ifdef EDITOR + output.EntityId = input.EntityId; +#endif + + return output; } #effect[VS=VS, PS=PS] \ No newline at end of file diff --git a/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf b/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf index ed29e38..05f1bfd 100644 --- a/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf +++ b/GlitchyEditor/src/EditWindows/SceneViewportWindow.bf @@ -93,7 +93,8 @@ namespace GlitchyEditor.EditWindows if(_renderTarget != null) { - ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize); + //ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize); + ImGui.Image(_editor.CurrentCamera.RenderTarget.GetViewBinding(0), viewportSize); } Vector2 relativeMouse = (Vector2)ImGui.GetMousePos() - (Vector2)ImGui.GetItemRectMin(); @@ -105,20 +106,18 @@ namespace GlitchyEditor.EditWindows relativeMouse.X < viewportSize.x && relativeMouse.Y < viewportSize.y && relativeMouse.X < x && relativeMouse.Y < y) { - uint32 id = 0; - - Renderer.[Friend]_gBuffer.Target.GetData(&id, 5, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1); - - id--; + uint32 id = uint32.MaxValue; + _editor.CurrentCamera.RenderTarget.GetData(&id, 1, (.)relativeMouse.X, (.)relativeMouse.Y, 1, 1); + //_renderTarget.GetData(&pixel, 0, ); Log.EngineLogger.Info($"{relativeMouse} || ID = {id}"); - /*if (id != uint32.MaxValue) + if (id != uint32.MaxValue) { - _editor.CurrentScene.[Friend]_ecsWorld.GetCurrentVersion() - }*/ + //_editor.CurrentScene.[Friend]_ecsWorld.GetCurrentVersion() + } //_editor.EntityHierarchyWindow.SelectEntityWithId(id, true); } diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 389d8c9..9cd8e1a 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -43,7 +43,7 @@ namespace GlitchyEditor Editor _editor ~ delete _; - RenderTarget2D _cameraTarget ~ _.ReleaseRef(); + RenderTargetGroup _cameraTarget ~ _.ReleaseRef(); RenderTargetGroup _viewportTarget ~ _.ReleaseRef(); SettingsWindow _settingsWindow = new .() ~ delete _; @@ -86,11 +86,15 @@ namespace GlitchyEditor DepthStencilStateDescription dsDesc = .(); _depthStencilState = new DepthStencilState(dsDesc); - _cameraTarget = new RenderTarget2D(RenderTarget2DDescription(.R16G16B16A16_Float, 100, 100) {DepthStencilFormat = .D32_Float}); - _cameraTarget.SamplerState = SamplerStateManager.LinearClamp; - - //_viewportTarget = new RenderTarget2D(RenderTarget2DDescription(.R8G8B8A8_UNorm, 100, 100)); - //_viewportTarget.SamplerState = SamplerStateManager.LinearClamp; + _cameraTarget = new RenderTargetGroup(.(){ + Width = 100, + Height = 100, + ColorTargetDescriptions = TargetDescription[]( + .(.R16G16B16A16_Float), + .(.R32_UInt) + ), + DepthTargetDescription = .(.D24_UNorm_S8_UInt) + }); _viewportTarget = new RenderTargetGroup(.() { @@ -164,6 +168,11 @@ namespace GlitchyEditor return Matrix.Translation(worldPos) * billboard; } + float CalculateAlpha(Vector3 pos) + { + return Math.Clamp(1.5f - Vector3.Distance(_editor.CurrentCamera.Position, pos) / 50, 0, 1); + } + for (var (entity, transform, camera) in _scene.[Friend]_ecsWorld.Enumerate()) { if (_editor.EntityHierarchyWindow.SelectedEntities.Contains(.(entity, _scene))) @@ -172,8 +181,10 @@ namespace GlitchyEditor } Matrix world = Billboard(transform.WorldTransform); - - Renderer2D.DrawQuad(world, _iconCamera); + + float alpha = CalculateAlpha(transform.WorldTransform.Translation); + Renderer2D.DrawQuad(world, _iconCamera, ColorRGBA(alpha, alpha, alpha, alpha), .(0, 0, 1, 1), entity.Index); + //Renderer2D.DrawQuad(world, _iconCamera, .White, .(0, 0, 1, 1), entity.Index); } for (var (entity, transform, light) in _scene.[Friend]_ecsWorld.Enumerate()) @@ -191,8 +202,10 @@ namespace GlitchyEditor } Matrix world = Billboard(transform.WorldTransform); - - Renderer2D.DrawQuad(world, _iconDirectionalLight, ColorRGBA(light.SceneLight.Color, 1.0f)); + + float alpha = CalculateAlpha(transform.WorldTransform.Translation); + Renderer2D.DrawQuad(world, _iconDirectionalLight, ColorRGBA(light.SceneLight.Color.Red * alpha, light.SceneLight.Color.Green * alpha, light.SceneLight.Color.Blue * alpha, alpha), .(0, 0, 1, 1), entity.Index); + //Renderer2D.DrawQuad(world, _iconDirectionalLight, ColorRGBA(light.SceneLight.Color, alpha), .(0, 0, 1, 1), entity.Index); } } diff --git a/GlitchyEngine/src/ImGui/ImGuiLayer.bf b/GlitchyEngine/src/ImGui/ImGuiLayer.bf index 0cb853c..c0d9a20 100644 --- a/GlitchyEngine/src/ImGui/ImGuiLayer.bf +++ b/GlitchyEngine/src/ImGui/ImGuiLayer.bf @@ -116,6 +116,8 @@ namespace GlitchyEngine.ImGui Begin(); + ImGui.ShowDemoWindow(); + { Debug.Profiler.ProfileScope!("ImGuiRenderEvent"); diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf index c30b294..a9d9044 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RenderTarget.bf @@ -5,6 +5,7 @@ using DirectX.D3D11; using GlitchyEngine.Platform.DX11; using DirectX.DXGI.DXGI1_2; using System; +using GlitchyEngine.Math; using internal GlitchyEngine.Platform.DX11; @@ -199,6 +200,16 @@ namespace GlitchyEngine.Renderer ReleaseEveryThing(); } + internal ID3D11Texture2D* GetNativeTexture(int index) + { + Log.EngineLogger.AssertDebug(index >= -1 && index < ColorTargetCount); + + if (index == -1) + return _nativeDepthTexture; + + return _nativeTextures[index]; + } + private ID3D11Texture2D* PlatformCreateTexture(TargetDescription target) { Debug.Profiler.ProfileResourceFunction!(); @@ -443,6 +454,18 @@ namespace GlitchyEngine.Renderer return .Ok; } + + public override void CopyTo(RenderTargetGroup destination, int dstTarget, Int2 dstTopLeft, Int2 size, Int2 srcTopLeft, int srcTarget) + { + ID3D11Texture2D* dstTexture = destination.GetNativeTexture(dstTarget); + ID3D11Texture2D* srcTexture = GetNativeTexture(srcTarget); + + // TODO: Mips/Arrays + + Box srcBox = .((.)srcTopLeft.X, (.)srcTopLeft.Y, 0, (.)(srcTopLeft.X + size.X), (.)(srcTopLeft.Y + size.Y), 1); + + NativeContext.CopySubresourceRegion(dstTexture, 0, (.)dstTopLeft.X, (.)dstTopLeft.Y, 0, srcTexture, 0, &srcBox); + } } } diff --git a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf index 498867c..d3a8516 100644 --- a/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf +++ b/GlitchyEngine/src/Platform/DX11/Renderer/Dx11RendererAPI.bf @@ -15,6 +15,9 @@ namespace GlitchyEngine.Renderer { private GraphicsContext _context ~ _?.ReleaseRef(); + private Effect _clearUintFx ~ _?.ReleaseRef(); + private BlendState _nonblendingState ~ _?.ReleaseRef(); + public GraphicsContext Context { get => _context; @@ -26,6 +29,11 @@ namespace GlitchyEngine.Renderer public override void Init() { Debug.Profiler.ProfileFunction!(); + + _clearUintFx = new Effect("content/Shaders/ClearUInt.hlsl"); + BlendStateDescription desc =.Default; + desc.RenderTarget[0].BlendEnable = false; + _nonblendingState = new BlendState(desc); } private mixin RtOrBackbuffer(RenderTarget2D renderTarget) @@ -69,12 +77,23 @@ namespace GlitchyEngine.Renderer case .Color(let color): NativeContext.ClearRenderTargetView(rtv, color); case .UInt(let value): -/*#unwarn +#unwarn NativeContext.OutputMerger.SetRenderTargets(1, &rtv, null); + using (BlendState lastBlendState = _currentBlendState..AddRef()) + { + SetBlendState(_nonblendingState); - - BindRenderTargets();*/ + _clearUintFx.Variables["ClearValue"].SetData(value); + _clearUintFx.Bind(_context); + + FullscreenQuad.Draw(); + + SetBlendState(lastBlendState); + } + + // Rebind the old render targets + BindRenderTargets(); default: Runtime.NotImplemented(); } diff --git a/GlitchyEngine/src/Renderer/BufferVariable.bf b/GlitchyEngine/src/Renderer/BufferVariable.bf index 19af71b..7121340 100644 --- a/GlitchyEngine/src/Renderer/BufferVariable.bf +++ b/GlitchyEngine/src/Renderer/BufferVariable.bf @@ -140,12 +140,13 @@ namespace GlitchyEngine.Renderer public void SetData(Int2 value) => SetData(value); public void SetData(Int3 value) => SetData(value); public void SetData(Int4 value) => SetData(value); + + public void SetData(uint32 value) => SetData(value); public void SetData(ColorRGB value) => SetData(value); public void SetData(ColorRGBA value) => SetData(value); public void SetData(Color value) => SetData((ColorRGBA)value); - public void SetData(Matrix4x3 value) => SetData(value); public void SetData(Matrix4x3[] value) diff --git a/GlitchyEngine/src/Renderer/FullscreenQuad.bf b/GlitchyEngine/src/Renderer/FullscreenQuad.bf index 42a6352..3dba5fd 100644 --- a/GlitchyEngine/src/Renderer/FullscreenQuad.bf +++ b/GlitchyEngine/src/Renderer/FullscreenQuad.bf @@ -1,12 +1,14 @@ +using GlitchyEngine.Math; + namespace GlitchyEngine.Renderer { static class FullscreenQuad { - //static GeometryBinding s_fullscreenQuadGeometry; + static GeometryBinding s_fullscreenQuadGeometry; public static void Init() { - /*s_fullscreenQuadGeometry = new GeometryBinding(); + s_fullscreenQuadGeometry = new GeometryBinding(); s_fullscreenQuadGeometry.SetPrimitiveTopology(.TriangleList); using(var quadVertices = new VertexBuffer(typeof(Vector4), 4, .Immutable)) @@ -38,15 +40,21 @@ namespace GlitchyEngine.Renderer VertexElement(.R32G32_Float, "TEXCOORD") ); - using (var quadBatchLayout = new VertexLayout(vertexElements, true, TestFullscreenEffect.VertexShader)) + using (var quadBatchLayout = new VertexLayout(vertexElements, true)) { s_fullscreenQuadGeometry.SetVertexLayout(quadBatchLayout); - }*/ + } } public static void Deinit() { - //s_fullscreenQuadGeometry.ReleaseRef(); + s_fullscreenQuadGeometry.ReleaseRef(); + } + + public static void Draw() + { + s_fullscreenQuadGeometry.Bind(); + RenderCommand.DrawIndexed(s_fullscreenQuadGeometry); } } } \ No newline at end of file diff --git a/GlitchyEngine/src/Renderer/RenderCommand.bf b/GlitchyEngine/src/Renderer/RenderCommand.bf index a3cd8a1..77bac6d 100644 --- a/GlitchyEngine/src/Renderer/RenderCommand.bf +++ b/GlitchyEngine/src/Renderer/RenderCommand.bf @@ -3,20 +3,17 @@ using GlitchyEngine.Math; namespace GlitchyEngine.Renderer { - /* - public enum DepthStencilClearFlag - { - None = 0, - Depth = 1, - Stencil = 2 - } - */ public enum ClearOptions { None = 0, Color = 1, Depth = 2, - Stencil = 4 + Stencil = 4, + + ColorDepth = Color | Depth, + ColorStencil = Color | Stencil, + DepthStencil = Depth | Stencil, + All = Color | Depth | Stencil } public static class RenderCommand diff --git a/GlitchyEngine/src/Renderer/RenderTarget.bf b/GlitchyEngine/src/Renderer/RenderTarget.bf index 3bc470d..34addaf 100644 --- a/GlitchyEngine/src/Renderer/RenderTarget.bf +++ b/GlitchyEngine/src/Renderer/RenderTarget.bf @@ -109,8 +109,16 @@ namespace GlitchyEngine.Renderer public enum ClearColor { + /// Clears the render target to the default value (Zero). + case Default; + /// The render target will be cleared with a RGBA color. case Color(ColorRGBA ClearColor); + /// The render target will be cleared with a UInt value. + /// @remarks Some platforms don't support clearing a UInt render target. + /// In these cases a draw call will be performed that draws a solid color into the target. + /// This can result in modified context state so it is recommended to rebind effects, etc. after clearing a uint rendertarget. case UInt(uint32 ClearValue); + /// Only valid for depth buffers. case DepthStencil(float Depth, uint8 Stencil); public static implicit operator ClearColor(ColorRGBA color) @@ -127,14 +135,13 @@ namespace GlitchyEngine.Renderer public bool IsShaderReadable = true; - /// Clear color. For DepthStencilBuffers: R is Depth, G is Stencil - public ClearColor ClearColor = .Color(.Black); + public ClearColor ClearColor = .Default; public SamplerStateDescription SamplerDescription = .(); public this() { } - public this(RenderTargetFormat format, bool isSwapchainTarget = false, bool isShaderReadable = true, ClearColor clearColor = .Color(.(0, 0, 0, 1)), SamplerStateDescription samplerDescription = .()) + public this(RenderTargetFormat format, bool isSwapchainTarget = false, bool isShaderReadable = true, ClearColor clearColor = .Default, SamplerStateDescription samplerDescription = .()) { Format = format; IsSwapchainTarget = isSwapchainTarget; @@ -189,6 +196,9 @@ namespace GlitchyEngine.Renderer public uint32 Samples => _description.Samples; + public int TargetCount => _colorTargetDescriptions.Count + (_depthTargetDescription.Format.IsDepth ? 1 : 0); + public int ColorTargetCount => _colorTargetDescriptions.Count; + [AllowAppend] public this(RenderTargetGroupDescription description) { @@ -220,6 +230,9 @@ namespace GlitchyEngine.Renderer } _colorSamplerStates[i] = SamplerStateManager.GetSampler(_colorTargetDescriptions[i].SamplerDescription); + + if (_colorTargetDescriptions[i].ClearColor case .Default) + _colorTargetDescriptions[i].ClearColor = .Color(.Black); } } @@ -228,6 +241,10 @@ namespace GlitchyEngine.Renderer if (_depthTargetDescription.Format != .None) { Log.EngineLogger.AssertDebug(_depthTargetDescription.Format.IsDepth, "Depth target must have depth format."); + + if (_depthTargetDescription.ClearColor case .Default) + _depthTargetDescription.ClearColor = .DepthStencil(0.0f, 0); + Log.EngineLogger.AssertDebug(_depthTargetDescription.ClearColor case .DepthStencil, "Clear color for depth stencil target must be of type DepthStencil."); _depthSamplerState = SamplerStateManager.GetSampler(_depthTargetDescription.SamplerDescription); @@ -258,5 +275,7 @@ namespace GlitchyEngine.Renderer return PlatformGetData(data, (.)sizeof(T), left, top, width, height, renderTarget, arraySlice, mipSlice); } + + public extern void CopyTo(RenderTargetGroup destination, int dstTarget, Int2 dstTopLeft, Int2 size, Int2 srcTopLeft, int srcTarget); } } diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 6fc67d8..ad694c3 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -11,7 +11,7 @@ namespace GlitchyEngine.Renderer { public Matrix ViewProjection; public Vector3 CameraPosition; - public RenderTarget2D CameraTarget; + public RenderTargetGroup CameraTarget; public RenderTargetGroup CompositionTarget; } @@ -25,24 +25,11 @@ namespace GlitchyEngine.Renderer private uint32 _width; private uint32 _height; - //public DepthStencilTarget DepthStencil; - public uint32 Width => _width; public uint32 Height => _height; public Int2 Size => .(_width, _height); - /*// RGB: Albedo.rgb A: ? - public RenderTarget2D Albedo ~ _?.ReleaseRef(); - // RG: TextureNormal.xy BA: GeometryNormal.xy - public RenderTarget2D Normal ~ _?.ReleaseRef(); - // R: GeometryNormal.z GBA: GeometryTangent.xyz - public RenderTarget2D Tangent ~ _?.ReleaseRef(); - // RGB: Worldspace Position A: ? - public RenderTarget2D Position ~ _?.ReleaseRef(); - // R: Metallicity G: Roughness B: Ambient A: ? - public RenderTarget2D Material ~ _?.ReleaseRef();*/ - public RenderTargetGroup Target ~ _?.ReleaseRef(); public void EnsureSize(uint32 width, uint32 height) @@ -52,22 +39,6 @@ namespace GlitchyEngine.Renderer if (_width == 0 || _height == 0) { - // Note: Depth-Buffer in Color-Target for convenience - /*RenderTarget2DDescription albedoDesc = .(.R8G8B8A8_UNorm, width, height, 1, 1, .D24_UNorm_S8_UInt); - Albedo = new RenderTarget2D(albedoDesc); - - RenderTarget2DDescription normalDesc = .(.R16G16B16A16_SNorm, width, height); - Normal = new RenderTarget2D(normalDesc); - - RenderTarget2DDescription tangentDesc = .(.R16G16B16A16_SNorm, width, height); - Tangent = new RenderTarget2D(tangentDesc); - - RenderTarget2DDescription positionDesc = .(.R32G32B32A32_Float, width, height); - Position = new RenderTarget2D(positionDesc); - - RenderTarget2DDescription materialDesc = .(.R8G8B8A8_UNorm, width, height); - Material = new RenderTarget2D(materialDesc);*/ - SamplerStateDescription desc = .(); desc.MinFilter = .Point; desc.MagFilter = .Point; @@ -79,7 +50,7 @@ namespace GlitchyEngine.Renderer .(RenderTargetFormat.R16G16B16A16_SNorm){SamplerDescription = desc}, .(RenderTargetFormat.R32G32B32A32_Float){SamplerDescription = desc}, .(RenderTargetFormat.R8G8B8A8_UNorm){SamplerDescription = desc}, - .(RenderTargetFormat.R32_UInt){SamplerDescription = desc, ClearColor = ColorRGBA(0, 0, 0, 0)}, + .(RenderTargetFormat.R32_UInt){SamplerDescription = desc, ClearColor = .UInt(uint32.MaxValue)}, ), TargetDescription(.D24_UNorm_S8_UInt){ SamplerDescription = desc, @@ -91,60 +62,29 @@ namespace GlitchyEngine.Renderer _width = width; _height = height; - /*Albedo.Resize(_width, _height); - Normal.Resize(_width, _height); - Tangent.Resize(_width, _height); - Position.Resize(_width, _height); - Material.Resize(_width, _height);*/ - - //DepthStencil = Albedo.DepthStencilTarget; - Target.Resize(_width, _height); } public void Bind() { - /*RenderCommand.SetDepthStencilTarget(DepthStencil); - - RenderCommand.UnbindRenderTargets(); - RenderCommand.SetRenderTarget(Albedo, 0); - RenderCommand.SetRenderTarget(Normal, 1); - RenderCommand.SetRenderTarget(Tangent, 2); - RenderCommand.SetRenderTarget(Position, 3); - RenderCommand.SetRenderTarget(Material, 4);*/ - RenderCommand.SetRenderTargetGroup(Target); - RenderCommand.BindRenderTargets(); } public void Clear() { - /*RenderCommand.Clear(_gBuffer.Albedo, .Color | .Depth, .HotPink, 1, 0); - RenderCommand.Clear(_gBuffer.Normal, .HotPink); - RenderCommand.Clear(_gBuffer.Tangent, .HotPink); - RenderCommand.Clear(_gBuffer.Position, .HotPink); - RenderCommand.Clear(_gBuffer.Material, .HotPink);*/ - - RenderCommand.Clear(Target, .Color | .Depth); + RenderCommand.Clear(Target, .ColorDepth); } } static internal GraphicsContext _context; - //static Buffer _sceneConstants ~ _?.ReleaseRef(); - - //static Buffer _objectConstants ~ _?.ReleaseRef(); - static SceneConstants _sceneConstants; static Effect LineEffect; static VertexBuffer LineVertices; static GeometryBinding LineGeometry; - - static GeometryBinding s_fullscreenQuadGeometry; - static GBuffer _gBuffer; static Effect TestFullscreenEffect; static Effect s_tonemappingEffect; @@ -158,14 +98,7 @@ namespace GlitchyEngine.Renderer Debug.Profiler.ProfileFunction!(); _context = context..AddRef(); - /* - _sceneConstants = new Buffer(.(0, .Constant, .Dynamic, .Write)); - _sceneConstants.Update(); - - _objectConstants = new Buffer(.(0, .Constant, .Dynamic, .Write)); - _objectConstants.Update(); - */ - + RenderCommand.Init(); Renderer2D.Init(); FullscreenQuad.Init(); @@ -226,43 +159,6 @@ namespace GlitchyEngine.Renderer TestFullscreenEffect = effectLibrary.Load("content\\Shaders\\simpleLight.hlsl"); s_tonemappingEffect = effectLibrary.Load("content\\Shaders\\SimpleTonemapping.hlsl"); - s_fullscreenQuadGeometry = new GeometryBinding(); - s_fullscreenQuadGeometry.SetPrimitiveTopology(.TriangleList); - - using(var quadVertices = new VertexBuffer(typeof(Vector4), 4, .Immutable)) - { - Vector4[4] vertices = .( - .(-1,-1, 0, 1), - .(-1, 1, 0, 0), - .( 1, 1, 1, 0), - .( 1,-1, 1, 1) - ); - - quadVertices.SetData(vertices); - s_fullscreenQuadGeometry.SetVertexBufferSlot(quadVertices, 0); - } - - using(var quadIndices = new IndexBuffer(6, .Immutable)) - { - uint16[6] indices = .( - 0, 1, 2, - 2, 3, 0 - ); - - quadIndices.SetData(indices); - s_fullscreenQuadGeometry.SetIndexBuffer(quadIndices); - } - - VertexElement[] vertexElements = new .( - VertexElement(.R32G32_Float, "POSITION"), - VertexElement(.R32G32_Float, "TEXCOORD") - ); - - using (var quadBatchLayout = new VertexLayout(vertexElements, true)) - { - s_fullscreenQuadGeometry.SetVertexLayout(quadBatchLayout); - } - _gBuffer = new GBuffer(); BlendStateDescription gBufferBlendDesc = .Default; _gBufferBlend = new BlendState(gBufferBlendDesc); @@ -291,7 +187,6 @@ namespace GlitchyEngine.Renderer _lightBlend.ReleaseRef(); _gBufferBlend.ReleaseRef(); delete _gBuffer; - s_fullscreenQuadGeometry.ReleaseRef(); s_tonemappingEffect.ReleaseRef(); TestFullscreenEffect.ReleaseRef(); @@ -302,11 +197,9 @@ namespace GlitchyEngine.Renderer Debug.Profiler.ProfileRendererFunction!(); _sceneConstants.ViewProjection = camera.ViewProjection; - //_sceneConstants.Data.ViewProjection = camera.ViewProjection; - //_sceneConstants.Update(); } - public static void BeginScene(Camera camera, Matrix transform, RenderTarget2D renderTarget, RenderTargetGroup finalTarget) + public static void BeginScene(Camera camera, Matrix transform, RenderTargetGroup renderTarget, RenderTargetGroup finalTarget) { Debug.Profiler.ProfileRendererFunction!(); @@ -331,7 +224,7 @@ namespace GlitchyEngine.Renderer public static int SortMeshes(SubmittedMesh left, SubmittedMesh right) { // TODO: Once Material "inheritance" is ready we could perhaps check how similar materials are (e.g. shared textures/variables/etc...) - // Similar thing could be done for Meshes. Both would probably require a different way to sort howerver?... + // Similar thing could be done for Meshes. Both would probably require a different way to sort however?... int cmp = (int)Internal.UnsafeCastToPtr(left.Material) <=> (int)Internal.UnsafeCastToPtr(right.Material); @@ -346,7 +239,7 @@ namespace GlitchyEngine.Renderer float distLeftSq = Vector3.DistanceSquared(_sceneConstants.CameraPosition, left.Transform.Translation); float distRightSq = Vector3.DistanceSquared(_sceneConstants.CameraPosition, right.Transform.Translation); - // Whether or not the values are squared doesn't affect the order (because square(-root) is a monotonic function) + // Whether or not the values are squared doesn't affect the order (because square(root) is a monotonic function) cmp = distLeftSq <=> distRightSq; } } @@ -410,10 +303,10 @@ namespace GlitchyEngine.Renderer Debug.Profiler.ProfileRendererScope!("Draw Lights"); RenderCommand.UnbindRenderTargets(); - RenderCommand.SetRenderTarget(_sceneConstants.CameraTarget, 0, true); + RenderCommand.SetRenderTargetGroup(_sceneConstants.CameraTarget); RenderCommand.BindRenderTargets(); - RenderCommand.Clear(_sceneConstants.CameraTarget, .Black); + RenderCommand.Clear(_sceneConstants.CameraTarget, .ColorDepth); RenderCommand.SetBlendState(_lightBlend); RenderCommand.SetDepthStencilState(_fullscreenDepthState); @@ -443,21 +336,24 @@ namespace GlitchyEngine.Renderer TestFullscreenEffect.Bind(_context); - s_fullscreenQuadGeometry.Bind(); - RenderCommand.DrawIndexed(s_fullscreenQuadGeometry); + FullscreenQuad.Draw(); } _lights.Clear(); + // Copy EntityIDs to camera target + _gBuffer.Target.CopyTo(_sceneConstants.CameraTarget, 1, Int2.Zero, Int2(_sceneConstants.CameraTarget.Width, _sceneConstants.CameraTarget.Height), Int2.Zero, 5); + RenderCommand.SetBlendState(_gBufferBlend); RenderCommand.SetRenderTargetGroup(_sceneConstants.CompositionTarget, true); RenderCommand.BindRenderTargets(); // TODO: Postprocessing effects - s_tonemappingEffect.SetTexture("CameraTarget", _sceneConstants.CameraTarget); + s_tonemappingEffect.SetTexture("CameraTarget", _sceneConstants.CameraTarget, 0); s_tonemappingEffect.Bind(_context); - RenderCommand.DrawIndexed(s_fullscreenQuadGeometry); + + FullscreenQuad.Draw(); RenderCommand.UnbindTextures(); } @@ -532,7 +428,7 @@ namespace GlitchyEngine.Renderer { Debug.Profiler.ProfileRendererFunction!(); - _queue.Add(SubmittedMesh(geometry, material, transform, 0)); + _queue.Add(SubmittedMesh(geometry, material, transform, uint32.MaxValue)); } public static void Submit(GeometryBinding geometry, Material material, EcsEntity entity, Matrix transform = .Identity) diff --git a/GlitchyEngine/src/Renderer/Renderer2D.bf b/GlitchyEngine/src/Renderer/Renderer2D.bf index e18477d..f61fadb 100644 --- a/GlitchyEngine/src/Renderer/Renderer2D.bf +++ b/GlitchyEngine/src/Renderer/Renderer2D.bf @@ -50,11 +50,14 @@ namespace GlitchyEngine.Renderer public ColorRGBA Color; public Vector4 UVTransform; - public this(Matrix transform, ColorRGBA color, Vector4 uvTransform) + public uint32 EntityId; + + public this(Matrix transform, ColorRGBA color, Vector4 uvTransform, uint32 entityId) { Transform = transform; Color = color; UVTransform = uvTransform; + EntityId = entityId; } } @@ -63,8 +66,8 @@ namespace GlitchyEngine.Renderer { public float InnerRadius; - public this(Matrix transform, ColorRGBA color, Vector4 uvTransform, float innerRadius) - : base(transform, color, uvTransform) + public this(Matrix transform, ColorRGBA color, Vector4 uvTransform, float innerRadius, uint32 entityId) + : base(transform, color, uvTransform, entityId) { InnerRadius = innerRadius; } @@ -91,14 +94,14 @@ namespace GlitchyEngine.Renderer FrontToBack } - struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, Vector4 uvTransform) { } + struct QueueQuad: this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, Vector4 uvTransform, uint32 entityId = uint32.MaxValue) { } struct QueueCircle : QueueQuad { public float InnerRadius; - public this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, Vector4 uvTransform, float innerRadius) - : base(Transform, Color, Texture, Depth, uvTransform) + public this(Matrix Transform, ColorRGBA Color, Texture Texture, float Depth, Vector4 uvTransform, float innerRadius, uint32 entityId = uint32.MaxValue) + : base(Transform, Color, Texture, Depth, uvTransform, entityId) { InnerRadius = innerRadius; } @@ -205,7 +208,8 @@ namespace GlitchyEngine.Renderer VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 2, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 3, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "COLOR", false, 0, 1, (.)-1, .PerInstanceData, 1), - VertexElement(.R32G32B32A32_Float, "TEXCOORD", false, 1, 1, (.)-1, .PerInstanceData, 1) + VertexElement(.R32G32B32A32_Float, "TEXCOORD", false, 1, 1, (.)-1, .PerInstanceData, 1), + VertexElement(.R32_UInt, "ENTITYID", false, 0, 1, (.)-1, .PerInstanceData, 1) ); s_quadBatchBinding = new GeometryBinding(); @@ -232,7 +236,8 @@ namespace GlitchyEngine.Renderer VertexElement(.R32G32B32A32_Float, "TRANSFORM", false, 3, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "COLOR", false, 0, 1, (.)-1, .PerInstanceData, 1), VertexElement(.R32G32B32A32_Float, "TEXCOORD", false, 1, 1, (.)-1, .PerInstanceData, 1), - VertexElement(.R32_Float, "TEXCOORD", false, 2, 1, (.)-1, .PerInstanceData, 1) + VertexElement(.R32_Float, "TEXCOORD", false, 2, 1, (.)-1, .PerInstanceData, 1), + VertexElement(.R32_UInt, "ENTITYID", false, 0, 1, (.)-1, .PerInstanceData, 1) ); s_circleBatchBinding = new GeometryBinding(); @@ -313,6 +318,24 @@ namespace GlitchyEngine.Renderer sampler.ReleaseRef(); } + private static BlendState s_opaqueBlendState; + private static BlendState s_transparentBlendState; + + private static void InitStates() + { + s_opaqueBlendState = new BlendState(.Default); + + // TODO: alpha is a bitch. + // This is for premultiplied alpha!!!! However the engine has basically no support for that >:[ + BlendStateDescription transparentDesc = .Default; + transparentDesc.IndependentBlendEnable = true; + transparentDesc.RenderTarget[0] = .(true, + .One, .InvertedSourceAlpha, .Add, + .One, .One, .Add, .All); + + s_transparentBlendState = new BlendState(transparentDesc); + } + public static void Init() { Debug.Profiler.ProfileFunction!(); @@ -320,6 +343,8 @@ namespace GlitchyEngine.Renderer Log.EngineLogger.AssertDebug(!s_initialized, "Renderer2D is already initialized."); #endif + InitStates(); + InitEffect(); InitGeometry(); InitInstancingGeometry(); @@ -361,6 +386,9 @@ namespace GlitchyEngine.Renderer s_currentEffect?.ReleaseRef(); s_currentCircleEffect?.ReleaseRef(); + s_opaqueBlendState.ReleaseRef(); + s_transparentBlendState.ReleaseRef(); + #if DEBUG s_initialized = false; #endif @@ -517,17 +545,17 @@ namespace GlitchyEngine.Renderer /// Adds a quad instance to the instance queue. [Inline] - private static void QueueQuadInstance(Matrix transform, ColorRGBA color, Texture texture, float depth, Vector4 uvTransform) + private static void QueueQuadInstance(Matrix transform, ColorRGBA color, Texture texture, float depth, Vector4 uvTransform, uint32 id = uint32.MaxValue) { - s_QuadinstanceQueue.Add(QueueQuad(transform, color, texture ?? s_whiteTexture, depth, uvTransform)); + s_QuadinstanceQueue.Add(QueueQuad(transform, color, texture ?? s_whiteTexture, depth, uvTransform, id)); s_statistics.QuadCount++; } /// Adds a circle instance to the instance queue. [Inline] - private static void QueueCircleInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, Vector4 uvTransform, float innerRadius) + private static void QueueCircleInstance(Matrix transform, ColorRGBA color, Texture2D texture, float depth, Vector4 uvTransform, float innerRadius, uint32 id = uint32.MaxValue) { - s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius)); + s_circleInstanceQueue.Add(QueueCircle(transform, color, texture ?? s_whiteTexture, depth, uvTransform, innerRadius, id)); s_statistics.CircleCount++; } @@ -637,6 +665,9 @@ namespace GlitchyEngine.Renderer if(s_QuadinstanceQueue.IsEmpty) return; + + // TODO: per object blendstate + RenderCommand.SetBlendState(s_transparentBlendState); Texture texture = s_QuadinstanceQueue[0].Texture; s_currentEffect.SetTexture("Texture", texture); @@ -656,7 +687,7 @@ namespace GlitchyEngine.Renderer s_currentEffect.SetTexture("Texture", texture); } - s_rawQuadInstances[s_setInstances++] = .(quad.Transform, quad.Color, quad.uvTransform); + s_rawQuadInstances[s_setInstances++] = .(quad.Transform, quad.Color, quad.uvTransform, quad.entityId); if(s_setInstances == s_rawQuadInstances.Count) { @@ -676,6 +707,9 @@ namespace GlitchyEngine.Renderer if(s_circleInstanceQueue.IsEmpty) return; + // TODO: per object blendstate + RenderCommand.SetBlendState(s_transparentBlendState); + Texture texture = s_circleInstanceQueue[0].Texture; s_currentCircleEffect.SetTexture("Texture", texture); @@ -694,7 +728,7 @@ namespace GlitchyEngine.Renderer s_currentCircleEffect.SetTexture("Texture", texture); } - s_rawCircleInstances[s_setInstances++] = .(circle.Transform, circle.Color, circle.uvTransform, circle.InnerRadius); + s_rawCircleInstances[s_setInstances++] = .(circle.Transform, circle.Color, circle.uvTransform, circle.InnerRadius, circle.entityId); if(s_setInstances == s_rawCircleInstances.Count) { @@ -800,11 +834,11 @@ namespace GlitchyEngine.Renderer DrawQuad(position, size, rotation, subtexture.Texture, .White, uv); } - public static void DrawQuad(Matrix transform, SubTexture2D subtexture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1)) + public static void DrawQuad(Matrix transform, SubTexture2D subtexture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1), uint32 entityId = uint32.MaxValue) { Vector4 uv = CalculateSubTexcoords(subtexture.TexCoords, uvTransform); - DrawQuad(transform, subtexture.Texture, .White, uv); + DrawQuad(transform, subtexture.Texture, color, uv, entityId); } // Textured Quad @@ -821,7 +855,7 @@ namespace GlitchyEngine.Renderer DrawQuad(transform, texture, color, uvTransform); } - public static void DrawQuad(Matrix transform, Texture texture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1)) + public static void DrawQuad(Matrix transform, Texture texture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1), uint32 entityId = uint32.MaxValue) { Debug.Profiler.ProfileRendererFunction!(); @@ -829,7 +863,7 @@ namespace GlitchyEngine.Renderer Log.EngineLogger.AssertDebug(s_sceneRunning, "Missing call of BeginScene."); #endif - QueueQuadInstance(transform, color, texture, transform.Translation.Z, uvTransform); + QueueQuadInstance(transform, color, texture, transform.Translation.Z, uvTransform, entityId); if(s_drawOrder == .Immediate) { @@ -837,6 +871,11 @@ namespace GlitchyEngine.Renderer } } + public static void DrawSprite(Matrix transform, SpriterRendererComponent* spriteRenderer, uint32 entityId) + { + DrawQuad(transform, spriteRenderer.Sprite ?? s_whiteTexture, spriteRenderer.Color, .(0, 0, 1, 1), entityId); + } + // Textured quad pivot public static void DrawQuadPivotCorner(Vector2 position, Vector2 size, float rotation, Texture2D texture, ColorRGBA color = .White, Vector4 uvTransform = .(0, 0, 1, 1)) diff --git a/GlitchyEngine/src/Renderer/RendererAPI.bf b/GlitchyEngine/src/Renderer/RendererAPI.bf index bd7b244..e4183ac 100644 --- a/GlitchyEngine/src/Renderer/RendererAPI.bf +++ b/GlitchyEngine/src/Renderer/RendererAPI.bf @@ -49,7 +49,7 @@ namespace GlitchyEngine.Renderer public extern void SetRasterizerState(RasterizerState rasterizerState); - public extern void SetBlendState(BlendState blendState, ColorRGBA blendFactor); + public extern void SetBlendState(BlendState blendState, ColorRGBA blendFactor = .White); public extern void SetDepthStencilState(DepthStencilState depthStencilState, uint8 stencilReference); diff --git a/GlitchyEngine/src/World/Components.bf b/GlitchyEngine/src/World/Components.bf index a085e40..a2ddadd 100644 --- a/GlitchyEngine/src/World/Components.bf +++ b/GlitchyEngine/src/World/Components.bf @@ -253,9 +253,9 @@ namespace GlitchyEngine.World { public SceneCamera Camera = .(); public bool Primary = true; // Todo: probably move into scene - private RenderTarget2D _renderTarget = null; + private RenderTargetGroup _renderTarget = null; - public RenderTarget2D RenderTarget + public RenderTargetGroup RenderTarget { get => _renderTarget; set mut diff --git a/GlitchyEngine/src/World/EcsEntity.bf b/GlitchyEngine/src/World/EcsEntity.bf index 134561a..0859cbc 100644 --- a/GlitchyEngine/src/World/EcsEntity.bf +++ b/GlitchyEngine/src/World/EcsEntity.bf @@ -11,10 +11,10 @@ namespace GlitchyEngine.World // Data: Version Index [Inline] - internal uint32 Version => (uint32)this; + public uint32 Version => (uint32)this; [Inline] - internal uint32 Index => (uint32)(this >> 32); + public uint32 Index => (uint32)(this >> 32); [Inline] static internal EcsEntity CreateEntityID(uint32 index, uint32 version) diff --git a/GlitchyEngine/src/World/EditorCamera.bf b/GlitchyEngine/src/World/EditorCamera.bf index 5386477..351eeb0 100644 --- a/GlitchyEngine/src/World/EditorCamera.bf +++ b/GlitchyEngine/src/World/EditorCamera.bf @@ -25,7 +25,7 @@ namespace GlitchyEngine.World private float _nearPlane; private float _aspectRatio; - private RenderTarget2D _renderTarget = null; + private RenderTargetGroup _renderTarget = null; internal bool BindMouse; internal uint8 MouseCooldown; @@ -34,7 +34,7 @@ namespace GlitchyEngine.World public Matrix View => _view; - public RenderTarget2D RenderTarget + public RenderTargetGroup RenderTarget { get => _renderTarget; set mut diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 8737e61..c3b234b 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -68,7 +68,7 @@ namespace GlitchyEngine.World Camera* primaryCamera = null; Matrix primaryCameraTransform = default; - RenderTarget2D renderTarget = null; + RenderTargetGroup renderTarget = null; for (var (entity, transform, camera) in _ecsWorld.Enumerate()) { @@ -138,12 +138,15 @@ namespace GlitchyEngine.World // TODO: alphablending + RenderCommand.SetRenderTargetGroup(camera.RenderTarget); + RenderCommand.BindRenderTargets(); + // Sprite renderer Renderer2D.BeginScene(camera, .BackToFront); for (var (entity, transform, sprite) in _ecsWorld.Enumerate()) { - Renderer2D.DrawQuad(transform.WorldTransform, sprite.Sprite, sprite.Color); + Renderer2D.DrawSprite(transform.WorldTransform, sprite, entity.Index); } Renderer2D.EndScene(); @@ -153,7 +156,9 @@ namespace GlitchyEngine.World DrawDebug2D(); Renderer2D.EndScene(); - + + // TODO: cameraTarget into viewportTarget (gamma correction!) + viewportTarget.ReleaseRef(); }