more OpenGL support, cameras and 3D projection and it now shares 3D models with vulkan, OpenGL does not work if launched, and switching to vulkan from OpenGL does not work

This commit is contained in:
Halbear 2026-08-29 04:24:05 +01:00
parent 5ea45890c8
commit 5518dae1d7
43 changed files with 1298 additions and 187 deletions

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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<MaterialData> Materials = new ArrayList<>();
private List<ModelData> 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{
}
}

View file

@ -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();

View file

@ -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;

View file

@ -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()

View file

@ -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);

View file

@ -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;

View file

@ -17,6 +17,8 @@ public class ModelLoader { // Model Utility class kinda like a model version of
}
public static List<String> ModelPaths = new ArrayList<>();
public static List<MaterialData> LoadMaterials(String[] Path){
var Result = new ArrayList<MaterialData>();
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{

View file

@ -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,6 +569,7 @@ public class GameCore implements GameLogic {
@Override
public void SecondUpdate(EngineInstance engineInstance) {
if(PrimaryRuntime.IsServer || RenderThread.Headless || PrimaryRuntime.GetRenderThread() == null) return;
try {
SettingPerformanceMetrics.clear();
List<String[]> Metrics = new ArrayList<>();
String[] ISceneDetails = new String[9];
@ -563,14 +577,14 @@ public class GameCore implements GameLogic {
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[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));
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());
@ -583,5 +597,8 @@ public class GameCore implements GameLogic {
SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetMemoryProfiling());
SettingPerformanceMetrics.addAll(EngineConfig.getInstance().GetSystemProfiling());
PerformanceMetrics = List.copyOf(SettingPerformanceMetrics);
} catch(NullPointerException e){
}
}
}

View file

@ -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) {

View file

@ -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();
}
}

View file

@ -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;

View file

@ -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<String,AudioInstance> 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;
}
}

View file

@ -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.*;

View file

@ -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;
}
}

View file

@ -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<ShaderProgram.ShaderModuleGL> 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);
}
}

View file

@ -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<GLMesh> 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<GLMesh> 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;
}
}

View file

@ -17,8 +17,13 @@ public class GLMesh {
private int VertexCount;
private int VAO_ID;
private List<Integer> 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);
}

View file

@ -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<GLMesh> Meshes, String VertexPath, String IndexPath) {
public class GLModel {
private final String ModelID;
private List<GLMesh> MeshList;
public GLModel(String ModelID, List<GLMesh> MeshList, ModelData data) {
this.ModelID = ModelID;
this.MeshList = MeshList;
}
public void CleanUp() {
MeshList.forEach(GLMesh::CleanUp);
}
public String GetId() {
return ModelID;
}
public List<GLMaterial> GetMaterialList(ModelsCache cache) {
List<GLMaterial> materials = new ArrayList<>();
MeshList.forEach(mesh->{
materials.add(cache.GetMaterial(mesh.MaterialID()));
});
return materials;
}
public List<GLMesh> GetMeshList() {
return MeshList;
}
}

View file

@ -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<GLMaterial> 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<Integer> 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;
// }
//}

View file

@ -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<String, GLMesh> MeshMap;
private final Map<String, GLModel> ModelMap;
private final Map<String, GLMaterial> 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<String, GLMesh> getMeshMap() {
return MeshMap;
}
public void CleanUp() {
ModelMap.values().forEach(GLModel::CleanUp);
cleanup();
}
public void loadModels(List<ModelData> 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<GLMesh> 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<MaterialData> 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<String, GLModel> GetModelMap() {
return ModelMap;
}
}

View file

@ -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;
}
}

View file

@ -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<String, ITexture> 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<String, ITexture> GetTextureCache() {
return TextureMap;
}
@Override
public List<ITexture> GetTextureList() {
return List.of();
}
@Override
public int GetPosition(String ID) {
return 0;
}
@Override
public void CleanUp(VulkanContext VkCtx) {
}
}

View file

@ -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<ShaderProgram.ShaderModuleGL> 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);
uniformsMap.SetUniform("projectionMatrix", scene.GetProjection().GetProjectionMatrix());
uniformsMap.SetUniform("viewMatrix", scene.GetCamera().GetViewMatrix());
uniformsMap.SetUniform("textureSampler", 0);
Map<String,GLModel> 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);
});
// scene.GetActors().forEach(actor -> {
// GLMesh mesh = modelsCache.getMeshMap().get(actor.GetModelID());
// glBindVertexArray(mesh.GetVaoID());
// glDrawArrays(GL_TRIANGLES, 0, mesh.GetVertexCount());
// }
// );
}
glBindVertexArray(0);

View file

@ -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) ;
}

View file

@ -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<Integer> ShaderModules){

View file

@ -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<String, Integer> 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);
}
}

View file

@ -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<String, ITexture> GetTextureCache();
public List<ITexture> GetTextureList();
public int GetPosition(String ID);
public void CleanUp(VulkanContext VkCtx);
}

View file

@ -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);

View file

@ -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 "";
}
}

View file

@ -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();
}

View file

@ -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;
}
}

View file

@ -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<String, ITexture> TextureMap;
private final List<String> ActualTextures;

View file

@ -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;

View file

@ -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<VulkanMesh> VkMeshList = model.GetVkMeshList();
int MeshCount = VkMeshList.size();
for (int j = 0; j < MeshCount; j++) {

View file

@ -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);
}

View file

@ -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(){

View file

@ -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

View file

@ -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