diff --git a/GlitchyEditor/content/Shaders/SimpleTonemapping.hlsl b/GlitchyEditor/content/Shaders/SimpleTonemapping.hlsl new file mode 100644 index 0000000..1dcd64d --- /dev/null +++ b/GlitchyEditor/content/Shaders/SimpleTonemapping.hlsl @@ -0,0 +1,37 @@ +Texture2D CameraTarget : register(t0); +SamplerState CameraTargetSampler : register(s0); + +struct VS_IN +{ + float2 Position : POSITION; + float2 TexCoord : TEXCOORD0; +}; + +struct PS_IN +{ + float4 Position : SV_POSITION; + float2 TexCoord : TEXCOORD; +}; + +PS_IN VS(VS_IN input) +{ + PS_IN output; + + output.Position = float4(input.Position, 0, 1); + output.TexCoord = input.TexCoord; + + return output; +} + +float4 PS(PS_IN input) : SV_TARGET +{ + float4 rawColor = CameraTarget.Sample(CameraTargetSampler, input.TexCoord); + + float3 color = rawColor.rgb / (rawColor.rgb + 1.0f); + + color = pow(color, 1.0f / 2.2f); + + return float4(color, 1); +} + +#effect[VS = VS, PS = PS] diff --git a/GlitchyEditor/content/Shaders/simpleLight.hlsl b/GlitchyEditor/content/Shaders/simpleLight.hlsl index 077198e..652ec23 100644 --- a/GlitchyEditor/content/Shaders/simpleLight.hlsl +++ b/GlitchyEditor/content/Shaders/simpleLight.hlsl @@ -108,16 +108,8 @@ float4 PS(PS_IN input) : SV_TARGET float3 luminanceColor = LightColor * Illuminance; - float3 cook = (kd * diffuse + specular) * luminanceColor * n_dot_l; - - float3 final = cook; - - // Tone mapping // TODO: do in postprocessing - final = final / (final + 1.0f); - - // Gamma correction // TODO: do in postprocessing/hardware - final = pow(final, 1.0f / 2.2f); - + float3 final = (kd * diffuse + specular) * luminanceColor * n_dot_l; + #if OUTPUT == Inspect_NormalDistribution final = max(final - 10000000, nrmDist.xxx); #elif OUTPUT == Inspect_GeometryFunction diff --git a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf index eacfd74..f656e61 100644 --- a/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf +++ b/GlitchyEditor/src/EditWindows/ComponentEditWindow.bf @@ -61,6 +61,7 @@ namespace GlitchyEditor.EditWindows ShowComponentEditor("Camera", entity, => ShowCameraComponentEditor, => ShowComponentContextMenu); ShowComponentEditor("Sprite Renderer", entity, => ShowSpriteRendererComponentEditor, => ShowComponentContextMenu); ShowComponentEditor("Mesh Renderer", entity, => ShowMeshRendererComponentEditor, => ShowComponentContextMenu); + ShowComponentEditor("Mesh Renderer", entity, => ShowLightComponentEditor, => ShowComponentContextMenu); ShowAddComponentButton(entity); } @@ -349,6 +350,58 @@ namespace GlitchyEditor.EditWindows } } + private static void LabelColumn(StringView label) + { + ImGui.TextUnformatted(label); + ImGui.NextColumn(); + } + + private static void ShowLightComponentEditor(Entity entity, LightComponent* lightComponent) + { + ImGui.Columns(2); + defer ImGui.Columns(1); + + const String[?] strings = String[]("Directional", "Point", "Spot"); + + var light = ref lightComponent.SceneLight; + + String typeName = strings[light.LightType.Underlying]; + + LabelColumn("Type"); + + if (ImGui.BeginCombo("##Type", typeName.CStr())) + { + for (int i = 0; i < 3; i++) + { + bool isSelected = (typeName == strings[i]); + + if (ImGui.Selectable(strings[i], isSelected)) + { + light.LightType = (.)i; + } + + if (isSelected) + ImGui.SetItemDefaultFocus(); + } + + ImGui.EndCombo(); + } + + ImGui.NextColumn(); + LabelColumn("Color"); + + ColorRGB color = light.Color; + if (ImGui.ColorEdit3("##Color", ref color)) + light.Color = color; + + ImGui.NextColumn(); + LabelColumn("Illuminance"); + + float illuminance = light.Illuminance; + if (ImGui.DragFloat("##Illuminance", &illuminance, 0.1f, 0.0f, float.MaxValue)) + light.Illuminance = illuminance; + } + private static void ShowAddComponentButton(Entity entity) { static char8[128] searchBuffer = .(); diff --git a/GlitchyEditor/src/EditorLayer.bf b/GlitchyEditor/src/EditorLayer.bf index 3f9ad1c..2080f32 100644 --- a/GlitchyEditor/src/EditorLayer.bf +++ b/GlitchyEditor/src/EditorLayer.bf @@ -28,8 +28,8 @@ namespace GlitchyEditor Editor _editor ~ delete _; - RenderTarget2D _intermediateTarget ~ _?.ReleaseRef(); - RenderTarget2D _viewportTarget ~ _?.ReleaseRef(); + RenderTarget2D _cameraTarget ~ _.ReleaseRef(); + RenderTarget2D _viewportTarget ~ _.ReleaseRef(); SettingsWindow _settingsWindow = new .() ~ delete _; @@ -87,16 +87,18 @@ namespace GlitchyEditor camera.Camera.SetPerspective(MathHelper.ToRadians(75), 0.1f, 10000.0f); camera.Primary = true; camera.FixedAspectRatio = false; - camera.RenderTarget = _viewportTarget; + camera.RenderTarget = _cameraTarget; let transform = _cameraEntity.GetComponent(); - transform.Position = .(-1.5f, 1.5f, -2.5f); - transform.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0); + //transform.Position = .(-1.5f, 1.5f, -2.5f); + transform.Position = .(3.5f, 1.25f, 2.75f); + //transform.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(35), 0); + transform.RotationEuler = .(MathHelper.ToRadians(25), MathHelper.ToRadians(40), 0); _cameraEntity.AddComponent().Bind(); _cameraEntity.AddComponent(); } - { + /*{ _otherCameraEntity = _scene.CreateEntity("Other Camera Entity"); let camera = _otherCameraEntity.AddComponent(); camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 1000.0f); @@ -108,13 +110,13 @@ namespace GlitchyEditor _otherCameraEntity.AddComponent().Bind(); _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); + transform.RotationEuler = .(MathHelper.ToRadians(45), MathHelper.ToRadians(-100), 0); let light = lightNtt.AddComponent(); light.SceneLight.Illuminance = 10.0f; @@ -132,6 +134,17 @@ namespace GlitchyEditor light.SceneLight.Color = .(1.0f, 0.95f, 0.8f); } + { + var lightNtt = _scene.CreateEntity("My Sexy Sun 3"); + let transform = lightNtt.GetComponent(); + transform.Position = .(0, 0, 0); + transform.RotationEuler = .(MathHelper.ToRadians(20), MathHelper.ToRadians(-55), 0); + + let light = lightNtt.AddComponent(); + light.SceneLight.Illuminance = 10.0f; + light.SceneLight.Color = .(1.0f, 0.95f, 0.8f); + } + InitEditor(); TestEntitiesWithModels(); @@ -160,8 +173,11 @@ namespace GlitchyEditor mat.SetTexture("NormalTexture", normal); mat.SetTexture("MetallicTexture", metal); mat.SetTexture("RoughnessTexture", rough); - //mat.SetVariable("BaseColor", Vector4(1, 0, 1, 1)); - //mat.SetVariable("LightDir", Vector3(1, 1, 0).Normalized()); + + mat.SetVariable("AlbedoColor", ColorRGBA.White); + mat.SetVariable("NormalScaling", Vector2.One); + mat.SetVariable("MetallicFactor", 1.0f); + mat.SetVariable("RoughnessFactor", 1.0f); EcsEntity e = ModelLoader.LoadModel("content/Models/sphere.glb", myEffect, mat, _scene.[Friend]_ecsWorld, clips, "Sphere 1"); @@ -239,8 +255,11 @@ 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) {DepthStencilFormat = .D32_Float}); + _viewportTarget = new RenderTarget2D(RenderTarget2DDescription(.R8G8B8A8_UNorm, 100, 100)); _viewportTarget.SamplerState = SamplerStateManager.LinearClamp; } @@ -281,7 +300,7 @@ namespace GlitchyEditor //Renderer.EndScene(); - _scene.Update(gameTime); + _scene.Update(gameTime, _viewportTarget); RenderCommand.Clear(null, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0); @@ -305,9 +324,9 @@ namespace GlitchyEditor private bool OnImGuiRender(ImGuiRenderEvent event) { - //viewer.ViewTexture(Renderer.[Friend]_gBuffer.Normal); + viewer.ViewTexture(_cameraTarget); - ImGui.Begin("Test"); + /*ImGui.Begin("Test"); static bool cameraA = true; @@ -317,7 +336,7 @@ namespace GlitchyEditor _otherCameraEntity.GetComponent().Primary = !cameraA; } - ImGui.End(); + ImGui.End();*/ ImGui.Viewport* viewport = ImGui.GetMainViewport(); ImGui.DockSpaceOverViewport(viewport); @@ -383,6 +402,7 @@ namespace GlitchyEditor return; _viewportTarget.Resize(sizeX, sizeY); + _cameraTarget.Resize(sizeX, sizeY); _scene.OnViewportResize(sizeX, sizeY); } diff --git a/GlitchyEngine/src/Renderer/Renderer.bf b/GlitchyEngine/src/Renderer/Renderer.bf index 44458cf..24863bd 100644 --- a/GlitchyEngine/src/Renderer/Renderer.bf +++ b/GlitchyEngine/src/Renderer/Renderer.bf @@ -12,6 +12,7 @@ namespace GlitchyEngine.Renderer public Matrix ViewProjection; public Vector3 CameraPosition; public RenderTarget2D CameraTarget; + public RenderTarget2D CompositionTarget; } struct ObjectConstants @@ -26,6 +27,11 @@ namespace GlitchyEngine.Renderer 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 @@ -114,6 +120,7 @@ namespace GlitchyEngine.Renderer static GBuffer _gBuffer; static Effect TestFullscreenEffect; + static Effect s_tonemappingEffect; static BlendState _gBufferBlend; static BlendState _lightBlend; @@ -188,6 +195,7 @@ namespace GlitchyEngine.Renderer static void InitDeferredRenderer(EffectLibrary effectLibrary) { TestFullscreenEffect = effectLibrary.Load("content\\Shaders\\simpleLight.hlsl"); + s_tonemappingEffect = effectLibrary.Load("content\\Shaders\\SimpleTonemapping.hlsl"); s_fullscreenQuadGeometry = new GeometryBinding(); s_fullscreenQuadGeometry.SetPrimitiveTopology(.TriangleList); @@ -256,6 +264,7 @@ namespace GlitchyEngine.Renderer delete _gBuffer; s_fullscreenQuadGeometry.ReleaseRef(); + s_tonemappingEffect.ReleaseRef(); TestFullscreenEffect.ReleaseRef(); } @@ -268,7 +277,7 @@ namespace GlitchyEngine.Renderer //_sceneConstants.Update(); } - public static void BeginScene(Camera camera, Matrix transform, RenderTarget2D renderTarget) + public static void BeginScene(Camera camera, Matrix transform, RenderTarget2D renderTarget, RenderTarget2D finalTarget) { Debug.Profiler.ProfileRendererFunction!(); @@ -276,6 +285,7 @@ namespace GlitchyEngine.Renderer _sceneConstants.ViewProjection = viewProjection; _sceneConstants.CameraPosition = transform.Translation; _sceneConstants.CameraTarget = renderTarget; + _sceneConstants.CompositionTarget = finalTarget; } public static int SortMeshes(SubmittedMesh left, SubmittedMesh right) @@ -361,12 +371,19 @@ namespace GlitchyEngine.Renderer RenderCommand.SetRenderTarget(_sceneConstants.CameraTarget, 0, true); RenderCommand.BindRenderTargets(); + RenderCommand.Clear(_sceneConstants.CameraTarget, .Black); + RenderCommand.SetBlendState(_lightBlend); RenderCommand.SetDepthStencilState(_fullscreenDepthState); + // Scaling to make sure that only the part of the gbuffer that we actually used gets rendered into the viewport. + Vector2 scaling = Vector2(_sceneConstants.CameraTarget.Width, _sceneConstants.CameraTarget.Height) / (Vector2)_gBuffer.Size; + for (SubmittedLight light in _lights) { - Vector3 lightDir = light.Transform.Forward; + Debug.Profiler.ProfileRendererScope!("Draw Light"); + + Vector3 lightDir = -light.Transform.Forward; _gBuffer.Albedo.SamplerState = SamplerStateManager.PointClamp; @@ -378,11 +395,11 @@ namespace GlitchyEngine.Renderer TestFullscreenEffect.Variables["LightColor"].SetData(light.Light.Color); TestFullscreenEffect.Variables["Illuminance"].SetData(light.Light.Illuminance); - TestFullscreenEffect.Variables["LightDir"].SetData(-lightDir); + 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.Variables["Scaling"].SetData(scaling); TestFullscreenEffect.Bind(_context); @@ -390,31 +407,18 @@ namespace GlitchyEngine.Renderer RenderCommand.DrawIndexed(s_fullscreenQuadGeometry); } - RenderCommand.SetBlendState(_gBufferBlend); - _lights.Clear(); - /* - _gBuffer.Albedo.SamplerState = SamplerStateManager.PointClamp; + RenderCommand.SetBlendState(_gBufferBlend); + + RenderCommand.SetRenderTarget(_sceneConstants.CompositionTarget, 0, false); + RenderCommand.BindRenderTargets(); - 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); + // TODO: Postprocessing effects + s_tonemappingEffect.SetTexture("CameraTarget", _sceneConstants.CameraTarget); + s_tonemappingEffect.Bind(_context); + RenderCommand.DrawIndexed(s_fullscreenQuadGeometry); - 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(); } diff --git a/GlitchyEngine/src/World/Components.bf b/GlitchyEngine/src/World/Components.bf index a947879..fb4afe4 100644 --- a/GlitchyEngine/src/World/Components.bf +++ b/GlitchyEngine/src/World/Components.bf @@ -308,9 +308,9 @@ namespace GlitchyEngine.World { public enum LightType { - Directional, - Spot, - Point + Directional = 0, + Spot = 1, + Point = 2 } private LightType _type = .Directional; @@ -319,7 +319,11 @@ namespace GlitchyEngine.World private ColorRGB _color = .(1, 1, 1); - public LightType LightType => _type; + public LightType LightType + { + get => _type; + set mut => _type = value; + } public ColorRGB Color { diff --git a/GlitchyEngine/src/World/Scene.bf b/GlitchyEngine/src/World/Scene.bf index 3dd6834..5011c50 100644 --- a/GlitchyEngine/src/World/Scene.bf +++ b/GlitchyEngine/src/World/Scene.bf @@ -34,7 +34,7 @@ namespace GlitchyEngine.World { } - public void Update(GameTime gameTime) + public void Update(GameTime gameTime, RenderTarget2D finalTarget) { TransformSystem.Update(_ecsWorld); @@ -67,7 +67,7 @@ namespace GlitchyEngine.World if (primaryCamera != null) { // 3D render - Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget); + Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget, finalTarget); for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate()) {