From 2d37c574d61a0c3b2d605b8ac35b7a46ac6545a5 Mon Sep 17 00:00:00 2001 From: Halbear Date: Sun, 14 Jun 2026 13:39:49 +0100 Subject: [PATCH] non functional deferred rendering and also camera paths and instanced GUIs --- .../shaders/lighting_frag.glsl | 12 + .../shaders/lighting_vertex.glsl | 8 + .../shaders/scene_fragment.glsl | 6 +- .../shaders/scene_opaque_fragment.glsl | 6 +- .../shaders/scene_translucent_fragment.glsl | 6 +- .../Terrain4J/EngineCore/Display/Render.java | 28 +- .../EngineCore/Logic/EngineConfig.java | 16 ++ .../Terrain4J/EngineCore/Main/GameCore.java | 172 +++--------- .../EngineCore/Main/Scene/Camera.java | 83 ++++-- .../EngineCore/Main/Scene/CameraFrame.java | 20 ++ .../EngineCore/Main/Scene/GUIOverlay.java | 8 + .../Main/Scene/GUIs/PerformanceOverlay.java | 154 ++++++++++ .../EngineCore/Main/Scene/Scene.java | 73 ++++- .../EngineCore/Threads/RenderThread.java | 2 +- .../EngineCore/Vulkan/GUI/GuiRenderer.java | 2 - .../Rendering/Deferred/LightRenderer.java | 213 ++++++++++++++ .../MultiRenderTargetAttachments.java | 51 ++++ .../Rendering/Pipeline/DefaultPipeline.java | 2 +- .../Rendering/Pipeline/Images/Attachment.java | 7 +- .../Rendering/Pipeline/PipelineBuildInfo.java | 9 + .../Rendering/PostProcessing/PostProcess.java | 80 +++--- .../Rendering/Projection/Project3D.java | 13 +- .../DisplayToScreen/SceneRender.java | 264 ++++++++++++------ .../DisplayToScreen/SceneRenderer.java | 3 + terrain4j.properties | 10 +- 25 files changed, 933 insertions(+), 315 deletions(-) create mode 100644 resources/EngineResources/shaders/lighting_frag.glsl create mode 100644 resources/EngineResources/shaders/lighting_vertex.glsl create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/CameraFrame.java create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIOverlay.java create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/LightRenderer.java create mode 100644 src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/MultiRenderTargetAttachments.java diff --git a/resources/EngineResources/shaders/lighting_frag.glsl b/resources/EngineResources/shaders/lighting_frag.glsl new file mode 100644 index 0000000..83e88bf --- /dev/null +++ b/resources/EngineResources/shaders/lighting_frag.glsl @@ -0,0 +1,12 @@ +#version 450 + +layout(location = 0) in vec2 inTextCoord; + +layout(location = 0) out vec4 outFragColor; + +layout(set = 0, binding = 0) uniform sampler2D albedoSampler; +layout(set = 0, binding = 1) uniform sampler2D depthSampler; + +void main() { + outFragColor = vec4(texture(albedoSampler, inTextCoord).rgb, 1.0); +} diff --git a/resources/EngineResources/shaders/lighting_vertex.glsl b/resources/EngineResources/shaders/lighting_vertex.glsl new file mode 100644 index 0000000..4a325b2 --- /dev/null +++ b/resources/EngineResources/shaders/lighting_vertex.glsl @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) out vec2 outTextCoord; + +void main() { + outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); + gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * - 2.0f + 1.0f, 0.0f, 1.0f); +} diff --git a/resources/EngineResources/shaders/scene_fragment.glsl b/resources/EngineResources/shaders/scene_fragment.glsl index a1387ad..2e3acc4 100644 --- a/resources/EngineResources/shaders/scene_fragment.glsl +++ b/resources/EngineResources/shaders/scene_fragment.glsl @@ -3,7 +3,7 @@ const int MAX_TEXTURES = 500; layout(location = 0) in vec2 inTextCoords; -layout(location = 0) out vec4 outFragColor; +layout(location = 0) out vec4 outAlbedo; struct Material{ vec4 diffuseColor; @@ -28,8 +28,8 @@ void main() if(material.hasTexture == 1){ vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords); if(texColor.a < 0.1){discard;} - outFragColor = texColor; + outAlbedo = texColor; } else{ - outFragColor = material.diffuseColor; + outAlbedo = material.diffuseColor; } } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_opaque_fragment.glsl b/resources/EngineResources/shaders/scene_opaque_fragment.glsl index 847ccf1..9becc74 100644 --- a/resources/EngineResources/shaders/scene_opaque_fragment.glsl +++ b/resources/EngineResources/shaders/scene_opaque_fragment.glsl @@ -3,7 +3,7 @@ const int MAX_TEXTURES = 500; layout(location = 0) in vec2 inTextCoords; -layout(location = 0) out vec4 outFragColor; +layout(location = 0) out vec4 outAlbedo; struct Material{ vec4 diffuseColor; @@ -28,8 +28,8 @@ void main() if(material.hasTexture == 1){ vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords); if(texColor.a < 0.9){discard;} - outFragColor = texColor; + outAlbedo = texColor; } else{ - outFragColor = material.diffuseColor; + outAlbedo = material.diffuseColor; } } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_translucent_fragment.glsl b/resources/EngineResources/shaders/scene_translucent_fragment.glsl index 3f38520..e1017ed 100644 --- a/resources/EngineResources/shaders/scene_translucent_fragment.glsl +++ b/resources/EngineResources/shaders/scene_translucent_fragment.glsl @@ -3,7 +3,7 @@ const int MAX_TEXTURES = 500; layout(location = 0) in vec2 inTextCoords; -layout(location = 0) out vec4 outFragColor; +layout(location = 0) out vec4 outAlbedo; struct Material{ vec4 diffuseColor; @@ -28,8 +28,8 @@ void main() if(material.hasTexture == 1){ vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords); if(texColor.a < 0.05 || texColor.a >= 0.9){discard;} - outFragColor = texColor; + outAlbedo = texColor; } else{ - outFragColor = material.diffuseColor; + outAlbedo = material.diffuseColor; } } \ No newline at end of file diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java index 1138a2c..41bbdb5 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Render.java @@ -6,6 +6,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.InitData; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiRenderer; import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiTexture; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Deferred.LightRenderer; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing.PostProcess; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.*; @@ -43,6 +44,7 @@ public class Render { private final Queue.PresentQueue PresentQueue; private final Semaphore[] RenderCompleteSemaphores; private final SceneRenderer sceneRender; + private final LightRenderer lightRenderer; private final PostProcess PostProcessor; private final SwapChainRender swapChainRender; private final GuiRenderer GuiRender; @@ -83,7 +85,8 @@ public class Render { RenderCompleteSemaphores[i] = new Semaphore(RendererContext); } sceneRender = new SceneRender(RendererContext); - PostProcessor = new PostProcess(RendererContext,sceneRender.GetAttachmentColour()); + lightRenderer = new LightRenderer(RendererContext, sceneRender.GetMRTAttachments().GetAllAttachments()); + PostProcessor = new PostProcess(RendererContext,sceneRender.GetCurrentDeferred() ? lightRenderer.GetColourAttachment() : sceneRender.GetAttachmentColour()); GuiRender = new GuiRenderer(engineInstance, RendererContext, GraphicsQueue, PostProcessor.GetAttachment()); swapChainRender = new SwapChainRender(RendererContext,PostProcessor.GetAttachment()); textureCache = new TextureCache(); @@ -139,6 +142,7 @@ public class Render { sceneRender.cleanup(RendererContext); PostProcessor.CleanUp(RendererContext); swapChainRender.CleanUp(RendererContext); + lightRenderer.CleanUp(RendererContext); GuiRender.CleanUp(RendererContext); Logger.debug("Dynamic Renderer Cleaned up"); Arrays.asList(RenderCompleteSemaphores).forEach(i->i.cleanup(RendererContext)); @@ -159,14 +163,7 @@ public class Render { } public void render(EngineInstance engineInstance){ SwapChain swapChain = RendererContext.GetSwapChain(); - WaitForFence(CurrentFrame); //problem child found - var CommandPool = CommandPools[CurrentFrame]; - var CommandBuffer = CommandBuffers[CurrentFrame]; - RecordingStart(CommandPool, CommandBuffer); - - sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame); - PostProcessor.Render(RendererContext,CommandBuffer,sceneRender.GetAttachmentColour()); - GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment()); + WaitForFence(CurrentFrame); int ImageIndex; if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame])) < 0){ @@ -174,6 +171,16 @@ public class Render { return; } + var CommandPool = CommandPools[CurrentFrame]; + var CommandBuffer = CommandBuffers[CurrentFrame]; + RecordingStart(CommandPool, CommandBuffer); + + sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame); + lightRenderer.Render(RendererContext,CommandBuffer,sceneRender.GetMRTAttachments()); + PostProcessor.Render(RendererContext,CommandBuffer,sceneRender.GetCurrentDeferred() ? lightRenderer.GetColourAttachment() : sceneRender.GetAttachmentColour()); + + GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment()); + swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex); RecordingStop(CommandBuffer); @@ -203,7 +210,8 @@ public class Render { VkExtent2D extend = RendererContext.GetSwapChain().GetSwapChainExtent(); engineInstance.scene().GetProjection().Resize(extend.width(),extend.height()); sceneRender.Resize(engineInstance,RendererContext); - PostProcessor.Resize(RendererContext,sceneRender.GetAttachmentColour()); + lightRenderer.Resize(RendererContext,sceneRender.GetMRTAttachments().GetAllAttachments()); + PostProcessor.Resize(RendererContext,sceneRender.GetCurrentDeferred() ? lightRenderer.GetColourAttachment() : sceneRender.GetAttachmentColour()); GuiRender.Resize(RendererContext,PostProcessor.GetAttachment()); swapChainRender.Resize(RendererContext,PostProcessor.GetAttachment()); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java index 22cb4b5..edc07aa 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java @@ -1,6 +1,7 @@ package net.halbear.Terrain4J.EngineCore.Logic; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRender; import org.tinylog.Logger; import java.io.*; @@ -69,7 +70,11 @@ public class EngineConfig { public int CPU_CORE_COUNT = 0; public String CPU_DETAILS = ""; public boolean AlphaToCoverage = false; + public boolean CompatibilityMode = false; + public Renderer renderer = Renderer.Forward; + public void SetRenderer(Renderer renderer){this.renderer = renderer;} + public boolean DeferredRendering(){return renderer == Renderer.Deferred;} public boolean AlphaToCoverage(){return AlphaToCoverage;} public void SetAlphaToCoverage(boolean AlphaToCoverage){this.AlphaToCoverage = AlphaToCoverage;} public String GetGPU(){return GPU_NAME;} @@ -79,6 +84,8 @@ public class EngineConfig { CPU_CORE_COUNT = CoreCount; CPU_DETAILS = CPU_NAME + " with " + CPU_CORE_COUNT + " Threads"; } + public boolean CompatibilityMode(){return CompatibilityMode;} + public void SetCompatibilitMode(boolean compatibilityMode){this.CompatibilityMode = compatibilityMode;} public int GetCoreCount(){return CPU_CORE_COUNT;} public String GetCPUName(){return CPU_NAME;} public String GetCPUDetails(){return CPU_DETAILS;} @@ -116,6 +123,11 @@ public class EngineConfig { } } + public enum Renderer{ + Forward, + Deferred + } + public enum AntiAliasType{ NONE, FXAA, @@ -203,6 +215,10 @@ public class EngineConfig { zNearPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_near_plane", 1.0f).toString())); zFarPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_far_plane", 100.0f).toString())); AAValue = (Integer.parseInt(EngineConfigVar.getOrDefault("anti_alias_mode", 1).toString())); + renderer = Integer.parseInt(EngineConfigVar.getOrDefault("Renderer", 1).toString()) == 0 ? Renderer.Forward: Renderer.Deferred; + CompatibilityMode = Boolean.parseBoolean(EngineConfigVar.getOrDefault("compatibility_mode", false).toString()); + AlphaToCoverage = Boolean.parseBoolean(EngineConfigVar.getOrDefault("AlphaToCoverage", false).toString()); + SceneRender.SetDualPassRendering(Boolean.parseBoolean(EngineConfigVar.getOrDefault("DualPassRendering", true).toString())); switch(AAValue){ case 0: AAMode = AntiAliasType.NONE; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java index 0cc6ee9..bf88f06 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -3,7 +3,6 @@ package net.halbear.Terrain4J.EngineCore.Main; import imgui.ImGui; import imgui.ImGuiIO; import imgui.ImGuiViewport; -import imgui.ImVec2; import imgui.flag.ImGuiCond; import imgui.flag.ImGuiWindowFlags; import net.halbear.Terrain4J.EngineCore.Audio.AudioManager; @@ -16,6 +15,7 @@ import net.halbear.Terrain4J.EngineCore.Input.MouseListener; import net.halbear.Terrain4J.EngineCore.Logic.*; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader; import net.halbear.Terrain4J.EngineCore.Main.Scene.*; +import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.PerformanceOverlay; import net.halbear.Terrain4J.EngineCore.Profiling.CPUMonitor; import net.halbear.Terrain4J.EngineCore.Profiling.GPUProfiler; import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiTexture; @@ -25,6 +25,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRe import org.joml.Vector2f; import org.joml.Vector3f; import org.lwjgl.openal.AL11; +import org.tinylog.Logger; import java.util.ArrayList; import java.util.List; @@ -48,22 +49,22 @@ public class GameCore implements GameLogic { private List rotatingAngles = new ArrayList<>(); private List Velocities = new ArrayList<>(); private Actor CubeActor; - private List CubeActors = new ArrayList<>(); - private List entities = new ArrayList<>(); - private List particleActors = new ArrayList<>(); + public List CubeActors = new ArrayList<>(); + public List entities = new ArrayList<>(); + public List particleActors = new ArrayList<>(); private Vector2f LastMousePos = new Vector2f(0,0); private int Ticks = 0; private int GUI_MODE = 0; private GuiTexture guiTexture; - private List PerformanceMetrics = new ArrayList<>(); - private List SettingPerformanceMetrics = new ArrayList<>(); - private boolean FetchingMetrics = false; - private boolean ChangeGraphicsSettings = false; - private int NextAAMode = -1; - private long LastFrameTime = 0; - private long CoolDown = 1000; - private ModelData MusicParticle; - private ModelData radio; + public List PerformanceMetrics = new ArrayList<>(); + public List SettingPerformanceMetrics = new ArrayList<>(); + public boolean FetchingMetrics = false; + public boolean ChangeGraphicsSettings = false; + public int NextAAMode = -1; + public long LastFrameTime = 0; + public long CoolDown = 1000; + public ModelData MusicParticle; + public ModelData radio; @Override public void cleanup() { @@ -115,12 +116,19 @@ public class GameCore implements GameLogic { models.add(MusicParticle); models.add(radio); Camera camera = scene.GetCamera(); + scene.AddCameraFrame("Default", new CameraFrame(new Vector3f(-120.10f,136.83f,-62.63f),new Vector3f(-1.90f,78.09f,0),scene.GetCamera().GetFOV(),"Second")); + scene.AddCameraFrame("Second", new CameraFrame(new Vector3f(-40.26f,141.08f,-72.12f),new Vector3f(-2.40f,143,0.0f),scene.GetCamera().GetFOV(),"Third")); + scene.AddCameraFrame("Third", new CameraFrame(new Vector3f(10.85f,149.56f,-14.10f),new Vector3f(2.5f,36.37f,0.00f),scene.GetCamera().GetFOV(),"Fourth")); + scene.AddCameraFrame("Fourth", new CameraFrame(new Vector3f(40.0f, 155.0f, -42.0f),new Vector3f(10,90,0),scene.GetCamera().GetFOV(),"Fifth")); + scene.AddCameraFrame("Fifth", new CameraFrame(new Vector3f(64.92f,158.06f,-35.25f),new Vector3f(-11.20f,156.5f,0.0f),scene.GetCamera().GetFOV(),"Sixth")); + scene.AddCameraFrame("Sixth", new CameraFrame(new Vector3f(94.52f,172.54f,47.57f),new Vector3f(4.3f,329.27f,0.0f),scene.GetCamera().GetFOV(),"NO_FRAME")); camera.SetPosition(40.0f, 155.0f, -42.0f); //camera.SetPosition(0,0,0); camera.SetRotation((float) Math.toRadians(10.0f), (float) Math.toRadians(-90.0f),0); //camera.SetRotation(0,0,0); guiTexture = new GuiTexture("resources/EngineResources/Texture/DefaultTexture.png"); + Logger.debug("GUI TEXTURE CREATED, ID->[{}], PATH->[{}]",guiTexture.ID(),guiTexture.TexturePath()); List guiTextures = new ArrayList<>(); guiTextures.add(guiTexture); @@ -154,8 +162,8 @@ public class GameCore implements GameLogic { public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { float Multiplier = MOUSE_SENSITIVITY; Scene scene = engineInstance.scene(); - Window window = engineInstance.window(); Camera camera = scene.GetCamera(); + Window window = engineInstance.window(); MouseListener MouseInput = window.getMouseInput(); Vector2f CurrentMousePos = window.getMouseInput().getCurrentPos(); @@ -177,6 +185,7 @@ public class GameCore implements GameLogic { @Override public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { + engineInstance.scene().CameraTick(FrameDiffNanoSeconds); if(ChangeGraphicsSettings){ if(NextAAMode != -1){ EngineConfig.getInstance().SetRenderAAType(NextAAMode); @@ -248,129 +257,15 @@ public class GameCore implements GameLogic { | ImGuiWindowFlags.NoMove; ImGui.newFrame(); if(GUI_MODE == 0){ - double FrameTimeMS = (frameTimeNS/1000000.0); - double AverageGPUTimeMS = EngineConfig.LAST_AVERAGE_GPU_TIME/1000000.0; - ImGui.setNextWindowPos(0,0, ImGuiCond.Always); - //ImGui.setNextWindowSize(300,100); - ImGui.begin("FPS overlay",windowFlags); - ImGui.text("PERFORMANCE METRICS:"); - ImGui.separator(); - ImGui.text(String.format("Vulkan FPS: " + EngineConfig.FrameRate_RENDERTHREAD + "fps | FrameTime: %.2f" + "ms | Avg. GPU Time: %.3f" + "ms | TPS: " + EngineConfig.TPS_RENDERTHREAD,FrameTimeMS,AverageGPUTimeMS)); - ImGui.text(String.format("Primary Thread FPS: " + EngineConfig.FrameRate_PRIMARYTHREAD + "fps | GLFW Window FrameRate:" + EngineConfig.FrameRate_WINDOW + "fps | TPS: " + EngineConfig.TPS_PRIMARYTHREAD)); - ImGui.text(String.format("Main Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + "fps | TPS: " + EngineConfig.TPS_MAINENGINETHREAD)); - ImGui.text(String.format("Fast Thread FPS: " + EngineConfig.FrameRate_FASTENGINETHREAD + "fps | TPS: " + EngineConfig.TPS_FASTENGINETHREAD)); - ImGui.separator(); - ImGui.text("GRAPHICS SETTINGS:"); - ImGui.text(" "); - ImGui.text("Presets:"); - if(ImGui.button("Lowest")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = (0); - SceneRender.SetDualPassRendering(false); - EngineConfig.getInstance().SetAlphaToCoverage(false); - PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); - } - ImGui.sameLine(); - if(ImGui.button("Medium")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = (1); - SceneRender.SetDualPassRendering(true); - EngineConfig.getInstance().SetAlphaToCoverage(true); - PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); - } - ImGui.sameLine(); - if(ImGui.button("Highest")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = (4); - SceneRender.SetDualPassRendering(true); - EngineConfig.getInstance().SetAlphaToCoverage(false); - PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); - } - ImGui.text(" "); - ImGui.text("anti aliasing:"); - if(ImGui.button("No AA")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = (0); - } - ImGui.sameLine(); - if(ImGui.button("FXAA")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = (1); - } - ImGui.sameLine(); - if(ImGui.button("MSAAx2")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = (2); - } - ImGui.sameLine(); - if(ImGui.button("MSAAx4")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = (3); - } - ImGui.sameLine(); - if(ImGui.button("MSAAx8")){ - ChangeGraphicsSettings = true; - CoolDown = 2000; - NextAAMode = 4; - } - ImGui.text("pipeline:"); - if(ImGui.button("Single Pass")){ - ChangeGraphicsSettings = true; - CoolDown = 500; - SceneRender.SetDualPassRendering(false); - } - ImGui.sameLine(); - if(ImGui.button("dual Pass")){ - ChangeGraphicsSettings = true; - CoolDown = 500; - SceneRender.SetDualPassRendering(true); - } - if(ImGui.button("AlphaToCoverage False")){ - ChangeGraphicsSettings = true; - CoolDown = 500; - EngineConfig.getInstance().SetAlphaToCoverage(false); - PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); - } - ImGui.sameLine(); - if(ImGui.button("AlphaToCoverage True")){ - ChangeGraphicsSettings = true; - CoolDown = 500; - EngineConfig.getInstance().SetAlphaToCoverage(true); - PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); - } - ImGui.separator(); - ImGui.text("Level Tools:"); - if(ImGui.button("Spawn Radio")){ - JackOfAllTradesActor newJackentity = new JackOfAllTradesActor("Radio" + entities.size(), radio.ID(), new Vector3f(engineInstance.scene().GetCamera().GetPosition()),MusicParticle).SetAudio(engineInstance, "resources/EngineResources/audio/sounds/youusedtocallmeonyourcellphone.ogg").SetScale(0.01f); - entities.add(newJackentity); - engineInstance.scene().AddActor(newJackentity); - } - if(PerformanceMetrics.size() > 0) { - ImGui.text(" "); - ImGui.separator(); - for (int i = 0; i < PerformanceMetrics.size(); i++) { - - String[] memoryUsageMetrics = PerformanceMetrics.get(i); - for(int j = 0; j < memoryUsageMetrics.length; j++){ - ImGui.text(memoryUsageMetrics[j]); - } - ImGui.separator(); - ImGui.text(" "); - } - } - ImGui.end(); + PerformanceOverlay overlay = new PerformanceOverlay(); + overlay.RenderGUI(engineInstance,frameTimeNS,this); } else if (GUI_MODE == 1){ + ImGui.setNextWindowPos(0,0, ImGuiCond.Always); ImGui.setNextWindowSize(500,500); ImGui.begin("Test Window"); - ImGui.image(guiTexture.ID(),new ImVec2(300,300)); + ImGui.image(PrimaryRuntime.GetRenderThread().GetRenderer().GetGuiTexture(guiTexture.ID()),300,300); + Logger.debug(PrimaryRuntime.GetRenderThread().GetRenderer().GetGuiTexture(guiTexture.ID())); ImGui.end(); } else if (GUI_MODE == 2){ } @@ -393,13 +288,6 @@ public class GameCore implements GameLogic { @Override public void Update(EngineInstance engineInstance, long FrameDiffNanoSeconds) { float DeltaTime = (float)(FrameDiffNanoSeconds/16000000.0); - for(int i = 0; i < angles.size()/2; i++) { - - } - Ticks++; - if(Ticks == 1000){ - - } } @Override @@ -411,6 +299,10 @@ public class GameCore implements GameLogic { CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); CubeActors.get(i).UpdateModelMatrix(); } + Ticks++; + if(Ticks == 1000){ + engineInstance.scene().StartCameraTrack("Default","Second",24000); + } for(int i = 0; i < entities.size(); i++){ JackOfAllTradesActor entity = entities.get(i); entity.tick(engineInstance.scene()); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Camera.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Camera.java index 8dba0d1..8e2867b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Camera.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Camera.java @@ -1,7 +1,9 @@ package net.halbear.Terrain4J.EngineCore.Main.Scene; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import org.joml.Matrix4f; import org.joml.Vector3f; +import org.tinylog.Logger; public class Camera { private final Vector3f Direction; @@ -9,8 +11,10 @@ public class Camera { private final Vector3f Right; private final Vector3f Rotation; private final Vector3f Up; - private final Matrix4f ViewMatrix; + private final Matrix4f ViewMatrix; + private float FOV = (float) (60 * EngineConfig.DegToRad); private boolean Sprint; + int i = 0; public Camera(){ Direction = new Vector3f(); @@ -21,72 +25,97 @@ public class Camera { ViewMatrix = new Matrix4f(); } + public Camera SetFOV(float FOVdegrees){ + FOV = (float) (FOVdegrees * EngineConfig.DegToRad); + return this; + } + + public void SetCameraFrame(CameraFrame frameIn){ + FOV = frameIn.FOV(); + SetPosition(frameIn.Position().x,frameIn.Position().y,frameIn.Position().z); + SetRotation((float) (frameIn.Rotation().x * EngineConfig.DegToRad), (float) (frameIn.Rotation().y * EngineConfig.DegToRad), (float) (frameIn.Rotation().z * EngineConfig.DegToRad)); + } + + public float GetFOV(){return FOV;} + public void Sprint(boolean sprint){ this.Sprint = sprint; } - public void SetRotation(float x, float y, float z){Rotation.set(x,y,z); Recalculate();} + public void SetRotation(float x, float y, float z){Rotation.set(x,y,z);Recalculate();} - public void AddRotation(float x, float y, float z){Rotation.add(x,y,z); Recalculate();} + public void AddRotation(float x, float y, float z){Rotation.add(x,y,z);Recalculate(); } public void AddRotX(float x){Rotation.x += x; Recalculate();} public void AddRotY(float y){Rotation.y += y; Recalculate();} public void AddRotZ(float z){Rotation.z += z; Recalculate();} public Vector3f GetRotation(){return Rotation;} - public void SetPosition(float x, float y, float z){Position.set(x,y,z); Recalculate();} + public void SetPosition(float x, float y, float z){Position.set(x,y,z);Recalculate();} - public void AddPosition(float x, float y, float z){Position.add(x,y,z);Recalculate(); } + public void AddPosition(float x, float y, float z){Position.add(x,y,z);Recalculate();} public void AddPosX(float x){Position.x += x;Recalculate();} public void AddPosY(float y){Position.y += y;Recalculate();} public void AddPosZ(float z){Position.z += z;Recalculate();} - public Vector3f GetPosition(){return Position;} + public Vector3f GetPosition(){ + return Position;} public Matrix4f GetViewMatrix(){ return ViewMatrix; } public void MoveForward(float Distance){ - if(Sprint) Distance *=2; - ViewMatrix.positiveZ(Direction).negate().mul(Distance); + if(Sprint) Distance *= 2; + Matrix4f rotationMatrix = new Matrix4f().rotateX(Rotation.x).rotateY(Rotation.y).rotateZ(Rotation.z); + rotationMatrix.positiveZ(Direction).negate().mul(Distance); Position.add(Direction); Recalculate(); } + public void MoveBackward(float Distance){ - if(Sprint) Distance *=2; - ViewMatrix.positiveZ(Direction).negate().mul(Distance); + if(Sprint) Distance *= 2; + Matrix4f rotationMatrix = new Matrix4f().rotateX(Rotation.x).rotateY(Rotation.y).rotateZ(Rotation.z); + rotationMatrix.positiveZ(Direction).negate().mul(Distance); Position.sub(Direction); Recalculate(); } - public void MoveUp(float Distance){ - if(Sprint) Distance *=2; - ViewMatrix.positiveY(Up).negate().mul(Distance); - Position.sub(Up); - Recalculate(); - } - public void MoveDown(float Distance){ - if(Sprint) Distance *=2; - ViewMatrix.positiveY(Up).negate().mul(Distance); - Position.add(Up); - Recalculate(); - } + public void MoveLeft(float Distance){ - if(Sprint) Distance *=2; - ViewMatrix.positiveX(Right).negate().mul(Distance); + if(Sprint) Distance *= 2; + Matrix4f rotationMatrix = new Matrix4f().rotateX(Rotation.x).rotateY(Rotation.y).rotateZ(Rotation.z); + rotationMatrix.positiveX(Right).negate().mul(Distance); Position.add(Right); Recalculate(); } + public void MoveRight(float Distance){ - if(Sprint) Distance *=2; - ViewMatrix.positiveX(Right).negate().mul(Distance); + if(Sprint) Distance *= 2; + Matrix4f rotationMatrix = new Matrix4f().rotateX(Rotation.x).rotateY(Rotation.y).rotateZ(Rotation.z); + rotationMatrix.positiveX(Right).negate().mul(Distance); Position.sub(Right); Recalculate(); } + + public void MoveUp(float Distance){ + if(Sprint) Distance *= 2; + Matrix4f rotationMatrix = new Matrix4f().rotateX(Rotation.x).rotateY(Rotation.y).rotateZ(Rotation.z); + rotationMatrix.positiveY(Up).negate().mul(Distance); + Position.sub(Up); + Recalculate(); + } + + public void MoveDown(float Distance){ + if(Sprint) Distance *= 2; + Matrix4f rotationMatrix = new Matrix4f().rotateX(Rotation.x).rotateY(Rotation.y).rotateZ(Rotation.z); + rotationMatrix.positiveY(Up).negate().mul(Distance); + Position.add(Up); + Recalculate(); + } public void Recalculate(){ ViewMatrix.identity() .rotateX(Rotation.x) .rotateY(Rotation.y) - //.rotateZ(Rotation.z) + .rotateZ(Rotation.z) .translate(-Position.x, -Position.y, -Position.z); } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/CameraFrame.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/CameraFrame.java new file mode 100644 index 0000000..9d54974 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/CameraFrame.java @@ -0,0 +1,20 @@ +package net.halbear.Terrain4J.EngineCore.Main.Scene; + +import org.joml.Math; +import org.joml.Vector3f; + +public record CameraFrame(Vector3f Position, Vector3f Rotation, float FOV, String NextFrame) { + public CameraFrame Lerp(CameraFrame EndFrame, int CurrentTick, int TotalTickTime){ + double t = (double)CurrentTick/(double)TotalTickTime; + Vector3f newPosition = new Vector3f(0,0,0); + Vector3f newRotation = new Vector3f(0,0,0); + float newFOV = (float)Math.lerp(FOV, EndFrame.FOV(), t); + newPosition.x = (float)Math.lerp(Position.x, EndFrame.Position().x, t); + newPosition.y = (float)Math.lerp(Position.y, EndFrame.Position().y, t); + newPosition.z = (float)Math.lerp(Position.z, EndFrame.Position().z, t); + newRotation.x = (float)Math.lerp(Rotation.x, EndFrame.Rotation().x, t); + newRotation.y = (float)Math.lerp(Rotation.y, EndFrame.Rotation().y, t); + newRotation.z = (float)Math.lerp(Rotation.z, EndFrame.Rotation().z, t); + return new CameraFrame(newPosition, newRotation, newFOV, "NO_FRAME"); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIOverlay.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIOverlay.java new file mode 100644 index 0000000..30052a6 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIOverlay.java @@ -0,0 +1,8 @@ +package net.halbear.Terrain4J.EngineCore.Main.Scene; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; +import net.halbear.Terrain4J.EngineCore.Main.GameCore; + +public interface GUIOverlay { + void RenderGUI(EngineInstance engineInstance, long FrameTimeNS, GameCore parent); +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java new file mode 100644 index 0000000..641a4e9 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java @@ -0,0 +1,154 @@ +package net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs; + +import imgui.ImGui; +import imgui.flag.ImGuiCond; +import imgui.flag.ImGuiWindowFlags; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; +import net.halbear.Terrain4J.EngineCore.Main.GameCore; +import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; +import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIOverlay; +import net.halbear.Terrain4J.EngineCore.Main.Scene.JackOfAllTradesActor; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRender; +import org.joml.Vector3f; + +public class PerformanceOverlay implements GUIOverlay { + @Override + public void RenderGUI(EngineInstance engineInstance, long frameTimeNS, GameCore parent) { + int windowFlags = ImGuiWindowFlags.NoDecoration + | ImGuiWindowFlags.AlwaysAutoResize + | ImGuiWindowFlags.NoSavedSettings + | ImGuiWindowFlags.NoFocusOnAppearing + | ImGuiWindowFlags.NoNav + | ImGuiWindowFlags.NoMove; + double FrameTimeMS = (frameTimeNS/1000000.0); + double AverageGPUTimeMS = EngineConfig.LAST_AVERAGE_GPU_TIME/1000000.0; + ImGui.setNextWindowPos(0,0, ImGuiCond.Always); + //ImGui.setNextWindowSize(300,100); + ImGui.begin("FPS overlay",windowFlags); + ImGui.text("PERFORMANCE METRICS:"); + ImGui.separator(); + ImGui.text(String.format("Vulkan FPS: " + EngineConfig.FrameRate_RENDERTHREAD + "fps | FrameTime: %.2f" + "ms | Avg. GPU Time: %.3f" + "ms | TPS: " + EngineConfig.TPS_RENDERTHREAD,FrameTimeMS,AverageGPUTimeMS)); + ImGui.text(String.format("Primary Thread FPS: " + EngineConfig.FrameRate_PRIMARYTHREAD + "fps | GLFW Window FrameRate:" + EngineConfig.FrameRate_WINDOW + "fps | TPS: " + EngineConfig.TPS_PRIMARYTHREAD)); + ImGui.text(String.format("Main Thread FPS: " + EngineConfig.FrameRate_MAINENGINETHREAD + "fps | TPS: " + EngineConfig.TPS_MAINENGINETHREAD)); + ImGui.text(String.format("Fast Thread FPS: " + EngineConfig.FrameRate_FASTENGINETHREAD + "fps | TPS: " + EngineConfig.TPS_FASTENGINETHREAD)); + ImGui.separator(); + ImGui.text("GRAPHICS SETTINGS:"); + ImGui.text(" "); + ImGui.text("Presets:"); + if(ImGui.button("Lowest")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (0); + SceneRender.SetDualPassRendering(false); + EngineConfig.getInstance().SetAlphaToCoverage(false); + PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.sameLine(); + if(ImGui.button("Medium")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (1); + SceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetAlphaToCoverage(true); + PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.sameLine(); + if(ImGui.button("Highest")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (4); + SceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetAlphaToCoverage(false); + PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.text(" "); + ImGui.text("anti aliasing:"); + if(ImGui.button("No AA")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (0); + } + ImGui.sameLine(); + if(ImGui.button("FXAA")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (1); + } + ImGui.sameLine(); + if(ImGui.button("MSAAx2")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (2); + } + ImGui.sameLine(); + if(ImGui.button("MSAAx4")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (3); + } + ImGui.sameLine(); + if(ImGui.button("MSAAx8")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = 4; + } + ImGui.text("pipeline:"); + if(ImGui.button("Single Pass")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 500; + SceneRender.SetDualPassRendering(false); + } + ImGui.sameLine(); + if(ImGui.button("dual Pass")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 500; + SceneRender.SetDualPassRendering(true); + } + if(ImGui.button("Forward Rendering")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 500; + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Forward); + } + ImGui.sameLine(); + if(ImGui.button("Deferred Rendering")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 500; + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); + } + if(ImGui.button("AlphaToCoverage False")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 500; + EngineConfig.getInstance().SetAlphaToCoverage(false); + PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.sameLine(); + if(ImGui.button("AlphaToCoverage True")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 500; + EngineConfig.getInstance().SetAlphaToCoverage(true); + PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.separator(); + ImGui.text("Level Tools:"); + if(ImGui.button("Spawn Radio")){ + JackOfAllTradesActor newJackentity = new JackOfAllTradesActor("Radio" + parent.entities.size(), parent.radio.ID(), new Vector3f(engineInstance.scene().GetCamera().GetPosition()),parent.MusicParticle).SetAudio(engineInstance, "resources/EngineResources/audio/sounds/youusedtocallmeonyourcellphone.ogg").SetScale(0.01f); + parent.entities.add(newJackentity); + engineInstance.scene().AddActor(newJackentity); + } + if(parent.PerformanceMetrics.size() > 0) { + ImGui.text(" "); + ImGui.separator(); + for (int i = 0; i < parent.PerformanceMetrics.size(); i++) { + + String[] memoryUsageMetrics = parent.PerformanceMetrics.get(i); + for(int j = 0; j < memoryUsageMetrics.length; j++){ + ImGui.text(memoryUsageMetrics[j]); + } + ImGui.separator(); + ImGui.text(" "); + } + } + ImGui.end(); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java index 32ce908..2c87374 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java @@ -3,23 +3,88 @@ package net.halbear.Terrain4J.EngineCore.Main.Scene; import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Logic.*; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection.Project3D; +import org.joml.Vector3f; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class Scene { private final List Actors; + private final Map CameraFrames; private final Project3D Projection; private final Camera camera; + private String ActiveCameraFrame = "NO_FRAME"; + private String SetCameraFrame = "NO_FRAME"; + private boolean TransitionCameraFrame = false; + private CameraFrame LastCameraFrame; + private int TotalTransitionTicks = 1000; + private float CurrentTransitionTick = 0; public Scene(Window window) { Actors = new ArrayList<>(); + CameraFrames = new HashMap<>(); var EngConfig = EngineConfig.getInstance(); - Projection = new Project3D(EngConfig.GetFOV(),EngConfig.GetZNearPlane(), EngConfig.GetZFarPlane(), - window.getWidth(), window.getHeight()); camera = new Camera(); + LastCameraFrame = new CameraFrame(camera.GetPosition(),camera.GetRotation(),camera.GetFOV(), "NO_FRAME"); + Projection = new Project3D(camera.GetFOV(),EngConfig.GetZNearPlane(), EngConfig.GetZFarPlane(), + window.getWidth(), window.getHeight()); } + + public void CameraTick(long FrameDiffNanoSeconds){ + float FrameTimeMS = FrameDiffNanoSeconds/1000000.0f; + float DeltaTime = FrameTimeMS/(60.0f/240.0f); + if(TransitionCameraFrame && TotalTransitionTicks > CurrentTransitionTick && !Objects.equals(SetCameraFrame, "NO_FRAME")){ + float StartFOV = LastCameraFrame.FOV(); + Vector3f StartPos = LastCameraFrame.Position(); + Vector3f StartRot = LastCameraFrame.Rotation(); + CameraFrame StartFrame; + if(CameraFrames.containsKey(ActiveCameraFrame)){ + StartFrame = CameraFrames.get(ActiveCameraFrame); + } else StartFrame = new CameraFrame(StartPos,StartRot,StartFOV, "NO_FRAME"); + float EndFOV = camera.GetFOV(); + Vector3f EndPos = camera.GetPosition(); + Vector3f EndRot = camera.GetRotation(); + CameraFrame EndFrame; + if(CameraFrames.containsKey(SetCameraFrame)){ + EndFrame = CameraFrames.get(SetCameraFrame); + } else EndFrame = new CameraFrame(EndPos,EndRot,EndFOV, "NO_FRAME"); + CameraFrame LerpedFrame = StartFrame.Lerp(EndFrame, (int)CurrentTransitionTick, TotalTransitionTicks); + camera.SetCameraFrame(LerpedFrame); + if(LastCameraFrame.FOV() != LerpedFrame.FOV()){ + Projection.ChangeFOV(LerpedFrame.FOV()); + } + CurrentTransitionTick+= DeltaTime; + } else if (TransitionCameraFrame){ + CurrentTransitionTick = 0; + ActiveCameraFrame = SetCameraFrame; + if(!Objects.equals(CameraFrames.get(ActiveCameraFrame).NextFrame(), "NO_FRAME") && CameraFrames.containsKey(CameraFrames.get(ActiveCameraFrame).NextFrame())){ + SetCameraFrame = CameraFrames.get(ActiveCameraFrame).NextFrame(); + } else{ + TotalTransitionTicks = 1000; + TransitionCameraFrame = false; + } + } else{ + if(!Objects.equals(ActiveCameraFrame, SetCameraFrame) && !Objects.equals(SetCameraFrame, "NO_FRAME")){ + LastCameraFrame = new CameraFrame(camera.GetPosition(),camera.GetRotation(),camera.GetFOV(), "NO_FRAME"); + CurrentTransitionTick = 0; + TransitionCameraFrame = true; + } + } + } + + public Map GetCameraFrameReg(){return CameraFrames;} + public CameraFrame GetCameraFrame(String Name){return CameraFrames.get(Name);} + public Scene AddCameraFrame(String Name, CameraFrame frame){ + CameraFrames.put(Name,frame); + return this; + } + public void StartCameraTrack(String StartFrame, String EndFrame, int TickAmount){ + ActiveCameraFrame = StartFrame; + CurrentTransitionTick = 0; + TotalTransitionTicks = TickAmount; + SetCameraFrame = EndFrame; + } + public void SetActiveCameraFrame(String frameName){SetCameraFrame = frameName;} public Camera GetCamera(){return camera;} public void AddActor(Actor NewActor){Actors.add(NewActor);} public List GetActors(){return Actors;} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java index ce4e020..c999875 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java @@ -50,7 +50,7 @@ public class RenderThread extends EngineThread { EngineConfig.getInstance().SetMemoryProfiling(Profiling); EngineConfig.FrameRate_RENDERTHREAD = Frames; EngineConfig.TPS_RENDERTHREAD = TickFrames; - if(render.GetCurrentAAMode() != EngineConfig.getInstance().RenderAAType()){ + if(render.GetCurrentAAMode() != EngineConfig.getInstance().RenderAAType() || render.GetSceneRender().GetCurrentDeferred() != EngineConfig.getInstance().DeferredRendering()){ render.cleanup(); render = new Render(PrimaryRuntime.GetEngineInstance()); render.Initialise(initData); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/GUI/GuiRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/GUI/GuiRenderer.java index 685ea51..d2c5eb0 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/GUI/GuiRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/GUI/GuiRenderer.java @@ -149,7 +149,6 @@ public class GuiRenderer { DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device, descriptorID, 1, TextDescriptorSetLayout)[0]; Texture texture = textureCache.GetTexture(guiTexture.TexturePath()); descriptorSet.SetImage(device,texture.GetImageView(),FontsTextureSampler,TextDescriptorSetLayout.GetLayoutInfo().Binding()); - //Logger.debug("TEXTURE ID -> [{}] DESCRIPTOR SET -> [{}] TEXTURE -> [{}] IMAGE PATH -> [{}] TEXTURE SAMPLER ->[{}]",guiTexture.ID(),descriptorSet.GetVkDescriptorSet(),texture,guiTexture.TexturePath(),FontsTextureSampler); GuiTexturesMap.put(guiTexture.ID(),descriptorSet.GetVkDescriptorSet()); } } @@ -167,7 +166,6 @@ public class GuiRenderer { ByteBuffer buffer = imGuiIO.getFonts().getTexDataAsRGBA32(textureWidth,textureHeight); ImageSrc imageSrc = new ImageSrc(buffer,textureWidth.get(),textureHeight.get(),4); Texture FontsTexture = new Texture(VkCtx, "GUI_TEXTURE",imageSrc,VK_FORMAT_R8G8B8A8_SRGB); - var commandPool = new CommandPool(VkCtx, queue.GetQueueFamilyIndex(), false); var commandBuffer = new CommandBuffer(VkCtx, commandPool, true, true); commandBuffer.BeginRecording(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/LightRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/LightRenderer.java new file mode 100644 index 0000000..ddb20e5 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/LightRenderer.java @@ -0,0 +1,213 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Deferred; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.EmptyVertexBufferStruct; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Image; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PipelineBuildInfo; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing.SpecializationConstants; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.*; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView; +import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain; +import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryStack; +import org.lwjgl.util.shaderc.Shaderc; +import org.lwjgl.vulkan.*; + +import java.nio.LongBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.lwjgl.vulkan.VK13.*; + +public class LightRenderer { + private static final int COLOUR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT; + private static final String DESCRIPTOR_ID_ATTACHMENT = "LIGHT_DESC_ID_ATT"; + private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_frag.glsl"; + private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; + private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_vertex.glsl"; + private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; + + private final DescriptorSetLayout AttachmentDescriptorSetLayout; + private final VkClearValue ClearValueColour; + private final Pipeline pipeline; + private final TextureSampler textureSampler; + private Attachment AttachmentColour; + private VkRenderingAttachmentInfo.Buffer AttachmentInfoColour; + private VkRenderingInfo RenderingInfo; + + public LightRenderer(VulkanContext VkCtx, List attachmentList){ + ClearValueColour=VkClearValue.calloc().color( + c->c.float32(0,0.0f).float32(1,0.0f).float32(2,0.0f).float32(3,0.0f)); + AttachmentColour = CreateColourAttachment(VkCtx); + AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour,ClearValueColour); + RenderingInfo = CreateRenderInfo(AttachmentColour,AttachmentInfoColour); + + ShaderModule[] shaderModules = CreateShaderModules(VkCtx); + + var textureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,VK_BORDER_COLOR_INT_OPAQUE_BLACK,1,true); + textureSampler = new TextureSampler(VkCtx, textureSamplerInfo); + int AttachmentCount = attachmentList.size(); + DescriptorSetLayout.LayoutInformation[] descriptorSetLayouts = new DescriptorSetLayout.LayoutInformation[AttachmentCount]; + for(int i = 0; i < AttachmentCount; i++){ + descriptorSetLayouts[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i,1,VK_SHADER_STAGE_FRAGMENT_BIT); + } + AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, descriptorSetLayouts); + CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, attachmentList, textureSampler); + + pipeline = CreatePipeline(VkCtx,shaderModules,new DescriptorSetLayout[]{AttachmentDescriptorSetLayout}); + Arrays.asList(shaderModules).forEach(s->{s.CleanUp(VkCtx);}); + } + + private static Attachment CreateColourAttachment(VulkanContext VkCtx){ + SwapChain swapChain = VkCtx.GetSwapChain(); + VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent(); + return new Attachment(VkCtx,SwapChainExtent.width(),SwapChainExtent.height(), + COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + } + + private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment SrcAttachment, VkClearValue ClearValue){ + return VkRenderingAttachmentInfo.calloc(1) + .sType$Default() + .imageView(SrcAttachment.GetVkImageView().GetVulkanImageView()) + .imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) + .storeOp(VK_ATTACHMENT_STORE_OP_STORE) + .clearValue(ClearValue); + } + + private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){ + var VertexBufferStruct = new EmptyVertexBufferStruct(); + var BuildInfo = new PipelineBuildInfo(shaderModules,VertexBufferStruct.GetVertexInput(),COLOUR_FORMAT) + .SetDescriptorSetLayouts(descriptorSetLayouts) + .BlendingIsUsed(true) + .SetDepthWrite(false) + .SetDepthTest(false); + var PipeLine = new DefaultPipeline(VkCtx,BuildInfo); + VertexBufferStruct.CleanUp(); + return PipeLine; + } + + private static VkRenderingInfo CreateRenderInfo(Attachment ColourAttachment, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo){ + VkRenderingInfo renderingInfo; + try(var MemStack = MemoryStack.stackPush()){ + Image image = ColourAttachment.GetVkImage(); + VkExtent2D extent2D = VkExtent2D.calloc(MemStack).width(image.GetWidth()).height(image.GetHeight()); + var RenderArea = VkRect2D.calloc(MemStack).extent(extent2D); + + renderingInfo = VkRenderingInfo.calloc() + .sType$Default() + .renderArea(RenderArea) + .layerCount(1) + .pColorAttachments(ColourAttachmentInfo); + } + return renderingInfo; + } + + private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descriptorSetLayout, List attachments, TextureSampler textureSampler){ + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + Device device = VkCtx.GetDevice(); + DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSet(device, DESCRIPTOR_ID_ATTACHMENT, descriptorSetLayout); + List imageViews = new ArrayList<>(); + attachments.forEach(a->imageViews.add(a.GetVkImageView())); + descriptorSet.SetImages(device, imageViews, textureSampler, 0); + } + + private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx){ + if(EngineConfig.getInstance().RecompileShaders()){ + ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); + ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); + } + return new ShaderModule[]{ + new ShaderModule(VkCtx,VK_SHADER_STAGE_VERTEX_BIT,VERTEX_SHADER_FILE_SPV,null), + new ShaderModule(VkCtx,VK_SHADER_STAGE_FRAGMENT_BIT,FRAGMENT_SHADER_FILE_SPV,null) + }; + } + + public Attachment GetColourAttachment(){ + return AttachmentColour; + } + + public void Render(VulkanContext VkCtx, CommandBuffer commandBuffer, MultiRenderTargetAttachments MRTAttachments){ + try(var MemStack = MemoryStack.stackPush()){ + VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); + + VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttachmentColour.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT); + + List ColourAttachments = MRTAttachments.GetColourAttachments(); + int AttachmentCount = ColourAttachments.size(); + for(int i = 0; i < AttachmentCount; i++) { + Attachment colourAttachment = ColourAttachments.get(i); + VulkanUtils.ImageBarrier(MemStack, CommandHandle, colourAttachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT); + } + VulkanUtils.ImageBarrier(MemStack, CommandHandle, MRTAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_SHADER_READ_BIT, + VK_IMAGE_ASPECT_DEPTH_BIT); + + vkCmdBeginRendering(CommandHandle, RenderingInfo); + + vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipeline()); + + Image colourImage = AttachmentColour.GetVkImage(); + int width = colourImage.GetWidth(); + int height = colourImage.GetHeight(); + var Viewport = VkViewport.calloc(1,MemStack) + .x(0) + .y(height) + .height(-height) + .width(width) + .minDepth(0.0F) + .maxDepth(1.0F); + vkCmdSetViewport(CommandHandle, 0, Viewport); + var Scissor = VkRect2D.calloc(1,MemStack) + .extent(it -> it.width(width).height(height)) + .offset(it->it.x(0).y(0)); + vkCmdSetScissor(CommandHandle, 0, Scissor); + + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + LongBuffer DescriptorSets = MemStack.mallocLong(1) + .put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT).GetVkDescriptorSet()); + vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); + vkCmdDraw(CommandHandle,3,1,0,0); + vkCmdEndRendering(CommandHandle); + } + } + + public void Resize(VulkanContext VkCtx, List attachments){ + RenderingInfo.free(); + AttachmentInfoColour.free(); + AttachmentColour.CleanUp(VkCtx); + + AttachmentColour = CreateColourAttachment(VkCtx); + AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour, ClearValueColour); + RenderingInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour); + DescriptorSet descriptorSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT); + var ImageViews = new ArrayList(); + attachments.forEach(a->ImageViews.add(a.GetVkImageView())); + descriptorSet.SetImages(VkCtx.GetDevice(),ImageViews,textureSampler,0); + } + + public void CleanUp(VulkanContext VkCtx){ + pipeline.CleanUp(VkCtx); + AttachmentDescriptorSetLayout.CleanUp(VkCtx); + textureSampler.CleanUp(VkCtx); + RenderingInfo.free(); + AttachmentColour.CleanUp(VkCtx); + AttachmentInfoColour.free(); + ClearValueColour.free(); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/MultiRenderTargetAttachments.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/MultiRenderTargetAttachments.java new file mode 100644 index 0000000..767ef3a --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Deferred/MultiRenderTargetAttachments.java @@ -0,0 +1,51 @@ +package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Deferred; + +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; +import org.lwjgl.vulkan.VkExtent2D; + +import java.util.ArrayList; +import java.util.List; + +import static org.lwjgl.vulkan.VK13.*; + +//multiple render target attachments +public class MultiRenderTargetAttachments { + public static final int ALBEDO_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; + public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT; + private final List ColourAttachments; + private final Attachment DepthAttachment; + private final int Height; + private final int Width; + + public MultiRenderTargetAttachments(VulkanContext VkCtx){ + VkExtent2D extent2D = VkCtx.GetSwapChain().GetSwapChainExtent(); + Width = extent2D.width(); + Height = extent2D.height(); + ColourAttachments = new ArrayList<>(); + + var AlbedoAttachment = new Attachment(VkCtx, Width, Height, ALBEDO_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); + ColourAttachments.add(AlbedoAttachment); + + DepthAttachment = new Attachment(VkCtx, Width, Height, DEPTH_FORMAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + } + + public int GetWidth(){return Width;} + + public int GetHeight(){return Height;} + + public Attachment GetDepthAttachment(){return DepthAttachment;} + + public List GetColourAttachments(){return ColourAttachments;} + + public List GetAllAttachments(){ + List attachments = new ArrayList<>(ColourAttachments); + attachments.add(DepthAttachment); + return attachments; + } + + public void CleanUp(VulkanContext VkCtx){ + ColourAttachments.forEach(cA -> cA.CleanUp(VkCtx)); + DepthAttachment.CleanUp(VkCtx); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/DefaultPipeline.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/DefaultPipeline.java index 94a5fb7..e76fed5 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/DefaultPipeline.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/DefaultPipeline.java @@ -88,7 +88,7 @@ public class DefaultPipeline implements Pipeline { if(BuildInfo.GetDepthFormat() != VK_FORMAT_UNDEFINED){ DepthStencil = VkPipelineDepthStencilStateCreateInfo.calloc(MemStack) .sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) - .depthTestEnable(true) + .depthTestEnable(BuildInfo.performDepthTest()) .depthWriteEnable(BuildInfo.performDepthWrite()) .depthCompareOp(VK_COMPARE_OP_GREATER_OR_EQUAL) .depthBoundsTestEnable(false) diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java index 573efd1..21a729b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/Images/Attachment.java @@ -12,19 +12,20 @@ public class Attachment { private boolean DepthAttachment; public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){ - var ImageData = new Image.ImageData().Width(Width).Height(Height) - .Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT).Format(Format).MemoryUsage(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT).SampleCount(EngineConfig.getInstance().GetRenderSampleCount()); - VkImage = new Image(VkCtx, ImageData); + var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format).MemoryUsage(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT).SampleCount(EngineConfig.getInstance().GetRenderSampleCount()); int AspectMask = 0; if((Usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) > 0){ AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); DepthAttachment = false; } if((Usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) > 0){ + ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT); AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; DepthAttachment = true; } + VkImage = new Image(VkCtx, ImageData); var ImageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(AspectMask); VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), ImageViewData,DepthAttachment); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java index 78d8fd6..b624528 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java @@ -17,6 +17,7 @@ public class PipelineBuildInfo { private DescriptorSetLayout[] DescriptorSetLayouts; private boolean useBlend; private boolean DepthWrite = true; + private boolean DepthTest = true; private boolean DualPass = false; private boolean alphaToCoverage = false; @@ -36,6 +37,14 @@ public class PipelineBuildInfo { this.DualPass = DualPass; return this; } + + public PipelineBuildInfo SetDepthTest(boolean DepthTest){ + this.DepthTest = DepthTest; + return this; + } + + public boolean performDepthTest(){return DepthTest;} + public PipelineBuildInfo SetDepthWrite(boolean DepthWrite){ this.DepthWrite = DepthWrite; return this; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/PostProcess.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/PostProcess.java index aa39317..4212203 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/PostProcess.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/PostProcessing/PostProcess.java @@ -116,10 +116,12 @@ public class PostProcess { } private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descriptorSetLayout, Attachment attachment, TextureSampler textureSampler){ - DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); - Device device = VkCtx.GetDevice(); - DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device,DESCRIPTOR_ID_ATTACHMENT,1 , descriptorSetLayout)[0]; - descriptorSet.SetImage(device,attachment.GetVkImageView(),textureSampler,0); + if(!EngineConfig.getInstance().DeferredRendering() && attachment != null) { + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + Device device = VkCtx.GetDevice(); + DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device, DESCRIPTOR_ID_ATTACHMENT, 1, descriptorSetLayout)[0]; + descriptorSet.SetImage(device, attachment.GetVkImageView(), textureSampler, 0); + } } private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, SpecializationConstants specConstants){ @@ -138,43 +140,47 @@ public class PostProcess { } public void Render(VulkanContext VkCtx, CommandBuffer commandBuffer, Attachment SrcAttachment){ - try(var MemStack = MemoryStack.stackPush()){ - SwapChain swapChain = VkCtx.GetSwapChain(); - VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); + if(SrcAttachment != null) { + try (var MemStack = MemoryStack.stackPush()) { + SwapChain swapChain = VkCtx.GetSwapChain(); + VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); - VulkanUtils.ImageBarrier(MemStack, CommandHandle, SrcAttachment.GetVkImage().getVulkanImage(), - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_SHADER_READ_BIT,VK_IMAGE_ASPECT_COLOR_BIT); - VulkanUtils.ImageBarrier(MemStack,CommandHandle,ColourAttachment.GetVkImage().getVulkanImage(), - VK_IMAGE_LAYOUT_UNDEFINED,VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, - VK_ACCESS_2_NONE,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_IMAGE_ASPECT_COLOR_BIT); - vkCmdBeginRendering(CommandHandle,RenderingInfo); - vkCmdBindPipeline(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipeline()); + VulkanUtils.ImageBarrier(MemStack, CommandHandle, SrcAttachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT); + VulkanUtils.ImageBarrier(MemStack, CommandHandle, ColourAttachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT); + vkCmdBeginRendering(CommandHandle, RenderingInfo); + vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipeline()); - VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent(); - int Width = SwapChainExtent.width(); - int Height = SwapChainExtent.height(); - var Viewport = VkViewport.calloc(1,MemStack) - .x(0) - .y(Height) - .height(-Height) - .width(Width) - .minDepth(0.0f) - .maxDepth(1.0f); - vkCmdSetViewport(CommandHandle,0,Viewport); + VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent(); + int Width = SwapChainExtent.width(); + int Height = SwapChainExtent.height(); + var Viewport = VkViewport.calloc(1, MemStack) + .x(0) + .y(Height) + .height(-Height) + .width(Width) + .minDepth(0.0f) + .maxDepth(1.0f); + vkCmdSetViewport(CommandHandle, 0, Viewport); - var Scissor = VkRect2D.calloc(1,MemStack) - .extent(it->it.width(Width).height(Height)) - .offset(it->it.x(0).y(0)); - vkCmdSetScissor(CommandHandle,0,Scissor); + var Scissor = VkRect2D.calloc(1, MemStack) + .extent(it -> it.width(Width).height(Height)) + .offset(it -> it.x(0).y(0)); + vkCmdSetScissor(CommandHandle, 0, Scissor); - DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); - LongBuffer DescriptorSets = MemStack.mallocLong(2) - .put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT).GetVkDescriptorSet()) - .put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SCREEN_SIZE).GetVkDescriptorSet()); - vkCmdBindDescriptorSets(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); - vkCmdDraw(CommandHandle,3,1,0,0); - vkCmdEndRendering(CommandHandle); + DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); + if(descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT) != null && descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SCREEN_SIZE) != null) { + LongBuffer DescriptorSets = MemStack.mallocLong(2) + .put(0, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT).GetVkDescriptorSet()) + .put(1, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SCREEN_SIZE).GetVkDescriptorSet()); + vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipelineLayout(), 0, DescriptorSets, null); + vkCmdDraw(CommandHandle, 3, 1, 0, 0); + } + vkCmdEndRendering(CommandHandle); + } } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Projection/Project3D.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Projection/Project3D.java index 32f501a..cd8e0f0 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Projection/Project3D.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Rendering/Projection/Project3D.java @@ -3,11 +3,13 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection; import org.joml.Matrix4f; public class Project3D { - private final float FOV; // IT IS IN RADIANS!! REMEEEEMMMBER RADIANS!!!! PI/180!!!!! + private float FOV; // IT IS IN RADIANS!! REMEEEEMMMBER RADIANS!!!! PI/180!!!!! // there is a universal DegToRad conversion variable one can use in EngineConfig if they need to convert it private final Matrix4f ProjectionMatrix; private final float ZFarPlane; private final float ZNearPlane; + private int LastWidth; + private int LastHeight; public Project3D(float FOV, float zNear, float zFar, int Width, int Height){ this.FOV = FOV; @@ -15,6 +17,13 @@ public class Project3D { this.ZNearPlane = zNear; ProjectionMatrix = new Matrix4f(); Resize(Width, Height); + LastWidth = Width; + LastHeight = Height; + } + + public void ChangeFOV(float newFOV){ + FOV = newFOV; + Resize(LastWidth,LastHeight); } public float GetFOV(){ @@ -32,5 +41,7 @@ public class Project3D { public void Resize(int Width, int Height){ ProjectionMatrix.identity(); ProjectionMatrix.perspective(FOV, (float)Width/(float)Height, ZNearPlane, ZFarPlane, true); + LastWidth = Width; + LastHeight = Height; } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java index 1ff27fb..6ed24af 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRender.java @@ -6,6 +6,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Deferred.MultiRenderTargetAttachments; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Image; @@ -38,6 +39,14 @@ import static org.lwjgl.vulkan.VK13.*; public class SceneRender implements SceneRenderer {//dynamic rendering + private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment.glsl"; + private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_translucent_fragment.glsl"; + private static final String FRAGMENT_OPAQUE_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_opaque_fragment.glsl"; + private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; + private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV = FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL + ".spv"; + private static final String FRAGMENT_OPAQUE_SHADER_FILE_SPV = FRAGMENT_OPAQUE_SHADER_FILE_GLSL + ".spv"; + private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_vertex.glsl"; + private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; private static final String DESCRIPTOR_ID_MAT = "SCN_DESC_ID_MAT"; private static final String DESCRIPTOR_ID_PRJ = "SCN_DESC_ID_PRJ"; private static final String DESCRIPTOR_ID_TEXT = "SCN_DESC_ID_TEXT"; @@ -48,7 +57,6 @@ public class SceneRender implements SceneRenderer {//dynamic rendering private final DescriptorSetLayout descriptorLayoutTexture; private final DescriptorSetLayout descriptorLayoutVertexUniform; private final TextureSampler textureSampler; - private static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; private static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT; private final VkClearValue ClearValueDepth; @@ -70,20 +78,13 @@ public class SceneRender implements SceneRenderer {//dynamic rendering public static long GPUTIME = 0; public static long CYCLES = 0; private static boolean DualPassRendering = false; - - private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment.glsl"; - private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_translucent_fragment.glsl"; - private static final String FRAGMENT_OPAQUE_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_opaque_fragment.glsl"; - private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; - private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_SPV = FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL + ".spv"; - private static final String FRAGMENT_OPAQUE_SHADER_FILE_SPV = FRAGMENT_OPAQUE_SHADER_FILE_GLSL + ".spv"; - private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_vertex.glsl"; - private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; private final VulkanBuffer[] BufferViewMatrices; private Pipeline VkPipeline; private Pipeline VkPipelineOpaque; private Pipeline VkPipelineTranslucent; private Matrix4f ProjectionMatrix; + private MultiRenderTargetAttachments MRTAttachments; + private boolean Deferred = false; public static long GetGPUTimeNS(){ long time = 0; @@ -95,15 +96,29 @@ public class SceneRender implements SceneRenderer {//dynamic rendering return time; } + public boolean GetCurrentDeferred(){return Deferred;} + + public void UpdateDeferred(VulkanContext vulkanContext){ + Deferred = EngineConfig.getInstance().DeferredRendering(); + CreateRenderAttachments(vulkanContext); + CreatePipelines(vulkanContext); + } + + public void CreateRenderAttachments(VulkanContext vulkanContext){ + MRTAttachments = new MultiRenderTargetAttachments(vulkanContext); + AttachmentColour = CreateColourAttachment(vulkanContext); + AttachmentDepth = CreateDepthAttachment(vulkanContext); + AttachmentInfoDepth = Deferred ? CreateDeferredDepthAttachmentInfo(MRTAttachments, ClearValueDepth) : CreateDepthAttachmentInfo(AttachmentDepth, ClearValueDepth); + AttachmentInfoColour = Deferred ? CreateDeferredColourAttachmentInfo(MRTAttachments, ClearValueDepth) : CreateColourAttachmentInfo(AttachmentColour,ClearValueColour); + RenderInfo = Deferred ? CreateDeferredRenderInfo(vulkanContext, AttachmentInfoColour, AttachmentInfoDepth) : CreateRenderInfo(AttachmentColour, AttachmentInfoColour, AttachmentInfoDepth); + } + public SceneRender(VulkanContext vulkanContext){ + Deferred = EngineConfig.getInstance().DeferredRendering(); ClearValueColour = VkClearValue.calloc().color( c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f)); ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f)); - AttachmentColour = CreateColourAttachment(vulkanContext); - AttachmentDepth = CreateDepthAttachment(vulkanContext); - AttachmentInfoDepth = CreateDepthAttachmentInfo(AttachmentDepth, ClearValueDepth); - AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour,ClearValueColour); - RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour, AttachmentInfoDepth); + CreateRenderAttachments(vulkanContext); PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE)); @@ -126,6 +141,7 @@ public class SceneRender implements SceneRenderer {//dynamic rendering } public void CreatePipelines(VulkanContext vulkanContext){ + DescriptorSetLayout[] layouts = new DescriptorSetLayout[]{ descriptorLayoutVertexUniform, descriptorLayoutVertexUniform, @@ -134,11 +150,11 @@ public class SceneRender implements SceneRenderer {//dynamic rendering }; ShaderModule[] shaderModules = SceneRender.CreateShaderModules(vulkanContext,0); - VkPipeline = CreatePipeline(vulkanContext, shaderModules, layouts, true, false,EngineConfig.getInstance().AlphaToCoverage()); + VkPipeline = Deferred ? CreateDeferredPipeline(vulkanContext, shaderModules, layouts, true, false,EngineConfig.getInstance().AlphaToCoverage()) : CreatePipeline(vulkanContext, shaderModules, layouts, true, false,EngineConfig.getInstance().AlphaToCoverage()); shaderModules = SceneRender.CreateShaderModules(vulkanContext,1); - VkPipelineOpaque = CreatePipeline(vulkanContext, shaderModules, layouts, true, true,EngineConfig.getInstance().AlphaToCoverage()); + VkPipelineOpaque = Deferred ? CreateDeferredPipeline(vulkanContext, shaderModules, layouts, true, true,EngineConfig.getInstance().AlphaToCoverage()) : CreatePipeline(vulkanContext, shaderModules, layouts, true, true,EngineConfig.getInstance().AlphaToCoverage()); shaderModules = SceneRender.CreateShaderModules(vulkanContext,2); - VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,EngineConfig.getInstance().AlphaToCoverage()); + VkPipelineTranslucent = Deferred ? CreateDeferredPipeline(vulkanContext, shaderModules, layouts, false, true,EngineConfig.getInstance().AlphaToCoverage()) : CreatePipeline(vulkanContext, shaderModules, layouts, false, true,EngineConfig.getInstance().AlphaToCoverage()); Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext)); } @@ -158,6 +174,22 @@ public class SceneRender implements SceneRenderer {//dynamic rendering return new Attachment(VkCtx, SwapChainExtent.width(), SwapChainExtent.height(), COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); } + private static VkRenderingAttachmentInfo.Buffer CreateDeferredColourAttachmentInfo(MultiRenderTargetAttachments attachment, VkClearValue ClearValue){ + List colourAttachments = attachment.GetColourAttachments(); + int AttachmentCount = colourAttachments.size(); + VkRenderingAttachmentInfo.Buffer result = VkRenderingAttachmentInfo.calloc(AttachmentCount); + for(int i = 0; i < AttachmentCount; i++) { + result.get(i).sType$Default() + .imageView(attachment.GetColourAttachments().get(i).GetVkImageView().GetVulkanImageView()) + .imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) + .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) + .storeOp(VK_ATTACHMENT_STORE_OP_STORE) + .clearValue(ClearValue); + } + return result; + } + + private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue ClearValue){ return VkRenderingAttachmentInfo.calloc(1) .sType$Default() @@ -176,6 +208,16 @@ public class SceneRender implements SceneRenderer {//dynamic rendering } + private static VkRenderingAttachmentInfo CreateDeferredDepthAttachmentInfo(MultiRenderTargetAttachments DepthAttachment, VkClearValue clearValue){ + return VkRenderingAttachmentInfo.calloc() + .sType$Default() + .imageView(DepthAttachment.GetDepthAttachment().GetVkImageView().GetVulkanImageView()) + .imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) + .storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) + .clearValue(clearValue); + } + private static VkRenderingAttachmentInfo CreateDepthAttachmentInfo(Attachment DepthAttachment, VkClearValue clearValue){ return VkRenderingAttachmentInfo.calloc() .sType$Default() @@ -186,34 +228,6 @@ public class SceneRender implements SceneRenderer {//dynamic rendering .clearValue(clearValue); } - private static Attachment[] createDepthAttachments(VulkanContext VkCtx){ - SwapChain swapChain = VkCtx.GetSwapChain(); - int ImageCount = swapChain.GetImageCount(); - VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent(); - Attachment[] DepthAttachments = new Attachment[ImageCount]; - for(int i = 0; i < ImageCount; i++){ - DepthAttachments[i] = new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(), - DEPTH_FORMAT,VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); - } - return DepthAttachments; - } - - private static VkRenderingAttachmentInfo[] createDepthAttachmentsInfo(VulkanContext VkCtx, Attachment[] DepthAttachments, VkClearValue clearValue){ - SwapChain swapChain = VkCtx.GetSwapChain(); - int ImageCount = swapChain.GetImageCount(); - var Result = new VkRenderingAttachmentInfo[ImageCount]; - for(int i = 0; i < ImageCount; i++){ - var Attachments = VkRenderingAttachmentInfo.calloc() - .sType$Default() - .imageView(DepthAttachments[i].GetVkImageView().GetVulkanImageView()) - .imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) - .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) - .storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE) - .clearValue(clearValue); - Result[i] = Attachments; - } - return Result; - } private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){ if(EngineConfig.getInstance().RecompileShaders()){ @@ -226,6 +240,25 @@ public class SceneRender implements SceneRenderer {//dynamic rendering }; } + private static Pipeline CreateDeferredPipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean AlphaToCoverage){ + var vertexBufferStructure = new VertexBufferStructure(); + var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),MultiRenderTargetAttachments.ALBEDO_FORMAT) + .SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT) + .SetDepthWrite(DepthWrite) + .SetPushConstantRanges( + new PushConstantsRange[]{ + new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,0,VulkanUtils.MATRIX4X4_SIZE), + new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT,VulkanUtils.MATRIX4X4_SIZE,VulkanUtils.INT_SIZE) + }) + .SetDescriptorSetLayouts(DescriptorSetLayouts) + .BlendingIsUsed(DualRender ? !DepthWrite : true) + .SetDualPass(DualRender) + .SetAlphaToCoverage(AlphaToCoverage); + var pipeline = new DefaultPipeline(VkCtx, BuildInfo); + vertexBufferStructure.cleanup(); + return pipeline; + } + private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean AlphaToCoverage){ var vertexBufferStructure = new VertexBufferStructure(); var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),COLOUR_FORMAT) @@ -246,7 +279,7 @@ public class SceneRender implements SceneRenderer {//dynamic rendering } - public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int CurrentFrame){ + public void ForwardRender(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int CurrentFrame){ try(var MemStack = MemoryStack.stackPush()){ VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttachmentColour.GetVkImage().getVulkanImage(), @@ -269,16 +302,80 @@ public class SceneRender implements SceneRenderer {//dynamic rendering int width = ColourImage.GetWidth(); int height = ColourImage.GetHeight(); var Viewport = VkViewport.calloc(1,MemStack) - .x(0) - .y(height) - .height(-height) - .width(width) - .minDepth(0.0F) - .maxDepth(1.0F); + .x(0) + .y(height) + .height(-height) + .width(width) + .minDepth(0.0F) + .maxDepth(1.0F); vkCmdSetViewport(CommandHandle, 0, Viewport); var Scissor = VkRect2D.calloc(1,MemStack) - .extent(it -> it.width(width).height(height)) - .offset(it->it.x(0).y(0)); + .extent(it -> it.width(width).height(height)) + .offset(it->it.x(0).y(0)); + vkCmdSetScissor(CommandHandle, 0, Scissor); + + VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferViewMatrices[CurrentFrame],engineInstance.scene().GetCamera().GetViewMatrix(), 0); // here + DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator(); + LongBuffer DescriptorSets = MemStack.mallocLong(4) + .put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet()) + .put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW, CurrentFrame).GetVkDescriptorSet()) + .put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet()) + .put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()); + vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); + + RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false); + if(DualPassRendering) { + vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineTranslucent.GetVulkanPipeline()); + vkCmdSetViewport(CommandHandle, 0, Viewport); + vkCmdSetScissor(CommandHandle, 0, Scissor); + vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineTranslucent.GetVulkanPipelineLayout(), 0, DescriptorSets, null); + } + RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true); + + vkCmdEndRendering(CommandHandle); + GPUTIME += System.nanoTime() - InitialTime; + CYCLES++; + } + } + public void DeferredRender(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int CurrentFrame){ + try(var MemStack = MemoryStack.stackPush()){ + VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); + + List ColourAttachments = MRTAttachments.GetColourAttachments(); + int AttachmentCount = ColourAttachments.size(); + for(int i = 0; i < AttachmentCount; i++) { + Attachment colourAttachment = ColourAttachments.get(i); + VulkanUtils.ImageBarrier(MemStack, CommandHandle, colourAttachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_ACCESS_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + VulkanUtils.ImageBarrier(MemStack, CommandHandle, MRTAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, + VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_IMAGE_ASPECT_DEPTH_BIT); + + long InitialTime = System.nanoTime(); + vkCmdBeginRendering(CommandHandle, RenderInfo); + + vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipeline() : VkPipeline.GetVulkanPipeline()); + + int width = MRTAttachments.GetWidth(); + int height = MRTAttachments.GetHeight(); + var Viewport = VkViewport.calloc(1,MemStack) + .x(0) + .y(height) + .height(-height) + .width(width) + .minDepth(0.0F) + .maxDepth(1.0F); + vkCmdSetViewport(CommandHandle, 0, Viewport); + var Scissor = VkRect2D.calloc(1,MemStack) + .extent(it -> it.width(width).height(height)) + .offset(it->it.x(0).y(0)); vkCmdSetScissor(CommandHandle, 0, Scissor); VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferViewMatrices[CurrentFrame],engineInstance.scene().GetCamera().GetViewMatrix(), 0); // here @@ -305,6 +402,16 @@ public class SceneRender implements SceneRenderer {//dynamic rendering } } + public MultiRenderTargetAttachments GetMRTAttachments(){ + return MRTAttachments; + } + + public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int CurrentFrame){ + + if(Deferred) DeferredRender(engineInstance,vulkanContext,commandBuffer,modelsCache,materialsCache,CurrentFrame); + else ForwardRender(engineInstance,vulkanContext,commandBuffer,modelsCache,materialsCache,CurrentFrame); + } + private void RenderActors(EngineInstance instance, VkCommandBuffer CommandHandle, ModelsCache modelsCache, MaterialsCache materialsCache, boolean Transparent){ try(var MemStack = MemoryStack.stackPush()){ LongBuffer offsets = MemStack.mallocLong(1).put(0,0L); @@ -312,7 +419,6 @@ public class SceneRender implements SceneRenderer {//dynamic rendering Scene scene = instance.scene(); List Actors = scene.GetActors(); int ActorCount = Actors.size(); - List translucentObjects = new ArrayList<>(); for(int i = 0; i < ActorCount; i++){ if(i < Actors.size()) { var Actor = Actors.get(i); @@ -352,17 +458,16 @@ public class SceneRender implements SceneRenderer {//dynamic rendering PushConstBuffer.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE)); } + public void Resize(EngineInstance instance, VulkanContext VkCtx){ RenderInfo.free(); - AttachmentInfoColour.free(); + AttachmentInfoDepth.free(); + MRTAttachments.CleanUp(VkCtx); + if(Deferred)Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free); + else AttachmentInfoColour.free(); AttachmentColour.CleanUp(VkCtx); AttachmentDepth.CleanUp(VkCtx); - AttachmentInfoDepth.free(); - AttachmentColour = CreateColourAttachment(VkCtx); - AttachmentDepth = CreateDepthAttachment(VkCtx); - AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour, ClearValueColour); - AttachmentInfoDepth = CreateDepthAttachmentInfo(AttachmentDepth, ClearValueDepth); - RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour, AttachmentInfoDepth); + CreateRenderAttachments(VkCtx); VulkanUtils.CopyMatrixToBuffer(VkCtx, BufferProjectionMatrix, instance.scene().GetProjection().GetProjectionMatrix(),0); } @@ -378,6 +483,21 @@ public class SceneRender implements SceneRenderer {//dynamic rendering descriptorSet.SetImageArray(device,imageViews,textureSampler,0); } + private static VkRenderingInfo CreateDeferredRenderInfo(VulkanContext VkCtx, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo, VkRenderingAttachmentInfo DepthAttachmentInfo){ + VkRenderingInfo Result = VkRenderingInfo.calloc(); + SwapChain swapChain = VkCtx.GetSwapChain(); + VkExtent2D Extent = swapChain.GetSwapChainExtent(); + try(var MemStack = MemoryStack.stackPush()){ + var RenderArea = VkRect2D.calloc(MemStack).extent(Extent); + Result.sType$Default() + .renderArea(RenderArea) + .layerCount(1) + .pColorAttachments(ColourAttachmentInfo) + .pDepthAttachment(DepthAttachmentInfo); + } + return Result; + } + private static VkRenderingInfo CreateRenderInfo(Attachment ColourAttachment, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo, VkRenderingAttachmentInfo DepthAttachmentInfo){ VkRenderingInfo Result; try(var MemStack = MemoryStack.stackPush()){ @@ -394,23 +514,8 @@ public class SceneRender implements SceneRenderer {//dynamic rendering } return Result; } - private static VkRenderingAttachmentInfo.Buffer[] CreateColourAttachmentsInfo(VulkanContext vulkanContext, VkClearValue CLearValue){ - SwapChain swapChain = vulkanContext.GetSwapChain(); - int ImageCount = swapChain.GetImageCount(); - var result = new VkRenderingAttachmentInfo.Buffer[ImageCount]; - for(int i = 0; i < ImageCount; i++){ - var Attachments = VkRenderingAttachmentInfo.calloc(1) - .sType$Default() - .imageView(swapChain.GetVulkanImageView(i).GetVulkanImageView()) - .imageLayout(VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR) - .loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR) - .storeOp(VK_ATTACHMENT_STORE_OP_STORE) - .clearValue(CLearValue); - result[i] = Attachments; - } - return result; - } public void cleanup(VulkanContext VkCtx){ + VkPipeline.CleanUp(VkCtx); Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx)); RenderInfo.free(); @@ -418,6 +523,7 @@ public class SceneRender implements SceneRenderer {//dynamic rendering AttachmentColour.CleanUp(VkCtx); AttachmentDepth.CleanUp(VkCtx); AttachmentInfoDepth.free(); + MRTAttachments.CleanUp(VkCtx); MemoryUtil.memFree(PushConstBuffer); ClearValueDepth.free(); ClearValueColour.free(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRenderer.java index 56f93ff..1b89daf 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Vulkan/Structure/DisplayToScreen/SceneRenderer.java @@ -2,6 +2,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Deferred.MultiRenderTargetAttachments; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline; @@ -21,4 +22,6 @@ public interface SceneRenderer { public void LoadMaterials(VulkanContext VkCtx, MaterialsCache materialsCache, TextureCache textureCache); public void cleanup(VulkanContext VkCtx); public Attachment GetAttachmentColour(); + public MultiRenderTargetAttachments GetMRTAttachments(); + public boolean GetCurrentDeferred(); } diff --git a/terrain4j.properties b/terrain4j.properties index 3bc1448..a6f3743 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -21,13 +21,21 @@ cap_main_to_tickrate=true cap_fast_to_tickrate=true #Renderer Properties +#this is for devices that can't render more than 64 textures +compatibility_mode=false +#Renderer Settings +#0 = Forward rendering +#1 = Deferred rendering +Renderer=0 +AlphaToCoverage=false +DualPassRendering=true #AA settings #0=No AA #1=FXAA #2=MSAAx2 #3=MSAAx4 #4=MSAAx8 -anti_alias_mode=1 +anti_alias_mode=2 Debug_Shaders = false ShaderRecompiling = true #Vulkan Debugging toggle