diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index a1a4e99..3f9ad1c 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -28,6 +28,7 @@ namespace GlitchyEditor Editor _editor ~ delete _; + RenderTarget2D _intermediateTarget ~ _?.ReleaseRef(); RenderTarget2D _viewportTarget ~ _?.ReleaseRef(); SettingsWindow _settingsWindow = new .() ~ delete _; @@ -109,6 +110,28 @@ namespace GlitchyEditor _otherCameraEntity.AddComponent(); } + { + var lightNtt = _scene.CreateEntity("My Sexy Sun"); + let transform = lightNtt.GetComponent(); + transform.Position = .(0, 0, 0); + transform.RotationEuler = .(MathHelper.ToRadians(45), MathHelper.ToRadians(-45), 0); + + let light = lightNtt.AddComponent(); + light.SceneLight.Illuminance = 10.0f; + light.SceneLight.Color = .(1.0f, 0.95f, 0.8f); + } + + { + var lightNtt = _scene.CreateEntity("My Sexy Sun 2"); + let transform = lightNtt.GetComponent(); + transform.Position = .(0, 0, 0); + transform.RotationEuler = .(MathHelper.ToRadians(70), MathHelper.ToRadians(-30), 0); + + let light = lightNtt.AddComponent(); + light.SceneLight.Illuminance = 10.0f; + light.SceneLight.Color = .(1.0f, 0.95f, 0.8f); + } + InitEditor(); TestEntitiesWithModels(); diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 033100e..44458cf 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -28,9 +28,9 @@ namespace GlitchyEngine.Renderer // RGB: Albedo.rgb A: ? public RenderTarget2D Albedo ~ _?.ReleaseRef(); - // RGB: Normal.xyz(Worldspace) A: Ambient + // 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(); @@ -97,7 +97,7 @@ namespace GlitchyEngine.Renderer } } - static internal GraphicsContext _context ~ _?.ReleaseRef(); + static internal GraphicsContext _context; //static Buffer _sceneConstants ~ _?.ReleaseRef(); @@ -105,14 +105,19 @@ namespace GlitchyEngine.Renderer static SceneConstants _sceneConstants; - static Effect LineEffect ~ _?.ReleaseRef(); - static VertexBuffer LineVertices ~ _?.ReleaseRef(); - static GeometryBinding LineGeometry ~ _?.ReleaseRef(); + static Effect LineEffect; + static VertexBuffer LineVertices; + static GeometryBinding LineGeometry; - static GBuffer _gBuffer ~ delete _; - static Effect TestFullscreenEffect ~ _?.ReleaseRef(); - static BlendState _gBufferBlend ~ _?.ReleaseRef(); + static GeometryBinding s_fullscreenQuadGeometry; + + static GBuffer _gBuffer; + static Effect TestFullscreenEffect; + + static BlendState _gBufferBlend; + static BlendState _lightBlend; + static DepthStencilState _fullscreenDepthState; public static void Init(GraphicsContext context, EffectLibrary effectLibrary) { @@ -132,17 +137,19 @@ namespace GlitchyEngine.Renderer InitLineRenderer(effectLibrary); InitDeferredRenderer(effectLibrary); - - _gBuffer = new GBuffer(); - BlendStateDescription gBufferBlendDesc = .Default; - _gBufferBlend = new BlendState(gBufferBlendDesc); } public static void Deinit() { Debug.Profiler.ProfileFunction!(); + DeinitDeferredRenderer(); + + DeinitLineRenderer(); + Renderer2D.Deinit(); + + _context.ReleaseRef(); } static void InitLineRenderer(EffectLibrary effectLibrary) @@ -170,15 +177,20 @@ namespace GlitchyEngine.Renderer VertexLayout layout = new VertexLayout(vertexElements, true, LineEffect.VertexShader); LineGeometry.SetVertexLayout(layout..ReleaseRefNoDelete()); } - - private static GeometryBinding s_quadGeometry ~ _?.ReleaseRef(); + + static void DeinitLineRenderer() + { + LineVertices.ReleaseRef(); + LineGeometry.ReleaseRef(); + LineEffect.ReleaseRef(); + } static void InitDeferredRenderer(EffectLibrary effectLibrary) { TestFullscreenEffect = effectLibrary.Load("content\\Shaders\\simpleLight.hlsl"); - s_quadGeometry = new GeometryBinding(); - s_quadGeometry.SetPrimitiveTopology(.TriangleList); + s_fullscreenQuadGeometry = new GeometryBinding(); + s_fullscreenQuadGeometry.SetPrimitiveTopology(.TriangleList); using(var quadVertices = new VertexBuffer(typeof(Vector4), 4, .Immutable)) { @@ -190,7 +202,7 @@ namespace GlitchyEngine.Renderer ); quadVertices.SetData(vertices); - s_quadGeometry.SetVertexBufferSlot(quadVertices, 0); + s_fullscreenQuadGeometry.SetVertexBufferSlot(quadVertices, 0); } using(var quadIndices = new IndexBuffer(6, .Immutable)) @@ -201,34 +213,51 @@ namespace GlitchyEngine.Renderer ); quadIndices.SetData(indices); - s_quadGeometry.SetIndexBuffer(quadIndices); + s_fullscreenQuadGeometry.SetIndexBuffer(quadIndices); } VertexElement[] vertexElements = new .( - VertexElement(.R32G32_Float, "POSITION", false, 0, 0, 0, .PerVertexData, 0), - VertexElement(.R32G32_Float, "TEXCOORD", false, 0, 0, (.)-1, .PerVertexData, 0) + VertexElement(.R32G32_Float, "POSITION"), + VertexElement(.R32G32_Float, "TEXCOORD") ); using (var quadBatchLayout = new VertexLayout(vertexElements, true, TestFullscreenEffect.VertexShader)) { - s_quadGeometry.SetVertexLayout(quadBatchLayout); + s_fullscreenQuadGeometry.SetVertexLayout(quadBatchLayout); } + + _gBuffer = new GBuffer(); + BlendStateDescription gBufferBlendDesc = .Default; + _gBufferBlend = new BlendState(gBufferBlendDesc); + + BlendStateDescription lightBlendDesc = .Default; + lightBlendDesc.RenderTarget[0] = .(){ + BlendEnable = true, + SourceBlend = .One, + DestinationBlend = .One, + BlendOperation = .Add, + SourceBlendAlpha = .One, + DestinationBlendAlpha = .Zero, + BlendOperationAlpha = .Add, + RenderTargetWriteMask = .All + }; + _lightBlend = new BlendState(lightBlendDesc); + + DepthStencilStateDescription dsDesc = .Default; + dsDesc.DepthEnabled = false; + _fullscreenDepthState = new DepthStencilState(dsDesc); } - // TODO - /*public static void BeginScene(EcsWorld world, EcsEntity cameraEntity) + static void DeinitDeferredRenderer() { - Debug.Profiler.ProfileRendererFunction!(); + _fullscreenDepthState.ReleaseRef(); + _lightBlend.ReleaseRef(); + _gBufferBlend.ReleaseRef(); + delete _gBuffer; + s_fullscreenQuadGeometry.ReleaseRef(); - var camera = world.GetComponent(cameraEntity); - var transform = world.GetComponent(cameraEntity); - - var trans = transform.WorldTransform; - var view = trans.Invert(); - var proj = camera.Projection; - - _sceneConstants.ViewProjection = proj * view; - }*/ + TestFullscreenEffect.ReleaseRef(); + } public static void BeginScene(OldCamera camera) { @@ -327,29 +356,64 @@ namespace GlitchyEngine.Renderer { Debug.Profiler.ProfileRendererScope!("Draw Lights"); - + RenderCommand.UnbindRenderTargets(); RenderCommand.SetRenderTarget(_sceneConstants.CameraTarget, 0, true); RenderCommand.BindRenderTargets(); - - _gBuffer.Albedo.SamplerState = SamplerStateManager.PointClamp; + + RenderCommand.SetBlendState(_lightBlend); + RenderCommand.SetDepthStencilState(_fullscreenDepthState); + + for (SubmittedLight light in _lights) + { + Vector3 lightDir = light.Transform.Forward; + + _gBuffer.Albedo.SamplerState = SamplerStateManager.PointClamp; + TestFullscreenEffect.SetTexture("GBuffer_Albedo", _gBuffer.Albedo); + TestFullscreenEffect.SetTexture("GBuffer_Normal", _gBuffer.Normal); + TestFullscreenEffect.SetTexture("GBuffer_Tangent", _gBuffer.Tangent); + TestFullscreenEffect.SetTexture("GBuffer_Position", _gBuffer.Position); + TestFullscreenEffect.SetTexture("GBuffer_Material", _gBuffer.Material); + + TestFullscreenEffect.Variables["LightColor"].SetData(light.Light.Color); + TestFullscreenEffect.Variables["Illuminance"].SetData(light.Light.Illuminance); + TestFullscreenEffect.Variables["LightDir"].SetData(-lightDir); + + TestFullscreenEffect.Variables["CameraPos"].SetData(_sceneConstants.CameraPosition); + + TestFullscreenEffect.Variables["Scaling"].SetData(Vector2(_sceneConstants.CameraTarget.Width, _sceneConstants.CameraTarget.Height) / Vector2(_gBuffer.Albedo.Width, _gBuffer.Albedo.Height)); + + TestFullscreenEffect.Bind(_context); + + s_fullscreenQuadGeometry.Bind(); + RenderCommand.DrawIndexed(s_fullscreenQuadGeometry); + } + + RenderCommand.SetBlendState(_gBufferBlend); + + _lights.Clear(); + + /* + _gBuffer.Albedo.SamplerState = SamplerStateManager.PointClamp; + TestFullscreenEffect.SetTexture("GBuffer_Albedo", _gBuffer.Albedo); TestFullscreenEffect.SetTexture("GBuffer_Normal", _gBuffer.Normal); TestFullscreenEffect.SetTexture("GBuffer_Tangent", _gBuffer.Tangent); TestFullscreenEffect.SetTexture("GBuffer_Position", _gBuffer.Position); TestFullscreenEffect.SetTexture("GBuffer_Material", _gBuffer.Material); - + TestFullscreenEffect.Variables["LightColor"].SetData(Vector3(1, 1, 1)); TestFullscreenEffect.Variables["Illuminance"].SetData(5.0f); TestFullscreenEffect.Variables["LightDir"].SetData(Vector3(0, 1, 0)); TestFullscreenEffect.Variables["CameraPos"].SetData(_sceneConstants.CameraPosition); TestFullscreenEffect.Variables["Scaling"].SetData(Vector2(_sceneConstants.CameraTarget.Width, _sceneConstants.CameraTarget.Height) / Vector2(_gBuffer.Albedo.Width, _gBuffer.Albedo.Height)); - + TestFullscreenEffect.Bind(_context); - + s_quadGeometry.Bind(); RenderCommand.DrawIndexed(s_quadGeometry); + */ RenderCommand.UnbindTextures(); } @@ -403,7 +467,20 @@ namespace GlitchyEngine.Renderer } } + struct SubmittedLight + { + public SceneLight Light; + public Matrix Transform; + + public this(SceneLight light, Matrix transform) + { + Light = light; + Transform = transform; + } + } + private static List _queue = new .(10000) ~ DeleteContainerAndDisposeItems!(_); + private static List _lights = new .(100) ~ delete _; public static void Submit(GeometryBinding geometry, Material material, Matrix transform = .Identity) { @@ -412,6 +489,13 @@ namespace GlitchyEngine.Renderer _queue.Add(SubmittedMesh(geometry, material, transform)); } + public static void Submit(SceneLight light, Matrix transform = .Identity) + { + Debug.Profiler.ProfileRendererFunction!(); + + _lights.Add(SubmittedLight(light, transform)); + } + /** @brief Draws a line. * @param start The start point of the line. * @param end The end point of the line. diff --git a/GlitchyEngine/src/Renderer/Renderer2D.bf b/GlitchyEngine/src/Renderer/Renderer2D.bf index e425d4e..c11b922 100644 --- a/GlitchyEngine/src/Renderer/Renderer2D.bf +++ b/GlitchyEngine/src/Renderer/Renderer2D.bf @@ -316,6 +316,9 @@ namespace GlitchyEngine.Renderer public static void Init() { Debug.Profiler.ProfileFunction!(); +#if DEBUG + Log.EngineLogger.AssertDebug(!s_initialized, "Renderer2D is already initialized."); +#endif InitEffect(); InitGeometry(); @@ -333,7 +336,7 @@ namespace GlitchyEngine.Renderer { Debug.Profiler.ProfileFunction!(); #if DEBUG - Log.EngineLogger.AssertDebug(s_initialized, "Renderer2D was not initialized."); + Log.EngineLogger.AssertDebug(s_initialized, "Renderer2D is not initialized."); #endif FontRenderer.Deinit(); diff --git a/GlitchyEngine/src/Renderer/VertexLayout.bf b/GlitchyEngine/src/Renderer/VertexLayout.bf index 005c226..9f83d7e 100644 --- a/GlitchyEngine/src/Renderer/VertexLayout.bf +++ b/GlitchyEngine/src/Renderer/VertexLayout.bf @@ -61,7 +61,7 @@ namespace GlitchyEngine.Renderer public this() => this = default; - public this(Format format, String semanticName, bool ownsName = false, uint32 semanticIndex = 0, uint32 inputSlot = 0, uint32 offset = (.)-1, InputClassification slotClass = .PerVertexData, uint32 instanceStepRate = 0) + public this(Format format, String semanticName, bool ownsName = false, uint32 semanticIndex = 0, uint32 inputSlot = 0, uint32 offset = VertexElement.AppendAligned, InputClassification slotClass = .PerVertexData, uint32 instanceStepRate = 0) { Format = format; SemanticName = semanticName; diff --git a/GlitchyEngine/src/World/Components.bf b/GlitchyEngine/src/World/Components.bf index ff00721..a947879 100644 --- a/GlitchyEngine/src/World/Components.bf +++ b/GlitchyEngine/src/World/Components.bf @@ -303,4 +303,39 @@ namespace GlitchyEngine.World DestroyInstanceFunction(&this); } } + + struct SceneLight + { + public enum LightType + { + Directional, + Spot, + Point + } + + private LightType _type = .Directional; + + private float _illuminance = 10.0f; + + private ColorRGB _color = .(1, 1, 1); + + public LightType LightType => _type; + + public ColorRGB Color + { + get => _color; + set mut => _color = value; + } + + public float Illuminance + { + get => _illuminance; + set mut => _illuminance = value; + } + } + + struct LightComponent + { + public SceneLight SceneLight; + } } \ No newline at end of file diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 9dc60ee..3dd6834 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -74,6 +74,11 @@ namespace GlitchyEngine.World Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform); } + for (var (entity, transform, camera) in _ecsWorld.Enumerate()) + { + Renderer.Submit(camera.SceneLight, transform.WorldTransform); + } + Renderer.EndScene(); // Sprite renderer