diff --git a/resources/EngineResources/GLShaders/gui_fragment.glsl b/resources/EngineResources/GLShaders/gui_fragment.glsl new file mode 100644 index 0000000..76f39c9 --- /dev/null +++ b/resources/EngineResources/GLShaders/gui_fragment.glsl @@ -0,0 +1,13 @@ +#version 330 + +in vec2 fragTextCoords; +in vec4 fragColour; + +uniform sampler2D textureSampler; + +out vec4 outColour; + +void main() +{ + outColour = fragColour * texture(textureSampler, fragTextCoords); +} \ No newline at end of file diff --git a/resources/EngineResources/GLShaders/gui_vertex.glsl b/resources/EngineResources/GLShaders/gui_vertex.glsl new file mode 100644 index 0000000..c200ebd --- /dev/null +++ b/resources/EngineResources/GLShaders/gui_vertex.glsl @@ -0,0 +1,17 @@ +#version 330 + +layout (location=0) in vec2 inPos; +layout (location=1) in vec2 inTextCoords; +layout (location=2) in vec4 inColour; + +out vec2 fragTextCoords; +out vec4 fragColour; + +uniform vec2 scale; + +void main() +{ + fragTextCoords = inTextCoords; + fragColour = inColour; + gl_Position = vec4(inPos * scale + vec2(-1.0, 1.0), 0.0, 1.0); +} \ No newline at end of file diff --git a/resources/EngineResources/GLShaders/scene_frag.glsl b/resources/EngineResources/GLShaders/scene_frag.glsl index e2430b6..626f7c7 100644 --- a/resources/EngineResources/GLShaders/scene_frag.glsl +++ b/resources/EngineResources/GLShaders/scene_frag.glsl @@ -1,9 +1,25 @@ -#version 330 +#version 330 core -in vec3 outColour; -out vec4 fragColor; +in vec4 outPos; +in vec3 outNormal; +in vec3 outTangent; +in vec3 outBitangent; +in vec2 outTextCoords; + +out vec4 outAlbedo; + +struct Material +{ + vec4 diffuse; +}; + +uniform sampler2D textureSampler; +uniform Material material; void main() { - fragColor = vec4(outColour, 1.0); + vec4 texColor = texture(textureSampler,outTextCoords); + if(texColor.a < 0.4){discard;} + outAlbedo = texColor; + texColor = texColor + material.diffuse; } \ No newline at end of file diff --git a/resources/EngineResources/GLShaders/scene_vert.glsl b/resources/EngineResources/GLShaders/scene_vert.glsl index c2886ea..efef138 100644 --- a/resources/EngineResources/GLShaders/scene_vert.glsl +++ b/resources/EngineResources/GLShaders/scene_vert.glsl @@ -1,12 +1,30 @@ -#version 330 +#version 330 core -layout (location=0) in vec3 position; -layout (location=1) in vec3 colour; +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec3 inNormal; +layout (location = 2) in vec3 inTangent; +layout (location = 3) in vec3 inBitangent; +layout (location = 4) in vec2 inTextCoords; + +out vec4 outPos; +out vec3 outNormal; +out vec3 outTangent; +out vec3 outBitangent; +out vec2 outTextCoords; + +uniform mat4 projectionMatrix; +uniform mat4 modelMatrix; +uniform mat4 viewMatrix; -out vec3 outColour; void main() { - gl_Position = vec4(position, 1.0); - outColour = colour; + vec4 worldPos = modelMatrix * vec4(inPos,1); + gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(inPos, 1.0); + mat3 mNormal = transpose(inverse(mat3(modelMatrix))); + outPos = worldPos; + outNormal = mNormal * normalize(inNormal); + outTangent = mNormal * normalize(inTangent); + outBitangent = mNormal * normalize(inBitangent); + outTextCoords = inTextCoords; } \ No newline at end of file diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java index eb570e6..9b5c94b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/GLFWImageParser.java @@ -11,7 +11,9 @@ import static org.lwjgl.stb.STBImage.stbi_load; public class GLFWImageParser { private final ByteBuffer image; - private int GLFW_Width, GLFW_Height, ImageChannels; + private final int GLFW_Width; + private final int GLFW_Height; + private final int ImageChannels; GLFWImageParser(int width, int height, ByteBuffer image, int ImageChannels) { this.image = image; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java index 577180e..96cc71c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java @@ -3,97 +3,89 @@ package net.halbear.Terrain4J.EngineCore.Display; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.InitData; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.GLMesh; +import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3D; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GUI.OpenGLGuiRenderer; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.*; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Rendering.ForwardRenderer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Rendering.SceneRender; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiRenderer; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.TextureCache; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.MaterialsCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.ModelData; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.ModelsCache; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.SceneRenderer; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils; +import org.joml.Vector3f; import org.lwjgl.opengl.GL; import org.lwjgl.opengl.GLCapabilities; import org.tinylog.Logger; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent; import static org.lwjgl.glfw.GLFW.glfwSwapBuffers; import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL20.GL_SHADING_LANGUAGE_VERSION; public class OpenGLRenderer implements Renderer{ private int CurrentFrame; private boolean Resize = false; private List Materials = new ArrayList<>(); private List Models = new ArrayList<>(); - private final MaterialsCache materialsCache; + private MaterialsCache materialsCache; private TextureCache textureCache; private EngineConfig.AntiAliasType CurrentAAMode; - private final ModelsCache modelsCache; + private ModelsCache modelsCache; private final boolean Deferred; private float LastGamma = 0.8545f; private GLCapabilities glCapabilities = null; private SceneRender sceneRenderer = null; + private OpenGLGuiRenderer GuiRenderer; + + public OpenGLGuiRenderer GetGuiRenderer(){return GuiRenderer;} public OpenGLRenderer(EngineInstance engineInstance) { - textureCache = new TextureCache(); - materialsCache = new MaterialsCache(); - modelsCache = new ModelsCache(); Resize = false; CurrentAAMode = EngineConfig.getInstance().RenderAAType(); LastGamma = EngineConfig.getInstance().GetGamma(); Deferred = EngineConfig.getInstance().DeferredRendering(); } public static boolean LoggedNullCapabilities = false; + long frameTimeNS = 0; @Override public void render(EngineInstance engineInstance) { if(!Initialised){ + frameTimeNS = System.nanoTime(); glfwMakeContextCurrent(PrimaryRuntime.GetEngineInstance().window().getHandle()); glCapabilities = GL.createCapabilities(); + + Logger.debug("OpenGL version: [{}]", glGetString(GL_VERSION)); + Logger.debug("GLSL version: [{}]", glGetString(GL_SHADING_LANGUAGE_VERSION)); + glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.1f, 0.0f); if(!LoggedNullCapabilities){ Logger.debug("Creating OpenGL Context On Render Thread"); LoggedNullCapabilities = true; } + textureCache = new TextureCache(); + materialsCache = new MaterialsCache(); + modelsCache = new ModelsCache(); sceneRenderer = new ForwardRenderer(); + GuiRenderer = new OpenGLGuiRenderer(engineInstance.window()); Models.addAll(initData.Models()); - Models.forEach(model->{ - float Left = -0.9f * (float)Math.random(); - float right = Left + 0.1f + 0.25f * (float)Math.random(); - float bottom = -1.0f + 2 * (float)Math.random(); - float top = bottom + 0.1f + 0.25f * (float)Math.random(); - float middle = Left + (right - Left)/2; - float[] positions = new float[]{ - Left, top, 0.0f, - Left, bottom, 0.0f, - right, bottom, 0.0f, - right, top, 0.0f - }; - float[] colours = new float[]{ - 0.5f, 0.0f, 0.0f, - 0.0f, 0.5f, 0.0f, - 0.0f, 0.0f, 0.5f, - 0.0f, 0.5f, 0.5f, - }; - int[] indices = new int[]{ - 0, 1, 3, 3, 1, 2, - }; - GLMesh mesh = new GLMesh(positions, colours, indices); - modelsCache.addMesh(model.ID(),mesh); - }); + modelsCache.loadModels(initData.Models()); + modelsCache.LoadMaterials(initData.Materials(),textureCache); Initialised = true; } if(glCapabilities == null) { + frameTimeNS = System.nanoTime(); glfwMakeContextCurrent(engineInstance.window().getHandle()); glCapabilities = GL.createCapabilities(); + glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); if(!LoggedNullCapabilities){ Logger.debug("Creating OpenGL Context On Render Thread"); @@ -106,13 +98,21 @@ public class OpenGLRenderer implements Renderer{ glViewport(0, 0, window.getWidth(), window.getHeight()); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - sceneRenderer.Render(engineInstance.scene(), modelsCache); - + long newFrameTimeNS = System.nanoTime(); + long frameTime = newFrameTimeNS - frameTimeNS; + PrimaryRuntime.GetGameCore().RenderThreadInput(engineInstance,frameTime); + sceneRenderer.Render(engineInstance.scene(), modelsCache, textureCache); + GuiRenderer.Render(engineInstance.scene()); glfwSwapBuffers(engineInstance.window().getHandle()); + frameTimeNS = newFrameTimeNS; } - public TextureCache GetTextureCache(){return textureCache;} + public void Resize(int width, int height) { + GuiRenderer.Resize(width, height); + //sceneRenderer.Resize(width, height); + } + + public ITextureCache GetTextureCache(){return textureCache;} public MaterialsCache GetMaterialsCache(){return materialsCache;} public VulkanContext GetVulkanContext(){return null;} @@ -124,7 +124,7 @@ public class OpenGLRenderer implements Renderer{ public SceneRenderer GetSceneRender() { return null; } - private boolean Initialised = false; + public static boolean Initialised = false; private InitData initData = null; @Override public void Initialise(InitData initData) { @@ -143,7 +143,24 @@ public class OpenGLRenderer implements Renderer{ } public void cleanup() { + if(sceneRenderer != null) { + sceneRenderer.CleanUp(); + sceneRenderer = null; + } + if(GuiRenderer != null) { + GuiRenderer.CleanUp(); + GuiRenderer = null; + } + + modelsCache = null; + materialsCache = null; + textureCache = null; + glCapabilities = null; + Initialised = false; + LoggedNullCapabilities = false; + + glfwMakeContextCurrent(0); } @Override @@ -156,6 +173,4 @@ public class OpenGLRenderer implements Renderer{ } - - } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java index dc6e72d..35230bc 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java @@ -5,6 +5,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.InitData; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.SkyBox; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiRenderer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiTexture; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRendering.LightRenderer; @@ -39,7 +40,7 @@ import java.util.List; import static org.lwjgl.vulkan.VK13.*; public interface Renderer { - public TextureCache GetTextureCache(); + public ITextureCache GetTextureCache(); public MaterialsCache GetMaterialsCache(); public VulkanContext GetVulkanContext(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java index 42dee26..3525376 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java @@ -76,6 +76,7 @@ public class VulkanRenderer implements Renderer { public boolean GetDeferred(){return Deferred;} public VulkanRenderer(EngineInstance engineInstance) { + engineInstance.scene().GetProjection().SetFarPlanes(); Deferred = EngineConfig.getInstance().DeferredRendering(); RendererContext = new VulkanContext(engineInstance.window()); CurrentFrame = 0; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java index 9fd56f6..493ef4d 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Window.java @@ -44,15 +44,14 @@ public class Window { public String GetTitle(){return Title;} public EngineConfig.RenderAPI GetLinkedApi(){return LinkedApi;} - public static Window RefreshRendererAttachment(Window windowIn){ + public static Window RefreshRendererAttachment(Window windowIn , EngineConfig.RenderAPI renderAPI){ if(PrimaryRuntime.IsServer) return null; Logger.debug("Creating new Window Instance"); Vector2i inSize = windowIn.GetSize(); Vector2i inPos = windowIn.GetPosition(); String Title = windowIn.GetTitle(); windowIn.cleanup(); - windowIn.setShouldClose(); - Window newWindow = new Window(Title); + Window newWindow = new Window(Title, renderAPI); newWindow.SetProperties(inSize.x, inSize.y, inPos.x, inPos.y); return newWindow; } @@ -104,14 +103,14 @@ public class Window { return; } this.Title = title; - this.LinkedApi = api; if (!glfwInit()) { throw new RuntimeException("Unable to initialize GLFW"); } - if (!glfwVulkanSupported() && EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.Vulkan) { + if (!glfwVulkanSupported() && api == EngineConfig.RenderAPI.Vulkan) { Logger.error("Cannot find a compatible Vulkan installable client driver (ICD)"); - EngineConfig.getInstance().SetRenderingAPI(EngineConfig.RenderAPI.OpenGL); + api = EngineConfig.RenderAPI.OpenGL; } + this.LinkedApi = api; GLFWVidMode vidMode = glfwGetVideoMode(glfwGetPrimaryMonitor()); if (vidMode == null) { throw new RuntimeException("Error getting primary monitor"); @@ -122,10 +121,11 @@ public class Window { glfwDefaultWindowHints(); switch (api){ case Vulkan: + Logger.debug("Vulkan API selected"); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); break; case OpenGL: - default: + Logger.debug("OpenGL API selected"); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); @@ -195,9 +195,15 @@ public class Window { PrimaryRuntime.UpdateFrameAccuracy(); } }); - if(LinkedApi == EngineConfig.RenderAPI.Vulkan)glfwMakeContextCurrent(handle); - if (EngineConfig.VSYNC) glfwSwapInterval(1); - else glfwSwapInterval(0); + + if(LinkedApi == EngineConfig.RenderAPI.OpenGL) { + glfwMakeContextCurrent(handle); + if (EngineConfig.VSYNC) { + glfwSwapInterval(1); + } else { + glfwSwapInterval(0); + } + } mouseInput = new MouseListener(handle); } @@ -212,11 +218,16 @@ public class Window { public void cleanup() { if(PrimaryRuntime.IsServer) return; + + if(LinkedApi == EngineConfig.RenderAPI.OpenGL) { + glfwMakeContextCurrent(0); + } + glfwFreeCallbacks(handle); glfwDestroyWindow(handle); - glfwTerminate(); Logger.debug("Destroyed Window"); } + public long getHandle(){ return handle; } @@ -236,9 +247,6 @@ public class Window { if(PrimaryRuntime.IsServer) return; if((!GameStarted || ShowSettings || ForceCursorUnlock) && CursorLocked) UnlockCursor(); else if (GameStarted && !ShowSettings && !CursorLocked) LockCursor(); - if (keyboardInput.keySinglePress(GLFW_KEY_V)) { - SetVsync(); - } keyboardInput.input(); mouseInput.input(); /* if(CursorLocked) { @@ -251,19 +259,23 @@ public class Window { }*/ EngineConfig.RENDERFRAMES++; } - public void UpdateWindowTitle(){ - if (displayFPS) glfwSetWindowTitle(handle, EngineConfig.SOFTWARE_TITLE + " - FPS: " + EngineConfig.FrameRate_PRIMARYTHREAD + " TPS: " + EngineConfig.TPS + " RenderFPS: " + EngineConfig.FrameRate_RENDERTHREAD + " VSYNC: " + EngineConfig.VSYNC); - } + public void SetVsync(){ if(PrimaryRuntime.IsServer) return; + + EngineConfig.VSYNC = !EngineConfig.VSYNC; + + if(LinkedApi != EngineConfig.RenderAPI.OpenGL) { + Logger.info("Vsync changed to [{}]. Vulkan requires swapchain recreation to apply this.", EngineConfig.VSYNC); + return; + } + Logger.info("Vsync Swap"); if (EngineConfig.VSYNC) { - glfwSwapInterval(0); - EngineConfig.VSYNC = false; + glfwSwapInterval(1); } else { - glfwSwapInterval(1); - EngineConfig.VSYNC = true; + glfwSwapInterval(0); } } public void setShouldClose() diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Input/KeyboardInput.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Input/KeyboardInput.java index 7475c23..b7bd988 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Input/KeyboardInput.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Input/KeyboardInput.java @@ -33,10 +33,10 @@ public class KeyboardInput implements GLFWKeyCallbackI { } public void KeyCallback(long Window, int key, int scancode, int action, int mods){ - ImGui.getIO().addKeyEvent(ImGuiKey.Backspace, key == (GLFW_KEY_BACKSPACE) && (action == GLFW_PRESS || action == GLFW_REPEAT)); - ImGui.getIO().addKeyEvent(ImGuiKey.Delete, key == (GLFW_KEY_DELETE) && (action == GLFW_PRESS || action == GLFW_REPEAT)); - ImGui.getIO().addKeyEvent(ImGuiKey.LeftArrow, key == (GLFW_KEY_LEFT) && (action == GLFW_PRESS || action == GLFW_REPEAT)); - ImGui.getIO().addKeyEvent(ImGuiKey.RightArrow, key == (GLFW_KEY_RIGHT) && (action == GLFW_PRESS || action == GLFW_REPEAT)); + //ImGui.getIO().addKeyEvent(ImGuiKey.Backspace, key == (GLFW_KEY_BACKSPACE) && (action == GLFW_PRESS || action == GLFW_REPEAT)); + //ImGui.getIO().addKeyEvent(ImGuiKey.Delete, key == (GLFW_KEY_DELETE) && (action == GLFW_PRESS || action == GLFW_REPEAT)); + //ImGui.getIO().addKeyEvent(ImGuiKey.LeftArrow, key == (GLFW_KEY_LEFT) && (action == GLFW_PRESS || action == GLFW_REPEAT)); + //ImGui.getIO().addKeyEvent(ImGuiKey.RightArrow, key == (GLFW_KEY_RIGHT) && (action == GLFW_PRESS || action == GLFW_REPEAT)); if (!keysPressed.contains(key) && action == GLFW_PRESS){ keysPressed.add(key); 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 7bfc75f..cbe5310 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java @@ -88,10 +88,10 @@ public class EngineConfig { public RenderAPI RenderingAPI = RenderAPI.Vulkan; - public float MusicVolume = 0.5f; - public float SoundVolume = 0.5f; - public float WeaponVolume = 0.5f; - public float AmbientVolume = 0.5f; + public float MusicVolume = 0.0f; + public float SoundVolume = 0.0f; + public float WeaponVolume = 0.0f; + public float AmbientVolume = 0.0f; public float PlayerOnline = 1.0f; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelLoader.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelLoader.java index c400527..81c1728 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelLoader.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelLoader.java @@ -17,6 +17,8 @@ public class ModelLoader { // Model Utility class kinda like a model version of } + public static List ModelPaths = new ArrayList<>(); + public static List LoadMaterials(String[] Path){ var Result = new ArrayList(); for(int i = 0; i < Path.length; i++) { @@ -46,6 +48,7 @@ public class ModelLoader { // Model Utility class kinda like a model version of return Result; } public static ModelData LoadModel(String Path){ + ModelPaths.add(Path); Logger.debug("Loading Models From [{}]",Path); ModelData Result; try{ 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 030eacf..bb4e724 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -47,6 +47,9 @@ import org.tinylog.Logger; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE; +import static org.lwjgl.glfw.GLFW.GLFW_KEY_F3; + public class GameCore implements GameLogic { private static final float MOUSE_SENSITIVITY = 0.1f; @@ -183,13 +186,13 @@ public class GameCore implements GameLogic { for(int i = 0; i < ActorEditorComponents.size(); i++){ ActorEditorComponents.get(i).UpdateAll(); } - if(PrimaryRuntime.IsServer) { + //if(PrimaryRuntime.IsServer) { permutation.GeneratePermutationArray(5783904701859L); GenerateChunk(new Vector3i(0, 0, 0), 16); for(int i = 0; i < 20; i++){ SpawnNewActor(engineInstance, new Vector3f(-5 + (float)Math.random() * 10,10 + (float)Math.random() * 10, -5 + (float)Math.random() * 10), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); } - } + //} Settings.textBuffer.set(ClientSideNetworkUtils.ServerIP); Settings.UsernameBuffer.set("Player"); return new InitData(models,materials,guiTextures); @@ -379,6 +382,7 @@ public class GameCore implements GameLogic { } long CumulativeFrameTime = 0; + @Override public void RenderThreadInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { CumulativeFrameTime += FrameDiffNanoSeconds; @@ -426,7 +430,16 @@ public class GameCore implements GameLogic { IScene scene = engineInstance.scene(); scene.GlobalInput(engineInstance,FrameDiffNanoSeconds, null, MOVEMENT_SPEED,this); - + KeyboardInput input = engineInstance.window().getKeyboardInput(); + if(input.keySinglePress(GLFW_KEY_F3)){ + Scene.GUI_MODE = (Scene.GUI_MODE + 1) % 2; + } + if (input.keySinglePress(GLFW_KEY_ESCAPE)) { + StartMenuActive = !StartMenuActive; + StartMenu.GameStarted = StartMenuActive; + StartMenu.ShowSettings = StartMenuActive; + SwitchBGM(engineInstance, scene, "resources/EngineResources/audio/music/MENUMUSIC_RetroFutureClean.ogg"); + } if(ClientSideNetworkUtils.Connected) { if("NULL".equals(ClientSideNetworkUtils.GetPlayerControlledActorID())) { return; @@ -556,32 +569,36 @@ public class GameCore implements GameLogic { @Override public void SecondUpdate(EngineInstance engineInstance) { if(PrimaryRuntime.IsServer || RenderThread.Headless || PrimaryRuntime.GetRenderThread() == null) return; - SettingPerformanceMetrics.clear(); - List Metrics = new ArrayList<>(); - String[] ISceneDetails = new String[9]; - Vector3f Position = engineInstance.scene().GetCamera().GetPosition(); - Vector2f Position2D = engineInstance.scene().Get2DCamera().GetPosition(); - Vector3f Rotation = engineInstance.scene().GetCamera().GetRotation(); - ISceneDetails[0] = String.format("INSTANCE INFORMATION: "); - ISceneDetails[1] = String.format(" Camera Position: X: %.2f Y: %.2f Z: %.2f",Position.x ,Position.y ,Position.z); - ISceneDetails[2] = String.format(" 2DCamera Position: X: %.2f Y: %.2f",Position2D.x ,Position2D.y); - ISceneDetails[3] = String.format(" Camera Rotation: X: %.2f° Y: %.2f° Z: %.2f°",Rotation.x *EngineConfig.RadToDeg,Rotation.y *EngineConfig.RadToDeg ,Rotation.z *EngineConfig.RadToDeg); - ISceneDetails[4] = String.format(" Anti Aliasing: " + EngineConfig.getInstance().RenderAAType().name()); - ISceneDetails[5] = String.format(" Renderer: " + (!RenderThread.AllowRender() ? "NO RENDERER" : (PrimaryRuntime.GetRenderThread().GetRenderer().GetDeferred() ? " Deferred" : "Forward"))); - ISceneDetails[6] = String.format(" Pipeline: " + (ForwardSceneRender.DualPassRendering() ? " Dual Pass" : "Single Pass")); - ISceneDetails[7] = String.format(" AlphaToCoverage: " + EngineConfig.getInstance().AlphaToCoverage()); - ISceneDetails[8] = String.format(" FOV: %.2f°",(EngineConfig.getInstance().GetFOV()*EngineConfig.RadToDeg)); - String[] DeviceInfo = new String[5]; - DeviceInfo[0] = String.format("SYSTEM INFORMATION: "); - DeviceInfo[1] = String.format(" CPU: " + EngineConfig.getInstance().GetCPUDetails()); - DeviceInfo[2] = String.format(" RAM: " + CPUMonitor.RamSize); - DeviceInfo[3] = String.format(" GPU: " + EngineConfig.getInstance().GetGPU()); - DeviceInfo[4] = String.format(" VRAM: " + GPUProfiler.GetVramCapacity()); - Metrics.add(ISceneDetails); - Metrics.add(DeviceInfo); - SettingPerformanceMetrics.addAll(Metrics); - SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetMemoryProfiling()); - SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetSystemProfiling()); - PerformanceMetrics = List.copyOf(SettingPerformanceMetrics); + try { + SettingPerformanceMetrics.clear(); + List Metrics = new ArrayList<>(); + String[] ISceneDetails = new String[9]; + Vector3f Position = engineInstance.scene().GetCamera().GetPosition(); + Vector2f Position2D = engineInstance.scene().Get2DCamera().GetPosition(); + Vector3f Rotation = engineInstance.scene().GetCamera().GetRotation(); + ISceneDetails[0] = String.format("INSTANCE INFORMATION: "); + ISceneDetails[1] = String.format(" Camera Position: X: %.2f Y: %.2f Z: %.2f", Position.x, Position.y, Position.z); + ISceneDetails[2] = String.format(" 2DCamera Position: X: %.2f Y: %.2f", Position2D.x, Position2D.y); + ISceneDetails[3] = String.format(" Camera Rotation: X: %.2f° Y: %.2f° Z: %.2f°", Rotation.x * EngineConfig.RadToDeg, Rotation.y * EngineConfig.RadToDeg, Rotation.z * EngineConfig.RadToDeg); + ISceneDetails[4] = String.format(" Anti Aliasing: " + EngineConfig.getInstance().RenderAAType().name()); + ISceneDetails[5] = String.format(" Renderer: " + (!RenderThread.AllowRender() ? "NO RENDERER" : (PrimaryRuntime.GetRenderThread().GetRenderer().GetDeferred() ? " Deferred" : "Forward"))); + ISceneDetails[6] = String.format(" Pipeline: " + (ForwardSceneRender.DualPassRendering() ? " Dual Pass" : "Single Pass")); + ISceneDetails[7] = String.format(" AlphaToCoverage: " + EngineConfig.getInstance().AlphaToCoverage()); + ISceneDetails[8] = String.format(" FOV: %.2f°", (EngineConfig.getInstance().GetFOV() * EngineConfig.RadToDeg)); + String[] DeviceInfo = new String[5]; + DeviceInfo[0] = String.format("SYSTEM INFORMATION: "); + DeviceInfo[1] = String.format(" CPU: " + EngineConfig.getInstance().GetCPUDetails()); + DeviceInfo[2] = String.format(" RAM: " + CPUMonitor.RamSize); + DeviceInfo[3] = String.format(" GPU: " + EngineConfig.getInstance().GetGPU()); + DeviceInfo[4] = String.format(" VRAM: " + GPUProfiler.GetVramCapacity()); + Metrics.add(ISceneDetails); + Metrics.add(DeviceInfo); + SettingPerformanceMetrics.addAll(Metrics); + SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetMemoryProfiling()); + SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetSystemProfiling()); + PerformanceMetrics = List.copyOf(SettingPerformanceMetrics); + } catch(NullPointerException e){ + + } } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java index ddf2a87..9b8ccd8 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/PrimaryRuntime.java @@ -317,8 +317,9 @@ CreateNewClientConnection(); } Logger.debug("Joined Drawing Thread"); DrawingThread.cleanup(); + DrawingThread = null; Window oldWindow = window; - window = Window.RefreshRendererAttachment(oldWindow); + window = Window.RefreshRendererAttachment(oldWindow, EngineConfig.getInstance().GetRenderingAPI()); engineInstance = engineInstance.SetWindow(window); if (window.GetLinkedApi() == OpenGL) { diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/LoadingScreen.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/LoadingScreen.java index 4db15c2..896966c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/LoadingScreen.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/LoadingScreen.java @@ -37,7 +37,7 @@ public class LoadingScreen implements GUIOverlay { ImGui.setNextWindowPos(CenterX,CenterY, ImGuiCond.Always,0.5f,0.5f); ImGui.pushStyleColor(ImGuiCol.WindowBg, 0,0.1f,0.5f,0.0f); ImGui.begin("Loading Screen",windowFlags); - ImGui.image(PrimaryRuntime.GetRenderThread().GetRenderer().GetGuiTexture(LoadingTexture.ID()),viewport.getWorkSizeX() / 2.0f,viewport.getWorkSizeY() / 2.0f); + //ImGui.image(PrimaryRuntime.GetRenderThread().GetRenderer().GetGuiTexture(LoadingTexture.ID()),viewport.getWorkSizeX() / 2.0f,viewport.getWorkSizeY() / 2.0f); ImGui.end(); } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/IScene.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/IScene.java index c002c12..602b1ab 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/IScene.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/IScene.java @@ -8,7 +8,7 @@ import net.halbear.Terrain4J.EngineCore.Main.GameCore; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3D; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.PlayerActor3D; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DynamicMesh.DynamicTerrainMesh; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Projection.Project3D; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Projection.Project3D; import java.util.List; import java.util.Map; 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 334ac27..e21d5f3 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 @@ -16,9 +16,10 @@ import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.GameChat; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.Gimbal; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.PerformanceOverlay; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.StartMenu; +import net.halbear.Terrain4J.EngineCore.Main.Scene.InputEvents.DebugCameraController; import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DynamicMesh.DynamicTerrainMesh; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Projection.Project3D; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Projection.Project3D; import net.halbear.Terrain4J.EngineCore.Main.AudioInstance.AudioType; import org.joml.Vector2f; import org.joml.Vector3f; @@ -61,6 +62,7 @@ public class Scene implements IScene { public Map audioInstances; private DynamicTerrainMesh terrainMesh; public IPlayerController playerController; + private DebugCameraController debugCam = new DebugCameraController(); public int Jumps = 0; public final int MaxJumps = 2; @@ -311,7 +313,7 @@ public class Scene implements IScene { public void SetCurrentWeapon(PlayerActor3D Weapon) {this.CurrentWeapon = Weapon; } - public int GUI_MODE = 1; + public static int GUI_MODE = 1; boolean InitialisedGun = false; @@ -327,6 +329,7 @@ public class Scene implements IScene { KeyboardInput input = window.getKeyboardInput(); float MovementDist = (float)(FrameDiffNanoSeconds / 1000000L) * MOVEMENT_SPEED; Camera camera = scene.GetCamera(); + if(playerActor!= null)camera = Camera.GetCamera(playerActor.AttachedCameraID); if(!InitialisedGun && playerActor != null){ playerActor.SetModelID(MusketItem.ModelID()); @@ -335,9 +338,7 @@ public class Scene implements IScene { GunCockSFX.Play(); InitialisedGun = true; } - if(input.keySinglePress(GLFW_KEY_F3)){ - GUI_MODE = (GUI_MODE + 1) % 2; - } + if(GameChat.IsChatOpen){ if(input.keyPressed(GLFW_KEY_ENTER)){ GameChat.IsChatOpen = false; @@ -392,20 +393,6 @@ public class Scene implements IScene { } } } - if (input.keyPressed(GLFW_KEY_1)) { - Gimbal.universalType = Gimbal.GimbalType.Move; - } - if (input.keyPressed(GLFW_KEY_2)) { - Gimbal.universalType = Gimbal.GimbalType.Resize; - } - if (input.keyPressed(GLFW_KEY_3)) { - Gimbal.universalType = Gimbal.GimbalType.Rotate; - } - if (input.keyPressed(GLFW_KEY_TAB)) { - for (int i = 0; i < parent.ActorEditorComponents.size(); i++) { - parent.ActorEditorComponents.get(i).UpdateAll(); - } - } if (input.keySinglePress(GLFW_KEY_F2)) { EngineConfig.getInstance().SetRenderCollisionMesh(!EngineConfig.getInstance().RenderCollisionMeshes()); } @@ -434,13 +421,11 @@ public class Scene implements IScene { if(input.keyPressed(GLFW_KEY_A)) { scene.Get2DCamera().AddPosition(new Vector2f(-1,0)); } - - if (input.keySinglePress(GLFW_KEY_ESCAPE)) { - parent.StartMenuActive = !parent.StartMenuActive; - StartMenu.GameStarted = parent.StartMenuActive; - StartMenu.ShowSettings = parent.StartMenuActive; - parent.SwitchBGM(engineInstance, this, "resources/EngineResources/audio/music/MENUMUSIC_RetroFutureClean.ogg"); + if (playerActor == null || CurrentWeapon == null || playerController == null) { + debugCam.Input(input, FrameDiffNanoSeconds,null, MOVEMENT_SPEED, parent, scene); + return; } + } @Override @@ -498,4 +483,12 @@ public class Scene implements IScene { // } engineInstance.audioManager().UpdateListenerPosition(camera); } + + public DebugCameraController getDebugCam() { + return debugCam; + } + + public void setDebugCam(DebugCameraController debugCam) { + this.debugCam = debugCam; + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene2D.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene2D.java index 5d3c126..de4786f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene2D.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene2D.java @@ -13,7 +13,7 @@ import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.PlayerActor3D; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.StartMenu; import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DynamicMesh.DynamicTerrainMesh; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Projection.Project3D; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Projection.Project3D; import org.joml.Vector2f; import java.util.*; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GUI/GuiMesh.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GUI/GuiMesh.java new file mode 100644 index 0000000..0dd502b --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GUI/GuiMesh.java @@ -0,0 +1,51 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GUI; + +import imgui.ImDrawData; + +import static org.lwjgl.opengl.GL15.*; +import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray; +import static org.lwjgl.opengl.GL20.glVertexAttribPointer; +import static org.lwjgl.opengl.GL30.*; + +public class GuiMesh { + private final int indicesVBO; + private final int vaoID; + private final int verticesVBO; + + public GuiMesh() { + vaoID = glGenVertexArrays(); + glBindVertexArray(vaoID); + + verticesVBO = glGenBuffers(); + glBindBuffer(GL_ARRAY_BUFFER, verticesVBO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, false, ImDrawData.sizeOfImDrawVert(), 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, false, ImDrawData.sizeOfImDrawVert(), 8); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, true, ImDrawData.sizeOfImDrawVert(), 16); + + indicesVBO = glGenBuffers(); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + public void CleanUp() { + glDeleteBuffers(indicesVBO); + glDeleteBuffers(verticesVBO); + glDeleteVertexArrays(vaoID); + } + + public int GetIndicesVBO() { + return indicesVBO; + } + + public int GetVaoId() { + return vaoID; + } + + public int GetVerticesVBO() { + return verticesVBO; + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GUI/OpenGLGuiRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GUI/OpenGLGuiRenderer.java new file mode 100644 index 0000000..c50ed26 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GUI/OpenGLGuiRenderer.java @@ -0,0 +1,134 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GUI; + +import imgui.ImDrawData; +import imgui.ImFontAtlas; +import imgui.ImGui; +import imgui.ImGuiIO; +import imgui.type.ImInt; +import net.halbear.Terrain4J.EngineCore.Display.OpenGLRenderer; +import net.halbear.Terrain4J.EngineCore.Display.Window; +import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput; +import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.Texture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader.ShaderProgram; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader.UniformsMap; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiUtils; +import org.joml.Vector2f; +import org.lwjgl.glfw.GLFWKeyCallback; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL14.*; +import static org.lwjgl.opengl.GL15.*; +import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER; +import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER; +import static org.lwjgl.opengl.GL30.glBindVertexArray; + +public class OpenGLGuiRenderer { + private GuiMesh guiMesh; + private GLFWKeyCallback prevKeyCallBack; + private Vector2f scale; + private ShaderProgram shaderProgram; + private Texture texture; + private UniformsMap uniformsMap; + + public OpenGLGuiRenderer(Window window) { + List ShaderModules = new ArrayList<>(); + ShaderModules.add(new ShaderProgram.ShaderModuleGL("resources/EngineResources/GLShaders/gui_vertex.glsl", GL_VERTEX_SHADER)); + ShaderModules.add(new ShaderProgram.ShaderModuleGL("resources/EngineResources/GLShaders/gui_fragment.glsl", GL_FRAGMENT_SHADER)); + shaderProgram = new ShaderProgram(ShaderModules); + CreateUniforms(); + CreateGUIResources(window); + KeyboardInput keyboardInput=window.getKeyboardInput(); + keyboardInput.setCharCallBack(new GuiUtils.CharacterCallBack()); + keyboardInput.AddKeyCallBack(new GuiUtils.KeyCallBack());; + } + + private void CreateGUIResources(Window window) { + ImGui.createContext(); + ImGuiIO imGuiIO = ImGui.getIO(); + imGuiIO.setIniFilename(null); + imGuiIO.setDisplaySize(window.getWidth(), window.getHeight()); + ImFontAtlas fontAtlas = ImGui.getIO().getFonts(); + ImInt width = new ImInt(); + ImInt height = new ImInt(); + ByteBuffer buffer = fontAtlas.getTexDataAsRGBA32(width, height); + texture = new Texture(width.get(), height.get(), buffer); + guiMesh = new GuiMesh(); + } + + private void CreateUniforms() { + uniformsMap = new UniformsMap(shaderProgram.GetProgramID()); + uniformsMap.CreateUniform("scale"); + scale = new Vector2f(); + } + + public void Render(IScene scene) { + + shaderProgram.Bind(); + + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + glBindVertexArray(guiMesh.GetVaoId()); + + glBindBuffer(GL_ARRAY_BUFFER, guiMesh.GetVerticesVBO()); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, guiMesh.GetIndicesVBO()); + + ImGuiIO io = ImGui.getIO(); + scale.x = 2.0f / io.getDisplaySizeX(); + scale.y = -2.0f / io.getDisplaySizeY(); + uniformsMap.SetUniform("scale", scale); + + ImDrawData drawData = ImGui.getDrawData(); + if (drawData == null || drawData.ptr == 0) { + glBindVertexArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glDisable(GL_BLEND); + + shaderProgram.UnBind(); + return; + } + int ListCount = drawData.getCmdListsCount(); + for (int i = 0; i < ListCount; i++) { + glBufferData(GL_ARRAY_BUFFER, drawData.getCmdListVtxBufferData(i), GL_STREAM_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, drawData.getCmdListIdxBufferData(i), GL_STREAM_DRAW); + + int CommandCount = drawData.getCmdListCmdBufferSize(i); + for (int j = 0; j < CommandCount; j++) { + final int ElementCount = drawData.getCmdListCmdBufferElemCount(i, j); + final int IndexBufferOffset = drawData.getCmdListCmdBufferIdxOffset(i, j); + final int Indices = IndexBufferOffset * ImDrawData.sizeOfImDrawIdx(); + + texture.Bind(); + glDrawElements(GL_TRIANGLES, ElementCount, GL_UNSIGNED_SHORT, Indices); + } + } + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glDisable(GL_BLEND); + } + + public void CleanUp() { + shaderProgram.CleanUp(); + texture.CleanUp(); + if (prevKeyCallBack != null) { + prevKeyCallBack.free(); + } + } + public void Resize(int width, int height) { + ImGuiIO imGuiIO = ImGui.getIO(); + imGuiIO.setDisplaySize(width, height); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMaterial.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMaterial.java new file mode 100644 index 0000000..b431551 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMaterial.java @@ -0,0 +1,42 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels; + +import org.joml.Vector4f; + +import java.util.ArrayList; +import java.util.List; + +public class GLMaterial { + private final List meshList; + private String texturePath; + public static final Vector4f DEFAULT_COLOUR = new Vector4f(0.0f, 0.0f, 0.0f, 1.0f); + + private Vector4f DiffuseColour; + + public GLMaterial() { + meshList = new ArrayList<>(); + DiffuseColour = DEFAULT_COLOUR; + } + + public void CleanUp() { + meshList.forEach(GLMesh::CleanUp); + } + + public List GetMeshList() { + return meshList; + } + + public String GetTexturePath() { + return texturePath; + } + + public void SetTexturePath(String texturePath) { + this.texturePath = texturePath; + } + + public Vector4f GetDiffuseColour() { + return DiffuseColour; + } + public void SetDiffuseColour(Vector4f diffuseColour) { + this.DiffuseColour = diffuseColour; + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMesh.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMesh.java index 5f6b94c..3126226 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMesh.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMesh.java @@ -17,8 +17,13 @@ public class GLMesh { private int VertexCount; private int VAO_ID; private List VBO_ID_List; + String MaterialID; + public String MaterialID() { + return MaterialID; + } - public GLMesh(float[] vertices, float[] colours, int[] indices) { + public GLMesh(float[] vertices, int[] indices, String materialID) { + this.MaterialID = materialID; this.VertexCount = indices.length; VBO_ID_List = new ArrayList<>(); @@ -26,22 +31,62 @@ public class GLMesh { glBindVertexArray(VAO_ID); int vboId = glGenBuffers(); - VBO_ID_List.add(vboId); - FloatBuffer positionsBuffer = MemoryUtil.memCallocFloat(vertices.length); - positionsBuffer.put(0, vertices); glBindBuffer(GL_ARRAY_BUFFER, vboId); - glBufferData(GL_ARRAY_BUFFER, positionsBuffer, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0); - vboId = glGenBuffers(); - VBO_ID_List.add(vboId); - FloatBuffer coloursBuffer = MemoryUtil.memCallocFloat(colours.length); - coloursBuffer.put(0, colours); - glBindBuffer(GL_ARRAY_BUFFER, vboId); - glBufferData(GL_ARRAY_BUFFER, coloursBuffer, GL_STATIC_DRAW); + FloatBuffer verticesBuffer = MemoryUtil.memCallocFloat(vertices.length); + verticesBuffer.put(0, vertices); + + glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW); + + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 0, + 3, + GL_FLOAT, + false, + 14 * Float.BYTES, + 0L + ); + glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0); + glVertexAttribPointer( + 1, + 3, + GL_FLOAT, + false, + 14 * Float.BYTES, + 3L * Float.BYTES + ); + + glEnableVertexAttribArray(2); + glVertexAttribPointer( + 2, + 3, + GL_FLOAT, + false, + 14 * Float.BYTES, + 6L * Float.BYTES + ); + + glEnableVertexAttribArray(3); + glVertexAttribPointer( + 3, + 3, + GL_FLOAT, + false, + 14 * Float.BYTES, + 9L * Float.BYTES + ); + + glEnableVertexAttribArray(4); + glVertexAttribPointer( + 4, + 2, + GL_FLOAT, + false, + 14 * Float.BYTES, + 12L * Float.BYTES + ); vboId = glGenBuffers(); VBO_ID_List.add(vboId); @@ -53,8 +98,7 @@ public class GLMesh { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); - MemoryUtil.memFree(positionsBuffer); - MemoryUtil.memFree(coloursBuffer); + MemoryUtil.memFree(verticesBuffer); MemoryUtil.memFree(indicesBuffer); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModel.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModel.java index e443bb7..d4b7bd1 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModel.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModel.java @@ -1,8 +1,37 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.MeshData; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.ModelData; +import java.util.ArrayList; import java.util.List; -public record GLModel(String ID, List Meshes, String VertexPath, String IndexPath) { +public class GLModel { + private final String ModelID; + private List MeshList; + + public GLModel(String ModelID, List MeshList, ModelData data) { + this.ModelID = ModelID; + this.MeshList = MeshList; + } + + public void CleanUp() { + MeshList.forEach(GLMesh::CleanUp); + } + + public String GetId() { + return ModelID; + } + + public List GetMaterialList(ModelsCache cache) { + List materials = new ArrayList<>(); + MeshList.forEach(mesh->{ + materials.add(cache.GetMaterial(mesh.MaterialID())); + }); + return materials; + } + + public List GetMeshList() { + return MeshList; + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModelLoader.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModelLoader.java new file mode 100644 index 0000000..8d9e0b9 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModelLoader.java @@ -0,0 +1,151 @@ +//package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels; +// +//import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.Texture; +//import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.TextureCache; +//import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; +//import org.joml.Vector4f; +//import org.lwjgl.PointerBuffer; +//import org.lwjgl.assimp.*; +//import org.lwjgl.system.MemoryStack; +// +//import java.io.File; +//import java.nio.IntBuffer; +//import java.util.ArrayList; +//import java.util.List; +// +//import static org.lwjgl.assimp.Assimp.*; +// +//public class GLModelLoader { +// private GLModelLoader() { +// } +// +// +// +// public static GLModel loadModel(String ModelId, String ModelPath, TextureCache textureCache) { +// return loadModel(ModelId, ModelPath, textureCache, aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices | +// aiProcess_Triangulate | aiProcess_FixInfacingNormals | aiProcess_CalcTangentSpace | aiProcess_LimitBoneWeights | +// aiProcess_PreTransformVertices); +// +// } +// +// public static GLModel loadModel(String ModelId, String ModelPath, TextureCache textureCache, int Flags) { +// File file = new File(ModelPath); +// if (!file.exists()) { +// throw new RuntimeException("Model path does not exist: " + ModelPath); +// } +// String ModelDir = file.getParent(); +// +// AIScene aiScene = aiImportFile(ModelPath, Flags); +// if (aiScene == null) { +// throw new RuntimeException("Error loading model: " + ModelPath); +// } +// +// int MaterialCount = aiScene.mNumMaterials(); +// List materialList = new ArrayList<>(); +// for (int i = 0; i < MaterialCount; i++) { +// AIMaterial aiMaterial = AIMaterial.create(aiScene.mMaterials().get(i)); +// materialList.add(ProcessMaterial(aiMaterial, ModelDir, textureCache)); +// } +// +// int MeshCount = aiScene.mNumMeshes(); +// PointerBuffer aiMeshes = aiScene.mMeshes(); +// GLMaterial defaultMaterial = new GLMaterial(); +// for (int i = 0; i < MeshCount; i++) { +// AIMesh aiMesh = AIMesh.create(aiMeshes.get(i)); +// GLMesh mesh = ProcessMesh(aiMesh); +// int materialIdx = aiMesh.mMaterialIndex(); +// GLMaterial material; +// if (materialIdx >= 0 && materialIdx < materialList.size()) { +// material = materialList.get(materialIdx); +// } else { +// material = defaultMaterial; +// } +// material.GetMeshList().add(mesh); +// } +// +// if (!defaultMaterial.GetMeshList().isEmpty()) { +// materialList.add(defaultMaterial); +// } +// +// return new GLModel(ModelId, materialList); +// } +// +// private static GLMaterial ProcessMaterial(AIMaterial aiMaterial, String modelDir, TextureCache textureCache) { +// GLMaterial Material = new GLMaterial(); +// try (MemoryStack stack = MemoryStack.stackPush()) { +// AIColor4D color = AIColor4D.create(); +// +// int result = aiGetMaterialColor(aiMaterial, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_NONE, 0, +// color); +// if (result == aiReturn_SUCCESS) { +// Material.SetDiffuseColour(new Vector4f(color.r(), color.g(), color.b(), color.a())); +// } +// +// AIString aiTexturePath = AIString.calloc(stack); +// aiGetMaterialTexture(aiMaterial, aiTextureType_DIFFUSE, 0, aiTexturePath, (IntBuffer) null, +// null, null, null, null, null); +// String TexturePath = aiTexturePath.dataString(); +// if (TexturePath != null && TexturePath.length() > 0) { +// Material.SetTexturePath(modelDir + File.separator + new File(TexturePath).getName()); +// textureCache.CreateTexture(Material.GetTexturePath()); +// Material.SetDiffuseColour(GLMaterial.DEFAULT_COLOUR); +// } +// +// return Material; +// } +// } +// private static GLMesh ProcessMesh(AIMesh aiMesh) { +// float[] vertices = ProcessVertices(aiMesh); +// float[] textCoords = ProcessTextCoords(aiMesh); +// int[] indices = ProcessIndices(aiMesh); +// +// if (textCoords.length == 0) { +// int numElements = (vertices.length / 3) * 2; +// textCoords = new float[numElements]; +// } +// +// return new GLMesh(vertices, textCoords, indices); +// } +// +// private static int[] ProcessIndices(AIMesh aiMesh) { +// List indices = new ArrayList<>(); +// int FaceCount = aiMesh.mNumFaces(); +// AIFace.Buffer aiFaces = aiMesh.mFaces(); +// for (int i = 0; i < FaceCount; i++) { +// AIFace aiFace = aiFaces.get(i); +// IntBuffer buffer = aiFace.mIndices(); +// while (buffer.remaining() > 0) { +// indices.add(buffer.get()); +// } +// } +// return indices.stream().mapToInt(Integer::intValue).toArray(); +// } +// +// private static float[] ProcessTextCoords(AIMesh aiMesh) { +// AIVector3D.Buffer TextureCoordBuffer = aiMesh.mTextureCoords(0); +// if (TextureCoordBuffer == null) { +// return new float[]{}; +// } +// float[] data = new float[TextureCoordBuffer.remaining() * 2]; +// int index = 0; +// while (TextureCoordBuffer.remaining() > 0) { +// AIVector3D TextureCoord = TextureCoordBuffer.get(); +// data[index++] = TextureCoord.x(); +// data[index++] = 1 - TextureCoord.y(); +// } +// return data; +// } +// +// private static float[] ProcessVertices(AIMesh aiMesh) { +// AIVector3D.Buffer VertexBuffer = aiMesh.mVertices(); +// float[] data = new float[VertexBuffer.remaining() * 3]; +// int index = 0; +// while (VertexBuffer.remaining() > 0) { +// AIVector3D TextureCoord = VertexBuffer.get(); +// data[index++] = TextureCoord.x(); +// data[index++] = TextureCoord.y(); +// data[index++] = TextureCoord.z(); +// } +// return data; +// } +//} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/ModelsCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/ModelsCache.java index 42b0a5a..7f4966f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/ModelsCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/ModelsCache.java @@ -1,17 +1,46 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.TextureCache; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ITexture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandPool; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.GPUSynchronisation.TransferBuffer; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Queues.Queue; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils; +import org.lwjgl.system.MemoryUtil; +import org.tinylog.Logger; + +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.nio.FloatBuffer; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; public class ModelsCache { private final Map MeshMap; + private final Map ModelMap; + private final Map MaterialsMap; public ModelsCache(){ - MeshMap = new HashMap<>(); + MeshMap = new ConcurrentHashMap<>(); + ModelMap = new ConcurrentHashMap<>(); + MaterialsMap = new ConcurrentHashMap<>(); } public void addMesh(String meshId, GLMesh mesh) { MeshMap.put(meshId, mesh); } + public void addModel(GLModel model) { + ModelMap.put(model.GetId(), model); + } public void cleanup() { MeshMap.values().forEach(GLMesh::CleanUp); @@ -20,4 +49,85 @@ public class ModelsCache { public Map getMeshMap() { return MeshMap; } + + public void CleanUp() { + ModelMap.values().forEach(GLModel::CleanUp); + cleanup(); + } + + public void loadModels(List Models){ + try { + for (ModelData modelData : Models) { + DataInputStream VertexInput = new DataInputStream(new BufferedInputStream( + new FileInputStream(modelData.VertexPath()))); + DataInputStream IndicesInput = new DataInputStream(new BufferedInputStream( + new FileInputStream(modelData.IndexPath()))); + List MeshList = new ArrayList<>(); + for (MeshData meshData : modelData.Meshes()) { + float[] Vertices; + int[] Indices; + + int ValuesToRead = meshData.VertexSize()/VulkanUtils.FLOAT_SIZE; + int Total = ValuesToRead; + Vertices = new float[ValuesToRead]; + while(ValuesToRead > 0){ + Vertices[Total-ValuesToRead] = (VertexInput.readFloat()); + ValuesToRead--; + } + + ValuesToRead = meshData.IndexSize()/VulkanUtils.INT_SIZE; + Total = ValuesToRead; + Indices = new int[ValuesToRead]; + while(ValuesToRead > 0){ + Indices[Total-ValuesToRead] = (IndicesInput.readInt()); + ValuesToRead--; + } + MeshList.add(new GLMesh(Vertices, Indices, meshData.MaterialID())); + } + GLModel GLModel = new GLModel(modelData.ID(),MeshList,modelData); + ModelMap.put(modelData.ID(), GLModel); + + } + } catch (Exception exception){ + throw new RuntimeException(exception); + } + } + + public GLMaterial GetMaterial(String MaterialID) + { + return MaterialsMap.get(MaterialID); + } + + public void LoadMaterials(List Materials, TextureCache textureCache){ + int MaterialCount = Materials.size(); + int Offset = 0; + for(int i = 0; i < MaterialCount; i++){ + var Material = Materials.get(i); + String TexturePath = Material.TexturePath(); + boolean ValidTexture = TexturePath != null && !TexturePath.isEmpty(); + boolean TransparentTexture; + Logger.debug("Material Texture Path -> [{}]",Material.TexturePath()); + if(ValidTexture){ + ITexture newTexture = textureCache.CreateTexture(TexturePath); + if(newTexture == null) { + TransparentTexture = false; + TexturePath = "resources/EngineResources/Texture/NoTexture.png"; + } + else TransparentTexture = newTexture.HasTransparency(); + } else{ + TexturePath = "resources/EngineResources/Texture/NoTexture.png"; + TransparentTexture = Material.DiffuseColour().w < 1.0f; + } + GLMaterial newMaterial = new GLMaterial(); + MaterialsMap.put(Material.ID(), newMaterial); + Logger.trace(Material.toString()); + + newMaterial.SetDiffuseColour(Material.DiffuseColour()); + newMaterial.SetTexturePath(TexturePath); + } + } + + public Map GetModelMap() { + return ModelMap; + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Images/Texture.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Images/Texture.java new file mode 100644 index 0000000..e183e99 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Images/Texture.java @@ -0,0 +1,132 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images; + +import net.halbear.Terrain4J.EngineCore.Display.GLFWImageParser; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.GraphUtils; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ITexture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ImageSrc; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView; +import org.lwjgl.opengl.GL11; +import org.lwjgl.system.MemoryStack; +import org.tinylog.Logger; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; + +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL30.glGenerateMipmap; +import static org.lwjgl.stb.STBImage.*; + +public class Texture implements ITexture { + private int TextureID; + private String TexturePath; + int Height; + int Width; + + public Texture(int width, int height, ByteBuffer buffer){ + TexturePath = ""; + GenerateTexture(width, height, buffer); + } + + public Texture(String TexturePath){ + try (MemoryStack stack = MemoryStack.stackPush()) { + this.TexturePath = TexturePath; + IntBuffer w = stack.mallocInt(1); + IntBuffer h = stack.mallocInt(1); + IntBuffer channels = stack.mallocInt(1); + + ByteBuffer buf = stbi_load(TexturePath, w, h, channels, 4); + if (buf == null) { + throw new RuntimeException("Image file [" + TexturePath + "] not loaded: " + stbi_failure_reason()); + } + + int width = w.get(); + int height = h.get(); + + GenerateTexture(width, height, buf); + + stbi_image_free(buf); + } + + } + + public void Bind(){ + glBindTexture(GL_TEXTURE_2D, TextureID); + } + + public void CleanUp(){ + GL11.glDeleteTextures(TextureID); + } + + private void GenerateTexture(int Width, int Height, ByteBuffer buffer){ + TextureID = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, TextureID); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, buffer); + glGenerateMipmap(GL_TEXTURE_2D); + } + + public String GetTexturePath(){ + return TexturePath; + } + + @Override + public boolean HasTransparency() { + return false; + } + + @Override + public void SetTransparency(ByteBuffer data) { + + } + + @Override + public void CreateStgBuffer(VulkanContext VkCtx, ByteBuffer data) { + + } + + @Override + public void RecordTextureTransition(CommandBuffer commandBuffer) { + + } + + @Override + public void CleanUp(VulkanContext VkCtx) { + + } + + @Override + public void CleanUpStgBuffer(VulkanContext VkCtx) { + + } + + @Override + public int GetHeight() { + return Height; + } + + @Override + public int GetWidth() { + return Width; + } + + @Override + public String GetID() { + return TexturePath; + } + + @Override + public ImageView GetImageView() { + return null; + } + + @Override + public TextureType getType() { + return null; + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Images/TextureCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Images/TextureCache.java new file mode 100644 index 0000000..7ca6d07 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Images/TextureCache.java @@ -0,0 +1,93 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images; + +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ITexture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ImageSrc; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandPool; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Queues.Queue; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class TextureCache implements ITextureCache { + public static final String DEFAULT_TEXTURE_PATH = "resources/EngineResources/Texture/NoTexture.png"; + private final Map TextureMap; + + public TextureCache(){ + TextureMap = new LinkedHashMap<>(); + TextureMap.put(DEFAULT_TEXTURE_PATH, new Texture(DEFAULT_TEXTURE_PATH)); + } + + public void CleanUp(){ + TextureMap.values().forEach(ITexture::CleanUp); + } + + public ITexture CreateTexture(String TexturePath){ + return TextureMap.computeIfAbsent(TexturePath, Texture::new); + } + + @Override + public ITexture AddCubeMapTexture(VulkanContext VkCtx, String ID, String[] FacePaths, int Format) { + return null; + } + + @Override + public ITexture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format) { + return null; + } + + @Override + public ITexture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format, boolean PaddingTexture) { + return null; + } + + @Override + public ITexture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) { + return null; + } + + @Override + public ITexture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format, boolean PaddingTexture) { + return null; + } + + @Override + public void TransitionTexts(VulkanContext VkCtx, CommandPool CmdPool, Queue queue) { + + } + + public ITexture GetTexture(String TexturePath){ + ITexture texture = null; + if (TexturePath != null) { + texture = TextureMap.get(TexturePath); + } + if (texture == null) { + texture = TextureMap.get(DEFAULT_TEXTURE_PATH); + } + return texture; + } + + @Override + public Map GetTextureCache() { + return TextureMap; + } + + @Override + public List GetTextureList() { + return List.of(); + } + + @Override + public int GetPosition(String ID) { + return 0; + } + + @Override + public void CleanUp(VulkanContext VkCtx) { + + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java index 050501f..165fc35 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java @@ -1,29 +1,55 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Rendering; import imgui.extension.imguizmo.flag.Mode; +import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3D; +import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3DElement; import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.GLMaterial; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.GLMesh; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.GLModel; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.ModelsCache; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.Texture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader.ShaderProgram; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader.UniformsMap; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ITexture; +import net.halbear.Terrain4J.EngineCore.ServerNetworking.ClientSideNetworkUtils; +import org.joml.Vector3f; import org.tinylog.Logger; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Map; import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL13.GL_TEXTURE0; +import static org.lwjgl.opengl.GL13.glActiveTexture; import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER; import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER; import static org.lwjgl.opengl.GL30.glBindVertexArray; public class ForwardRenderer implements SceneRender{ - private ShaderProgram shaderProgram; + private final ShaderProgram shaderProgram; + private UniformsMap uniformsMap; public ForwardRenderer(){ List shaderModules = new ArrayList<>(); shaderModules.add(new ShaderProgram.ShaderModuleGL("resources/EngineResources/GLShaders/scene_vert.glsl", GL_VERTEX_SHADER)); shaderModules.add(new ShaderProgram.ShaderModuleGL("resources/EngineResources/GLShaders/scene_frag.glsl", GL_FRAGMENT_SHADER)); shaderProgram = new ShaderProgram(shaderModules); + CreateUniforms(); + } + + private void CreateUniforms() { + uniformsMap = new UniformsMap(shaderProgram.GetProgramID()); + uniformsMap.CreateUniform("projectionMatrix"); + uniformsMap.CreateUniform("modelMatrix"); + uniformsMap.CreateUniform("textureSampler"); + uniformsMap.CreateUniform("viewMatrix"); + uniformsMap.CreateUniform("material.diffuse"); } @Override @@ -32,18 +58,28 @@ public class ForwardRenderer implements SceneRender{ } @Override - public void Render(IScene scene, ModelsCache modelsCache) { + public void Render(IScene scene, ModelsCache modelsCache, TextureCache textureCache) { shaderProgram.Bind(); - modelsCache.getMeshMap().forEach((key , value)->{ - glBindVertexArray(value.GetVaoID()); - glDrawElements(GL_TRIANGLES, value.GetVertexCount(), GL_UNSIGNED_INT, 0); - }); -// scene.GetActors().forEach(actor -> { -// GLMesh mesh = modelsCache.getMeshMap().get(actor.GetModelID()); -// glBindVertexArray(mesh.GetVaoID()); -// glDrawArrays(GL_TRIANGLES, 0, mesh.GetVertexCount()); -// } -// ); + uniformsMap.SetUniform("projectionMatrix", scene.GetProjection().GetProjectionMatrix()); + uniformsMap.SetUniform("viewMatrix", scene.GetCamera().GetViewMatrix()); + uniformsMap.SetUniform("textureSampler", 0); + Map models = modelsCache.GetModelMap(); + for (Actor3D actor : scene.GetActors()) { + if(actor instanceof Actor3DElement &&( !((Actor3DElement) actor).RenderOnTopOfPlayer && ClientSideNetworkUtils.OwnsActor(((Actor3DElement) actor).GetParentID()) || new Vector3f().set(actor.GetPosition()).sub(scene.GetCamera().GetPosition()).absolute().lengthSquared() < 4f)) continue; + if(actor == null) continue; + GLModel model = models.get(actor.GetModelID()); + if(model == null) continue; + model.GetMeshList().stream().forEach(mesh -> { + GLMaterial material = modelsCache.GetMaterial(mesh.MaterialID()); + ITexture texture = textureCache.GetTexture(material.GetTexturePath()); + glActiveTexture(GL_TEXTURE0); + texture.Bind(); + uniformsMap.SetUniform("material.diffuse", material.GetDiffuseColour()); + glBindVertexArray(mesh.GetVaoID()); + uniformsMap.SetUniform("modelMatrix", actor.GetModelMatrix()); + glDrawElements(GL_TRIANGLES, mesh.GetVertexCount(), GL_UNSIGNED_INT, 0); + }); + } glBindVertexArray(0); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/SceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/SceneRender.java index 838435c..aa8bca3 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/SceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/SceneRender.java @@ -2,8 +2,9 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Rendering; import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.ModelsCache; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.TextureCache; public interface SceneRender { public void CleanUp(); - public void Render(IScene scene, ModelsCache modelsCache) ; + public void Render(IScene scene, ModelsCache modelsCache, TextureCache textureCache) ; } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java index d23b84b..a677895 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java @@ -36,21 +36,36 @@ public class ShaderProgram { } protected int CreateShader(String ShaderCode, int ShaderType){ + ShaderCode = NormalizeShaderCode(ShaderCode); + int ShaderID = glCreateShader(ShaderType); if(ShaderID == 0){ - Logger.error("Failed to create shader of Type: " + ShaderType); + throw new RuntimeException("Failed to create shader of Type: " + ShaderType); } + + Logger.debug("Compiling OpenGL shader type [{}]. Header: [{}]", + ShaderType, + ShaderCode.substring(0, Math.min(ShaderCode.length(), 80)).replace("\n", "\\n").replace("\r", "\\r")); + glShaderSource(ShaderID, ShaderCode); glCompileShader(ShaderID); + if(glGetShaderi(ShaderID, GL_COMPILE_STATUS) == GL_FALSE){ - Logger.error("Failed to compile shader: [{}]",glGetShaderInfoLog(ShaderID, 1024)); + String infoLog = glGetShaderInfoLog(ShaderID, 1024); + glDeleteShader(ShaderID); + throw new RuntimeException("Failed to compile shader of Type [" + ShaderType + "]: " + infoLog); } glAttachShader(ProgramID, ShaderID); return ShaderID; } - + private String NormalizeShaderCode(String shaderCode) { + if (shaderCode != null && !shaderCode.isEmpty() && shaderCode.charAt(0) == '\uFEFF') { + return shaderCode.substring(1); + } + return shaderCode; + } public int GetProgramID(){return ProgramID;} public void LinkShaderProgram(List ShaderModules){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/UniformsMap.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/UniformsMap.java new file mode 100644 index 0000000..8f082c6 --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/UniformsMap.java @@ -0,0 +1,56 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader; + +import org.joml.Matrix4f; +import org.joml.Vector2f; +import org.joml.Vector4f; +import org.lwjgl.system.MemoryStack; + +import java.util.HashMap; +import java.util.Map; + +import static org.lwjgl.opengl.GL20.*; + +public class UniformsMap { + private final int programID; + private final Map Uniforms; + + public UniformsMap(int programId) { + this.programID = programId; + Uniforms = new HashMap<>(); + } + + public void CreateUniform(String uniformName) { + int uniformLocation = glGetUniformLocation(programID, uniformName); + if (uniformLocation < 0) { + throw new RuntimeException("Could not find uniform: " + uniformName + " in shader program: " + + programID); + } + Uniforms.put(uniformName, uniformLocation); + } + + private int GetUniformLocation(String uniformName) { + Integer location = Uniforms.get(uniformName); + if (location == null) { + throw new RuntimeException("Could not find uniform [" + uniformName + "]"); + } + return location.intValue(); + } + + public void SetUniform(String uniformName, int value) { + glUniform1i(GetUniformLocation(uniformName), value); + } + + public void SetUniform(String uniformName, Matrix4f value) { + try (MemoryStack stack = MemoryStack.stackPush()) { + glUniformMatrix4fv(GetUniformLocation(uniformName), false, value.get(stack.mallocFloat(16))); + } + } + + public void SetUniform(String uniformName, Vector4f value) { + glUniform4f(GetUniformLocation(uniformName), value.x, value.y, value.z, value.w); + } + + public void SetUniform(String uniformName, Vector2f value) { + glUniform2f(GetUniformLocation(uniformName), value.x, value.y); + } +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Interfaces/ITextureCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Interfaces/ITextureCache.java new file mode 100644 index 0000000..f58af2a --- /dev/null +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Interfaces/ITextureCache.java @@ -0,0 +1,37 @@ +package net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces; + +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.GraphUtils; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.CubeMapTexture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ITexture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ImageSrc; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Texture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandPool; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Queues.Queue; +import org.tinylog.Logger; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; + +public interface ITextureCache { + public ITexture AddCubeMapTexture(VulkanContext VkCtx, String ID, String[] FacePaths, int Format); + public ITexture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format); + public ITexture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format, boolean PaddingTexture); + public ITexture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format); + public ITexture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format, boolean PaddingTexture); + + public void TransitionTexts(VulkanContext VkCtx, CommandPool CmdPool, Queue queue); + public ITexture GetTexture(String TexturePath); + public Map GetTextureCache(); + public List GetTextureList(); + public int GetPosition(String ID); + public void CleanUp(VulkanContext VkCtx); +} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Projection/Project3D.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Projection/Project3D.java similarity index 56% rename from src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Projection/Project3D.java rename to src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Projection/Project3D.java index 5357f6f..b718cc0 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Projection/Project3D.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Projection/Project3D.java @@ -1,26 +1,37 @@ -package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Projection; +package net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Projection; +import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import org.joml.Matrix4f; public class Project3D { 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 float ZFarPlane; + private float ZNearPlane; private int LastWidth; private int LastHeight; + private final float OriginalNear; + private final float OriginalFar; public Project3D(float FOV, float zNear, float zFar, int Width, int Height){ this.FOV = FOV; - this.ZFarPlane = zFar; - this.ZNearPlane = zNear; + OriginalNear = zNear; + OriginalFar = zFar; + this.ZFarPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? zNear : zFar; + this.ZNearPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? zFar : zNear; ProjectionMatrix = new Matrix4f(); Resize(Width, Height); LastWidth = Width; LastHeight = Height; } + public void SetFarPlanes(){ + ZFarPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? OriginalNear : OriginalFar; + ZNearPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? OriginalFar : OriginalNear; + Resize(LastWidth,LastHeight); + } + public void ChangeFOV(float newFOV){ FOV = newFOV; Resize(LastWidth,LastHeight); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/CubeMapTexture.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/CubeMapTexture.java index d344b79..be07f9f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/CubeMapTexture.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/CubeMapTexture.java @@ -164,4 +164,19 @@ public class CubeMapTexture implements ITexture{ return TextureType.CubeMap; } + @Override + public void Bind() { + + } + + @Override + public void CleanUp() { + + } + + @Override + public String GetTexturePath() { + return ""; + } + } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/ITexture.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/ITexture.java index f13d4c8..e703045 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/ITexture.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/ITexture.java @@ -3,9 +3,24 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline. import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView; +import org.lwjgl.opengl.GL11; import java.nio.ByteBuffer; +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11.GL_NEAREST; +import static org.lwjgl.opengl.GL11.GL_RGBA; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_MAG_FILTER; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_MIN_FILTER; +import static org.lwjgl.opengl.GL11.GL_UNPACK_ALIGNMENT; +import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE; +import static org.lwjgl.opengl.GL11.glBindTexture; +import static org.lwjgl.opengl.GL11.glPixelStorei; +import static org.lwjgl.opengl.GL11.glTexImage2D; +import static org.lwjgl.opengl.GL11.glTexParameteri; +import static org.lwjgl.opengl.GL30.glGenerateMipmap; + public interface ITexture { public enum TextureType{ FlatImage, @@ -22,4 +37,10 @@ public interface ITexture { public String GetID(); public ImageView GetImageView(); public TextureType getType(); + + + public void Bind(); + public void CleanUp(); + + public String GetTexturePath(); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/Texture.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/Texture.java index 0dd9906..fbc604d 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/Texture.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/Texture.java @@ -1,6 +1,7 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Util.Maths.T4Math; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView; @@ -213,4 +214,19 @@ public class Texture implements ITexture { public TextureType getType() { return TextureType.FlatImage; } + + @Override + public void Bind() { + + } + + @Override + public void CleanUp() { + CleanUp(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + + @Override + public String GetTexturePath() { + return ID; + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java index 40b4f66..9279d28 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java @@ -2,6 +2,7 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline. import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.GraphUtils; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; @@ -16,7 +17,7 @@ import java.util.UUID; import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; -public class TextureCache { +public class TextureCache implements ITextureCache { public static final int MAX_TEXTURES = 128; private final IndexedLinkedHashMap TextureMap; private final List ActualTextures; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java index ea2e3f2..0f49bdd 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java @@ -5,7 +5,7 @@ import net.halbear.Terrain4J.EngineCore.Main.Scene.Camera; import net.halbear.Terrain4J.EngineCore.Main.Scene.ILight; import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene; import net.halbear.Terrain4J.EngineCore.Main.Scene.SceneLightingManager; -import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Projection.Project3D; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Projection.Project3D; import org.joml.Matrix4f; import org.joml.Vector3f; import org.joml.Vector4f; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java index 1b6e961..d4b8e28 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java @@ -420,6 +420,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering if(Actor instanceof Actor3DElement &&( !((Actor3DElement) Actor).RenderOnTopOfPlayer && ClientSideNetworkUtils.OwnsActor(((Actor3DElement) Actor).GetParentID()) || new Vector3f().set(Actor.GetPosition()).sub(instance.scene().GetCamera().GetPosition()).absolute().lengthSquared() < 4f)) continue; else { VulkanModel model = modelsCache.GetModel(Actor.GetModelID()); + // if(model == null) continue; List VkMeshList = model.GetVkMeshList(); int MeshCount = VkMeshList.size(); for (int j = 0; j < MeshCount; j++) { diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/ClientSession.java b/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/ClientSession.java index ffb4c5f..f363f3f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/ClientSession.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/ServerNetworking/ClientSession.java @@ -309,6 +309,7 @@ public class ClientSession implements ServerConnection { } public void QueueWritePacket(Packet outPacket) { + if(!selectionKey.isValid()) return; if (outPacket.PacketTypeByte == Packet.PACKET_UPDATE_MODEL_ID) { Logger.debug("Queueing model ID update packet for actor [{}]", outPacket.TargetID); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java index 87a5eda..b4a1813 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/MainThread.java @@ -44,7 +44,7 @@ public class MainThread extends EngineThread { } profiling.addAll(Collections.singleton(ThreadInformation)); EngineConfig.getInstance().SetSystemProfiling(profiling); - gameLogic.SecondUpdate(PrimaryRuntime.GetEngineInstance()); + if(RenderThread.AllowRender())gameLogic.SecondUpdate(PrimaryRuntime.GetEngineInstance()); } public void UpdateTickRateThreshold(){ 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 a562f72..ed9d455 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java @@ -27,6 +27,7 @@ public class RenderThread extends EngineThread { case OpenGL -> render = new OpenGLRenderer(engineInstance); } } + engineInstance.scene().GetProjection().SetFarPlanes(); super(engineInstance,appLogic,"Render"); this.initData = initData; if(Headless) return; @@ -60,9 +61,13 @@ public class RenderThread extends EngineThread { @Override public void FrameEvent(long now, long InitialTime) { if (AllowRendering) { - gameLogic.RenderThreadInput(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); + if(EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.Vulkan)gameLogic.RenderThreadInput(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); if (Headless) return; render.render(PrimaryRuntime.GetEngineInstance()); +// if(EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL){ +// gameLogic.CameraInput(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); +// gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); +// } } } @Override diff --git a/terrain4j.properties b/terrain4j.properties index 3126c4e..eba432f 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -1,5 +1,5 @@ #created new properties file -#Tue Aug 25 20:07:31 BST 2026 +#Sat Aug 29 04:15:30 BST 2026 AlphaToCoverage=false Debug_Shaders=false DefaultTexturePath=resources/EngineResources/Texture/NoTexture.png @@ -8,7 +8,7 @@ LoadingScreenLocation=resources/EngineResources/Texture/Terrain4JTitleImage.png MaxAllowedVulkanCrashes=10 PhysicalDeviceName= Renderer=1 -RenderingAPI=VULKAN +RenderingAPI=Vulkan RequestedImages=3 ShaderRecompiling=true ShadowMapSize=2048