This commit is contained in:
Harrison Corlett 2026-06-23 13:20:43 +01:00
parent eb01ec4877
commit f135d99d74
60 changed files with 924 additions and 90 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View file

@ -0,0 +1,2 @@
Sky texture:
kaori669 on deviant art

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

View file

@ -149,4 +149,9 @@ void main() {
vec3 color = ambient + Lo;
outFragColor = vec4(color, 1.0f);
if (length(normal) < 0.001) {
outFragColor = vec4(albedo,1.0f);
return;
}
}

View file

@ -2,7 +2,7 @@
layout(constant_id = 0) const int USE_AA = 0;
const float GAMMA_CONST = 0.8545;
const float GAMMA_CONST = 0.6545;
const float SPAN_MAX = 8.0;
const float REDUCE_MIN = 1.0/128.0;
const float REDUCE_MUL = 1.0/32.0;

View file

@ -2,7 +2,7 @@
layout(constant_id = 0) const int USE_AA = 0;
const float GAMMA_CONST = 0.8545;
const float GAMMA_CONST = 0.4545;
const float SPAN_MAX = 8.0;
const float REDUCE_MIN = 1.0/128.0;
const float REDUCE_MUL = 1.0/32.0;

View file

@ -1,6 +1,6 @@
#version 450
const int MAX_TEXTURES = 512;
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;

View file

@ -1,6 +1,6 @@
#version 450
const int MAX_TEXTURES = 512;
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;

View file

@ -1,6 +1,6 @@
#version 450
const int MAX_TEXTURES = 512;
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;

View file

@ -1,6 +1,6 @@
#version 450
const int MAX_TEXTURES = 512;
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
@ -13,6 +13,13 @@ layout(location = 0) out vec4 outPos;
layout(location = 2) out vec4 outNormal;
layout(location = 3) out vec4 outPBR;
const float bayerMatrix[16] = float[](
0.0 / 16.0, 8.0 / 16.0, 2.0 / 16.0, 10.0 / 16.0,
12.0 / 16.0, 4.0 / 16.0, 14.0 / 16.0, 6.0 / 16.0,
3.0 / 16.0, 11.0 / 16.0, 1.0 / 16.0, 9.0 / 16.0,
15.0 / 16.0, 7.0 / 16.0, 13.0 / 16.0, 5.0 / 16.0
);
struct Material {
vec4 diffuseColor;
uint hasTexture;
@ -55,13 +62,17 @@ void main()
} else {
outAlbedo = material.diffuseColor;
}
/*int Intensity = 4;
int x = int(gl_FragCoord.x) % Intensity;
int y = int(gl_FragCoord.y) % Intensity;
float threshold = bayerMatrix[y * Intensity + x];
if(outAlbedo.a < threshold || outAlbedo.a < 0.05f) discard;*/
if(outAlbedo.a < 0.75) discard;
mat3 TBN = mat3(inTangent, inBitangent, inNormal);
vec3 newNormal = calcNormal(material, inNormal, inTextCoords, TBN);
outNormal = vec4(newNormal, 1.0f);
outNormal = vec4(newNormal, outAlbedo.a);
float ao = 0.5f;
float roughnessFactor = 0.0f;
@ -75,6 +86,6 @@ void main()
metallicFactor = material.metallicFactor;
}
outPBR = vec4(ao, roughnessFactor, metallicFactor, 1.0f);
outPBR = vec4(ao, roughnessFactor, metallicFactor, outAlbedo.a);
}

View file

@ -1,6 +1,6 @@
#version 450
const int MAX_TEXTURES = 512;
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
@ -37,7 +37,7 @@ void main()
Material material = matUniform.materials[push_constants.materialIdx];
if(material.hasTexture == 1){
vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
if(texColor.a < 0.05 || texColor.a >= 0.9){discard;}
if(texColor.a >= 0.9){discard;}
outAlbedo = texColor;
} else{
outAlbedo = material.diffuseColor;

View file

@ -1,6 +1,6 @@
#version 450
const int MAX_TEXTURES = 512;
const int MAX_TEXTURES = 128;
layout(location = 0) in vec4 inPos;
layout(location = 1) in vec3 inNormal;
@ -13,6 +13,14 @@ layout(location = 0) out vec4 outPos;
layout(location = 2) out vec4 outNormal;
layout(location = 3) out vec4 outPBR;
const float bayerMatrix[16] = float[](
0.0 / 16.0, 8.0 / 16.0, 2.0 / 16.0, 10.0 / 16.0,
12.0 / 16.0, 4.0 / 16.0, 14.0 / 16.0, 6.0 / 16.0,
3.0 / 16.0, 11.0 / 16.0, 1.0 / 16.0, 9.0 / 16.0,
15.0 / 16.0, 7.0 / 16.0, 13.0 / 16.0, 5.0 / 16.0
);
struct Material {
vec4 diffuseColor;
uint hasTexture;
@ -57,7 +65,7 @@ void main()
}
if(outAlbedo.a < 0.05 || outAlbedo.a >= 0.75) discard;
if(outAlbedo.a >= 0.75 || outAlbedo.a < 0.05f) discard;
mat3 TBN = mat3(inTangent, inBitangent, inNormal);
vec3 newNormal = calcNormal(material, inNormal, inTextCoords, TBN);

View file

@ -0,0 +1,5 @@
#version 450
void main() {
}

View file

@ -0,0 +1,5 @@
#version 450
void main() {
}

View file

@ -0,0 +1,5 @@
#version 450
void main() {
}

View file

@ -0,0 +1,11 @@
#version 450
layout(location = 0) in vec3 outTexCoords;
layout(location = 1) out vec4 outColor;
layout(set = 2, binding = 0) uniform samplerCube skyboxSampler;
void main() {
outColor = vec4(texture(skyboxSampler, outTexCoords).rgb, 1.0);
}

View file

@ -0,0 +1,18 @@
#version 450
layout(location = 0) in vec3 inPosition;
layout(location = 0) out vec3 outTexCoords;
layout(set = 0, binding = 0) uniform ProjectionBuffer {
mat4 proj;
} uboProj;
layout(set = 1, binding = 0) uniform ViewBuffer {
mat4 view;
} uboView;
void main() {
outTexCoords = inPosition;
mat4 skyView = mat4(mat3(uboView.view));
vec4 pos = uboProj.proj * skyView * vec4(inPosition, 1.0);
gl_Position = vec4(pos.xy, 0.0, pos.w);
}

View file

@ -3,7 +3,9 @@ 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.SkyBox;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiRenderer;
import net.halbear.Terrain4J.EngineCore.Vulkan.GUI.GuiTexture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DeferredRendering.LightRenderer;
@ -58,6 +60,8 @@ public class Render {
private TextureCache textureCache;
private EngineConfig.AntiAliasType CurrentAAMode;
private final boolean Deferred;
private float LastGamma = 0.8545f;
public TextureCache GetTextureCache(){return textureCache;}
public MaterialsCache GetMaterialsCache(){return materialsCache;}
@ -105,6 +109,7 @@ public class Render {
modelsCache = new ModelsCache();
Resize = false;
CurrentAAMode = EngineConfig.getInstance().RenderAAType();
LastGamma = EngineConfig.getInstance().GetGamma();
}
public void Initialise(InitData initData){
@ -115,6 +120,15 @@ public class Render {
Logger.debug("Loaded {} Materials", Materials.size());
List<GuiTexture> guiTextures = initData.GuiTextures();
String[] SkyBoxTextures = new String[]{
"resources/EngineResources/SkyBoxTextures/skySide.png",
"resources/EngineResources/SkyBoxTextures/skySide.png",
"resources/EngineResources/SkyBoxTextures/SkyTop.png",
"resources/EngineResources/SkyBoxTextures/SkyTop.png",
"resources/EngineResources/SkyBoxTextures/skySide.png",
"resources/EngineResources/SkyBoxTextures/skySide.png"
};
textureCache.AddCubeMapTexture(RendererContext, DeferredSceneRender.SkyBoxID,SkyBoxTextures,VK_FORMAT_R8G8B8A8_SRGB);
if(guiTextures != null){
initData.GuiTextures().forEach(texture -> textureCache.AddTexture(RendererContext, texture.TexturePath(), texture.TexturePath(), VK_FORMAT_R8G8B8A8_SRGB));
}
@ -127,6 +141,7 @@ public class Render {
Models.addAll(initData.Models());
Logger.debug("Loading {} models", Models.size());
//modelsCache.CleanUp(RendererContext);
modelsCache.CreateSkybox(RendererContext, SkyBox.SkyBoxMesh.VERTICES,DeferredSceneRender.SkyBoxID);
modelsCache.loadModels(RendererContext, Models, CommandPools[0], GraphicsQueue);
Logger.debug("Loaded {} models", Models.size());
@ -227,6 +242,10 @@ public class Render {
public void render(EngineInstance engineInstance){
if(Deferred) DeferredRender(engineInstance);
else ForwardRender(engineInstance);
// if(LastGamma != EngineConfig.getInstance().GetGamma()){
// vkDeviceWaitIdle(RendererContext.GetDevice().FetchVulkanDevice());
// PrimaryRuntime.GetRenderThread().RefreshRenderer();
// }
}
private void resize(EngineInstance engineInstance){

View file

@ -41,7 +41,8 @@ public class Window {
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_MAXIMIZED, GLFW_FALSE);
glfwWindowHint(GLFW_ALPHA_BITS, 0);
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_FALSE);
handle = glfwCreateWindow(width, height, title, MemoryUtil.NULL, MemoryUtil.NULL);
if (handle == MemoryUtil.NULL) {
//throw new RuntimeException("Failed to create the GLFW window");
@ -72,6 +73,7 @@ public class Window {
IconBuffer.free(); //free the buffer once icon is set so when the program closes there isn't memory still floating around
Logger.debug("Freeing icon Buffer");
glfwSetWindowFocusCallback(handle, new GLFWWindowFocusCallback() {
@Override
public void invoke(long window, boolean focused) {

View file

@ -55,7 +55,7 @@ public class EngineConfig {
private String PhysicalDeviceName;
private int RequestedImages;
private String IconPath = "/WindowResources/Icon/";
private String DefaultTexturePath = "resources/EngineResources/Texture/DefaultTexture.png";
private String DefaultTexturePath = "resources/EngineResources/Texture/NoTexture.png";
private String IconName = "ProgramIcon.png";
private float FOV = 60f;
private float zFarPlane;
@ -73,7 +73,13 @@ public class EngineConfig {
public boolean AlphaToCoverage = false;
public boolean CompatibilityMode = false;
public Renderer renderer = Renderer.Forward;
public int ShadowMapSize = 16;
public float Gamma = 0.8545f;
public int MaxVulkanCrashesAllowed = 10;
public int GetMaxVulkanCrashes(){return MaxVulkanCrashesAllowed;}
public void SetShadowMapSize(int ShadowSize){this.ShadowMapSize = ShadowSize;}
public int GetShadowMapSize(){return ShadowMapSize;}
public void SetRenderer(Renderer renderer){this.renderer = renderer;}
public boolean DeferredRendering(){return renderer == Renderer.Deferred;}
public boolean AlphaToCoverage(){return AlphaToCoverage;}
@ -85,6 +91,7 @@ public class EngineConfig {
CPU_CORE_COUNT = CoreCount;
CPU_DETAILS = CPU_NAME + " with " + CPU_CORE_COUNT + " Threads";
}
public float GetGamma(){return Gamma;}
public boolean CompatibilityMode(){return CompatibilityMode;}
public void SetCompatibilitMode(boolean compatibilityMode){this.CompatibilityMode = compatibilityMode;}
public int GetCoreCount(){return CPU_CORE_COUNT;}
@ -217,6 +224,8 @@ public class EngineConfig {
zFarPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_far_plane", 100.0f).toString()));
AAValue = (Integer.parseInt(EngineConfigVar.getOrDefault("anti_alias_mode", 1).toString()));
renderer = Integer.parseInt(EngineConfigVar.getOrDefault("Renderer", 1).toString()) == 0 ? Renderer.Forward: Renderer.Deferred;
ShadowMapSize = Integer.parseInt(EngineConfigVar.getOrDefault("ShadowMapSize", 16).toString());
MaxVulkanCrashesAllowed = Integer.parseInt(EngineConfigVar.getOrDefault("MaxAllowedVulkanCrashes", 10).toString());
CompatibilityMode = Boolean.parseBoolean(EngineConfigVar.getOrDefault("compatibility_mode", false).toString());
AlphaToCoverage = Boolean.parseBoolean(EngineConfigVar.getOrDefault("AlphaToCoverage", false).toString());
ForwardSceneRender.SetDualPassRendering(Boolean.parseBoolean(EngineConfigVar.getOrDefault("DualPassRendering", true).toString()));

View file

@ -0,0 +1,32 @@
package net.halbear.Terrain4J.EngineCore.Logic.Rendering;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Camera;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import java.nio.ByteBuffer;
public class SkyBox {
public static class SkyBoxMesh{
public static final float[] VERTICES = {
-1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f
};
}
}

View file

@ -38,7 +38,7 @@ import static org.lwjgl.glfw.GLFW.*;
public class GameCore implements GameLogic {
private static final float MOUSE_SENSITIVITY = 0.1f;
private static final float MOVEMENT_SPEED = 0.525f;
private static final float MOVEMENT_SPEED = 0.025f;
private static final String SOUND_BUFFER_MUSIC = "music-sound-buffer";
private static final String SOUND_BUFFER_PLAYER = "player-sound-buffer";
@ -80,25 +80,25 @@ public class GameCore implements GameLogic {
List<ModelData> models = new ArrayList<>();
MusicParticle = ModelLoader.LoadModel("resources/models/MusicParticle/MusicParticle.json");
List<MaterialData> MusicParticleMat = ModelLoader.LoadMaterials("resources/models/MusicParticle/MusicParticle_mat.json");
// ModelData SponzaData = ModelLoader.LoadModel("resources/models/room/living_room.json");
// List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/room/living_room_mat.json");
ModelData SponzaData = ModelLoader.LoadModel("resources/models/Forest/forest.json");
List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Forest/forest_mat.json");
radio = ModelLoader.LoadModel("resources/models/radio/radio.json");
List<MaterialData> SponzaMaterial2 = ModelLoader.LoadMaterials("resources/models/radio/radio_mat.json");
ModelData SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json");
List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json");
ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json");
List<MaterialData> SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json");
// ModelData SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json");
// List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json");
// ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json");
// List<MaterialData> SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json");
scene.AddActor(new Actor("Sponza1", SponzaData.ID(), new Vector3f(0,0f,-5f)));
scene.AddActor(new Actor("Sponza2", SponzaData1.ID(), new Vector3f(0,0f,-5f)));
// scene.AddActor(new Actor("Sponza2", SponzaData1.ID(), new Vector3f(0,0f,-5f)));
CubeActors.forEach(scene::AddActor);
List<MaterialData> materials = new ArrayList<>();
materials.addAll(SponzaMaterial);
materials.addAll(MusicParticleMat);
materials.addAll(SponzaMaterial1);
// materials.addAll(SponzaMaterial1);
materials.addAll(SponzaMaterial2);
models.add(SponzaData1);
// models.add(SponzaData1);
models.add(SponzaData);
models.add(MusicParticle);
models.add(radio);
@ -110,26 +110,26 @@ public class GameCore implements GameLogic {
scene.AddCameraFrame("Fifth", new CameraFrame(new Vector3f(64.92f,158.06f,-35.25f),new Vector3f(-11.20f,156.5f,0.0f),scene.GetCamera().GetFOV(),"Sixth"));
scene.AddCameraFrame("Sixth", new CameraFrame(new Vector3f(94.52f,172.54f,47.57f),new Vector3f(4.3f,329.27f,0.0f),scene.GetCamera().GetFOV(),"NO_FRAME"));
camera.SetPosition(40.0f, 155.0f, -42.0f);
camera.SetPosition(0,0,0);
//camera.SetPosition(0,0,0);
camera.SetRotation((float) Math.toRadians(10.0f), (float) Math.toRadians(-90.0f),0);
camera.SetRotation(0,0,0);
//camera.SetRotation(0,0,0);
guiTexture = new GuiTexture("resources/EngineResources/Texture/DefaultTexture.png");
guiTexture = new GuiTexture("resources/EngineResources/Texture/Billy.png");
Logger.debug("GUI TEXTURE CREATED, ID->[{}], PATH->[{}]",guiTexture.ID(),guiTexture.TexturePath());
List<GuiTexture> guiTextures = new ArrayList<>();
guiTextures.add(guiTexture);
scene.GetLightingManager().GetAmbientLightColour().set(0.5f, 0.5f, 0.5f);
scene.GetLightingManager().SetAmbientLightIntensity(0.01f);
scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f);
scene.GetLightingManager().SetAmbientLightIntensity(1.5f);
SkyLight = new Light(new Vector3f(0.25f, 1.0f, 1.5f),new Vector3f(0.0f, -1.0f, 0.0f), true, 0.70f);
SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.0f), true, 10.00f);
List<ILight> lights = new ArrayList<>();
//lights.add(new Light(new Vector3f(2.9f,2.75f,1.5f),new Vector3f(0.35f,2.69f,-2.11f),false,3.0f));
//lights.add(new Light(new Vector3f(3.0f,2.5f,0.75f),new Vector3f(2.65f,1.57f,-3.31f),false,0.5f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-433, 445f, -424f),false,300000.0f+ (float)(Math.random() * 10000.0)));
/*lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-433, 445f, -424f),false,300000.0f+ (float)(Math.random() * 10000.0)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-210, 445f, 460f),false,70000.0f + (float)(Math.random() * 15000.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-966, 445f, 204f),false,70000.0f + (float)(Math.random() * 15000.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-176, 445f, 1000f),false,70000.0f + (float)(Math.random() * 15000.0f)));
@ -160,9 +160,10 @@ public class GameCore implements GameLogic {
lights.add(new Light(new Vector3f(0.75f,2.0f,0.75f),new Vector3f(1086, 425, -3375),false,50000.0f));
*/
//lights.add(new Light(new Vector3f(3.0f,2.75f,0.0f),new Vector3f(35.0f, 150.0f, -42.0f),false,100.0f));
//lights.add(new Light(new Vector3f(0.0f,3.0f,0.0f),new Vector3f(40.0f, 155.0f, -35.0f),false,20.0f));
lights.add(new Light(new Vector3f(3.0f,2.75f,0.0f),new Vector3f(35.0f, 150.0f, -42.0f),false,100.0f));
lights.add(new Light(new Vector3f(0.0f,3.0f,0.0f),new Vector3f(40.0f, 155.0f, -35.0f),false,20.0f));
lights.add(SkyLight);
ILight[] lightArr = new ILight[lights.size()];

View file

@ -2,7 +2,9 @@ package net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs;
import imgui.ImGui;
import imgui.flag.ImGuiCond;
import imgui.flag.ImGuiInputTextFlags;
import imgui.flag.ImGuiWindowFlags;
import imgui.type.ImFloat;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
@ -15,6 +17,7 @@ import org.joml.Vector3f;
import org.tinylog.Logger;
public class PerformanceOverlay implements GUIOverlay {
private final ImFloat GammaValue = new ImFloat(0.8545f);
@Override
public void RenderGUI(EngineInstance engineInstance, long frameTimeNS, GameCore parent) {
int windowFlags = ImGuiWindowFlags.NoDecoration
@ -139,6 +142,10 @@ public class PerformanceOverlay implements GUIOverlay {
EngineConfig.getInstance().SetAlphaToCoverage(true);
PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext());
}
ImGui.inputFloat("Gamma", GammaValue, 0.0025f, 0.22725f, "%.4f");
if (ImGui.isItemDeactivatedAfterEdit()) {
// EngineConfig.getInstance().Gamma = GammaValue.get();
}
ImGui.separator();
ImGui.text("Level Tools:");
if(ImGui.button("Spawn Radio")){

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Main.Scene;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.SkyBox;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection.Project3D;
@ -31,4 +32,6 @@ public interface IScene {
public String GetActiveCameraFrame();
public void SetUpAudio(EngineInstance engineInstance);
public ISceneLightingManager GetLightingManager();
public SkyBox GetSkyBox();
public void SetSkyBox(SkyBox skyBox);
}

View file

@ -5,6 +5,7 @@ import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput;
import net.halbear.Terrain4J.EngineCore.Input.MouseListener;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.SkyBox;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIs.PerformanceOverlay;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Projection.Project3D;
@ -38,10 +39,17 @@ public class Scene implements IScene {
public float CurrentTransitionTick = 0;
private Vector2f LastMousePos = new Vector2f(0,0);
private final ISceneLightingManager lightingManager;
private SkyBox skyBox;
public List<String> ActiveGUIs = new ArrayList<>();
public Map<String, GUIOverlay> GUIReg = new HashMap<>();
public void SetSkyBox(SkyBox skyBox){
this.skyBox = skyBox;
}
public SkyBox GetSkyBox(){return skyBox;}
public Scene(Window window) {
lightingManager = new SceneLightingManager(1000,new Vector3f(1f,1f,1f), 0.5f);
Actors = new ArrayList<>();

View file

@ -7,6 +7,7 @@ import java.util.Arrays;
import java.util.List;
public class SceneLightingManager implements ISceneLightingManager {
public static int SHADOW_MAP_CASCADE_COUNT = 10;
public static int MaxLights;
private Vector3f AmbientLightingColour;
private float AmbientLightIntensity;

View file

@ -15,6 +15,7 @@ public class RenderThread extends EngineThread {
private Render render;
private Window window;
private final InitData initData;
public static int VulkanCrashCount = 0;
public RenderThread(Window window, EngineInstance engineInstance, InitData initData, GameLogic appLogic) {
//this.window = window;
@ -24,6 +25,17 @@ public class RenderThread extends EngineThread {
render.Initialise(initData);
}
public void RestartCrashedRenderer(){
if(VulkanCrashCount < EngineConfig.getInstance().GetMaxVulkanCrashes()){
RefreshRenderer();
VulkanCrashCount++;
}else{
Logger.error("MAX VULKAN CRASHES REACHED, CLOSING SOFTWARE");
PrimaryRuntime.GetEngineInstance().window().setShouldClose();
PrimaryRuntime.CloseRuntime();
}
}
public Render GetRenderer(){return render;}
@Override
@ -40,6 +52,7 @@ public class RenderThread extends EngineThread {
}
public void RefreshRenderer(){
Logger.debug("REFRESHING RENDERER");
render.cleanup();
render = new Render(PrimaryRuntime.GetEngineInstance());
render.Initialise(initData);

View file

@ -145,7 +145,7 @@ public class GuiRenderer {
var guiTexture = GuiTextures.get(i);
String descriptorID = guiTexture.TexturePath();
DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device, descriptorID, 1, TextDescriptorSetLayout)[0];
Texture texture = textureCache.GetTexture(guiTexture.TexturePath());
ITexture texture = textureCache.GetTexture(guiTexture.TexturePath());
descriptorSet.SetImage(device,texture.GetImageView(),FontsTextureSampler,TextDescriptorSetLayout.GetLayoutInfo().Binding());
//Logger.debug("TEXTURE ID -> [{}] DESCRIPTOR SET -> [{}] TEXTURE -> [{}] IMAGE PATH -> [{}] TEXTURE SAMPLER ->[{}]",guiTexture.ID(),descriptorSet.GetVkDescriptorSet(),texture,guiTexture.TexturePath(),FontsTextureSampler);
GuiTexturesMap.put(guiTexture.ID(),descriptorSet.GetVkDescriptorSet());

View file

@ -12,7 +12,7 @@ import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
public class MultiRenderTargetAttachments {
public static final int ALBEDO_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT;
public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT;
public static final int NORMAL_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
public static final int PBR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
public static final int POSITION_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;

View file

@ -124,6 +124,7 @@ public class DefaultPipeline implements Pipeline {
ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout());
}
Logger.debug("registered Descriptor sets");
int[] ColourFormats = BuildInfo.GetColourFormat();
int ColourFormatCount = ColourFormats.length;
@ -135,6 +136,8 @@ public class DefaultPipeline implements Pipeline {
.colorAttachmentCount(ColourFormatCount)
.pColorAttachmentFormats(ColourFormatsBuffer);
Logger.debug("created render info");
if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());}
VkPipelineColorBlendAttachmentState.Buffer BlendAttributeState = VkPipelineColorBlendAttachmentState.calloc(ColourFormatCount,MemStack);
@ -146,10 +149,11 @@ public class DefaultPipeline implements Pipeline {
.alphaBlendOp(VK_BLEND_OP_ADD)
.srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA)
.dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA)
.srcAlphaBlendFactor(BuildInfo.GetBlendingMethod() == 0 ? VK_BLEND_FACTOR_ONE : VK_BLEND_FACTOR_SRC_ALPHA)
.srcAlphaBlendFactor(BuildInfo.GetBlendingMethod() == 0 || BuildInfo.GetBlendingMethod() == 2 ? VK_BLEND_FACTOR_ONE : VK_BLEND_FACTOR_SRC_ALPHA)
.dstAlphaBlendFactor(BuildInfo.GetBlendingMethod() == 0 ? VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA : VK_BLEND_FACTOR_ZERO);
}
}
Logger.debug("created BlendAttributeStates");
var ColourBlendState = VkPipelineColorBlendStateCreateInfo.calloc(MemStack)
.sType$Default()
@ -157,17 +161,44 @@ public class DefaultPipeline implements Pipeline {
var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack)
.sType$Default()
.pSetLayouts(ppLayout)
.pPushConstantRanges(VkPushConstRangeBuffer);
.pSetLayouts(ppLayout);
//.pPushConstantRanges(VkPushConstRangeBuffer);
if (PushConstCount > 0 && VkPushConstRangeBuffer != null) {
PipelineLayoutCreateInfoPtr.pPushConstantRanges(VkPushConstRangeBuffer);
} else {
PipelineLayoutCreateInfoPtr.pPushConstantRanges(null);
}
VulkanUtils.vkCheck(vkCreatePipelineLayout(device.FetchVulkanDevice(), PipelineLayoutCreateInfoPtr,null,longPtr)
,"Unable to create new pipeline layout");
VulkanPipelineLayout = longPtr.get(0);
Logger.debug("created PipelineLayout");
VkPipelineVertexInputStateCreateInfo vertexInputState;
var originalInputState = BuildInfo.GetVertexInputStateCreateInfo();
if (originalInputState != null) {
vertexInputState = VkPipelineVertexInputStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO)
.pVertexBindingDescriptions(originalInputState.pVertexBindingDescriptions())
.pVertexAttributeDescriptions(originalInputState.pVertexAttributeDescriptions());
} else {
// Fix for your cut-off block: Instantiate an explicit, empty state configuration structure
vertexInputState = VkPipelineVertexInputStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO)
.pVertexBindingDescriptions(null)
.pVertexAttributeDescriptions(null);
}
Logger.debug("created vertexInputState");
var PipelineCreateInfo = VkGraphicsPipelineCreateInfo.calloc(1,MemStack)
.sType$Default()
.pStages(ShaderStages)
.pVertexInputState(BuildInfo.GetVertexInputStateCreateInfo())
.pVertexInputState(vertexInputState)
.pInputAssemblyState(AssemblyStateCreateInfo)
.pViewportState(ViewportCreateStateInfo)
.pRasterizationState(RasterizationStateCreateInfo)
@ -177,12 +208,14 @@ public class DefaultPipeline implements Pipeline {
.layout(VulkanPipelineLayout)
.pNext(RendererCreateInfo);
Logger.debug("created PipelineCreateInfo");
if(DepthStencil != null){PipelineCreateInfo.pDepthStencilState(DepthStencil);}
VulkanUtils.vkCheck(vkCreateGraphicsPipelines(device.FetchVulkanDevice(),
VkCtx.GetVkPipelineCache().GetVkPipelineCache(), PipelineCreateInfo,
null, longPtr),"Could not create new pipeline");
Logger.debug("created GraphicsPipeline");
VulkanPipeline = longPtr.get(0);
}
}

View file

@ -22,7 +22,7 @@ public class Attachment {
}
if((Usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) > 0){
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT);
AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
DepthAttachment = true;
}
VkImage = new Image(VkCtx, ImageData);

View file

@ -0,0 +1,169 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.GraphUtils;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.*;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.LongBuffer;
import static org.lwjgl.system.MemoryUtil.memByteBuffer;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.vkCmdPipelineBarrier2;
public class CubeMapTexture implements ITexture{
private final String id;
private final int Height;
private final int Width;
private final Image image;
private final ImageView imageView;
private boolean RecordedTransition;
private VulkanBuffer stgBuffer;
private final long layerSize;
public CubeMapTexture(VulkanContext vkCtx, String id, String[] facePaths, int format) throws IOException {
this.id = id;
ImageSrc firstFace = GraphUtils.LoadImage(facePaths[0]);
Width = firstFace.Width();
Height = firstFace.Height();
this.layerSize = (long) Width * Height * 4;
long totalBufferSize = layerSize * 6;
GraphUtils.CleanImageData(firstFace);
this.stgBuffer = new VulkanBuffer(vkCtx, totalBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
0, 0, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
long mappedAddress = stgBuffer.MapMemory(vkCtx);
ByteBuffer byteBuffer = memByteBuffer(mappedAddress, (int) totalBufferSize);
for (int i = 0; i < 6; i++) {
ImageSrc currentFace = GraphUtils.LoadImage(facePaths[i]);
ByteBuffer pixelData = currentFace.data();
ByteBuffer targetSlice = byteBuffer.duplicate();
targetSlice.position((int) (i * layerSize));
targetSlice.limit((int) ((i + 1) * layerSize));
targetSlice.put(pixelData);
GraphUtils.CleanImageData(currentFace);
}
CreateStgBuffer(vkCtx, byteBuffer);
stgBuffer.UnMapMemory(vkCtx);
var ImageData = new Image.ImageData().Width(Width).Height(Height)
.Usage(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
.Format(format).MipMapLevels(1).ArrayLayers(6).Flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT);
image = new Image(vkCtx, ImageData);
var ImageViewData = new ImageView.ImageViewData().Format(image.GetFormat())
.AspectMask(VK_IMAGE_ASPECT_COLOR_BIT).MipLevels(1).LayerCount(6).ViewType(VK_IMAGE_VIEW_TYPE_CUBE);
imageView = new ImageView(vkCtx.GetDevice(), image.getVulkanImage(), ImageViewData, false);
}
@Override
public boolean HasTransparency() {
return false;
}
@Override
public void SetTransparency(ByteBuffer data) {
}
public void CreateStgBuffer(VulkanContext VkCtx, ByteBuffer data){
int Size = data.remaining();
stgBuffer = new VulkanBuffer(VkCtx, Size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
long MappedMemory = stgBuffer.MapMemory(VkCtx);
ByteBuffer buffer = memByteBuffer(MappedMemory, (int) stgBuffer.GetRequestedSize());
buffer.put(data);
data.flip();
stgBuffer.UnMapMemory(VkCtx);
}
private void RecordImageTransition(MemoryStack stack, CommandBuffer cmd) {
var imageBarrier = VkImageMemoryBarrier2.calloc(1, stack)
.sType$Default()
.oldLayout(VK_IMAGE_LAYOUT_UNDEFINED)
.newLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
.srcStageMask(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
.dstStageMask(VK_PIPELINE_STAGE_TRANSFER_BIT)
.srcAccessMask(0)
.dstAccessMask(VK_ACCESS_TRANSFER_WRITE_BIT)
.subresourceRange(it -> it
.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT)
.baseMipLevel(0)
.levelCount(image.GetMipLevels())
.baseArrayLayer(0)
.layerCount(1))
.image(image.getVulkanImage());
VkDependencyInfo depInfo = VkDependencyInfo.calloc(stack)
.sType$Default()
.pImageMemoryBarriers(imageBarrier);
vkCmdPipelineBarrier2(cmd.GetVulkanCommandBuffer(), depInfo);
}
public void RecordTextureTransition(CommandBuffer commandBuffer){
if(stgBuffer != null && !RecordedTransition){
RecordedTransition = true;
try(var MemStack = MemoryStack.stackPush()){
RecordImageTransition(MemStack, commandBuffer);
RecordCopyBuffer(MemStack, commandBuffer, stgBuffer);
}
}
}
private void RecordCopyBuffer(MemoryStack MemStack, CommandBuffer commandBuffer, VulkanBuffer bufferData){
VkBufferImageCopy.Buffer copyRegions = VkBufferImageCopy.calloc(6, MemStack);
for(int i = 0; i < 6; i++) {
int BaseLayer = i;
copyRegions.get(i).bufferOffset(i * layerSize)
.bufferRowLength(0)
.bufferImageHeight(0)
.imageSubresource(it ->
it.aspectMask(VK_IMAGE_ASPECT_COLOR_BIT)
.mipLevel(0)
.baseArrayLayer(BaseLayer)
.layerCount(1)
).imageOffset(it -> it.x(0).y(0).z(0))
.imageExtent().set(Width, Height, 1);
}
vkCmdCopyBufferToImage(commandBuffer.GetVulkanCommandBuffer(), bufferData.GetBuffer(), image.getVulkanImage(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copyRegions);
}
public void CleanUp(VulkanContext VkCtx){
CleanUpStgBuffer(VkCtx);
imageView.cleanup(VkCtx.GetDevice());
image.CleanUp(VkCtx);
}
public void CleanUpStgBuffer(VulkanContext VkCtx){
if(stgBuffer != null){
stgBuffer.cleanup(VkCtx);
stgBuffer = null;
}
}
public int GetHeight(){return Height;}
public int GetWidth(){return Width;}
public String GetID(){return id;}
public ImageView GetImageView(){return imageView;}
@Override
public TextureType getType() {
return TextureType.CubeMap;
}
}

View file

@ -0,0 +1,25 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView;
import java.nio.ByteBuffer;
public interface ITexture {
public enum TextureType{
FlatImage,
CubeMap
}
public boolean HasTransparency();
public void SetTransparency(ByteBuffer data);
public void CreateStgBuffer(VulkanContext VkCtx, ByteBuffer data);
public void RecordTextureTransition(CommandBuffer commandBuffer);
public void CleanUp(VulkanContext VkCtx);
public void CleanUpStgBuffer(VulkanContext VkCtx);
public int GetHeight();
public int GetWidth();
public String GetID();
public ImageView GetImageView();
public TextureType getType();
}

View file

@ -46,6 +46,7 @@ public class Image {
.height(imageData.Height)
.depth(1))
.mipLevels(MipLevels)
.flags(imageData.Flag)
.arrayLayers(imageData.ArrayLayers)
.samples(imageData.SampleCount)
.initialLayout(VK_IMAGE_LAYOUT_UNDEFINED)
@ -83,18 +84,24 @@ public class Image {
private int MipMapLevels;
private int SampleCount;
private int Usage;
private int Flag;
public ImageData(){
Format = VK_FORMAT_R8G8B8A8_SRGB;
MipMapLevels = 1;
SampleCount = 1;
ArrayLayers = 1;
Flag = 0;
MemoryUsage = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
}
public ImageData MemoryUsage(int memoryUsage){
this.MemoryUsage = memoryUsage;
return this;
}
public ImageData Flags(int flag){
this.Flag = flag;
return this;
}
public ImageData ArrayLayers(int ArrayLayers){
this.ArrayLayers = ArrayLayers;
return this;

View file

@ -19,7 +19,7 @@ import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.VK_ACCESS_2_NONE;
import static org.lwjgl.vulkan.VK13.vkCmdPipelineBarrier2;
public class Texture {
public class Texture implements ITexture {
private final String ID;
private final int Height;
@ -212,4 +212,8 @@ public class Texture {
public int GetWidth(){return Width;}
public String GetID(){return ID;}
public ImageView GetImageView(){return imageView;}
@Override
public TextureType getType() {
return TextureType.FlatImage;
}
}

View file

@ -18,8 +18,8 @@ import java.util.UUID;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB;
public class TextureCache {
public static final int MAX_TEXTURES = 512;
private final IndexedLinkedHashMap<String, Texture> TextureMap;
public static final int MAX_TEXTURES = 128;
private final IndexedLinkedHashMap<String, ITexture> TextureMap;
private final List<String> ActualTextures;
public TextureCache(){
@ -27,14 +27,28 @@ public class TextureCache {
ActualTextures = new ArrayList<>();
}
public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format) {
public ITexture AddCubeMapTexture(VulkanContext VkCtx, String ID, String[] FacePaths, int Format) {
ITexture cubemap = TextureMap.get(ID);
if (cubemap == null) {
try {
cubemap = new CubeMapTexture(VkCtx, ID, FacePaths, Format);
TextureMap.put(ID, cubemap);
ActualTextures.add(ID);
} catch (IOException exception) {
Logger.error("Could not load cubemap texture faces, exception: {}", exception.getMessage());
}
}
return cubemap;
}
public ITexture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format) {
return AddTexture(VkCtx,ID,imageSrc,Format,false);
}
public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format, boolean PaddingTexture){
public ITexture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format, boolean PaddingTexture){
if(TextureMap.size() > MAX_TEXTURES){
throw new IllegalArgumentException("Texture Cache Is Full");
}
Texture newTexture = TextureMap.get(ID);
ITexture newTexture = TextureMap.get(ID);
if(newTexture == null){
newTexture = new Texture(VkCtx, ID, imageSrc, Format);
if(!PaddingTexture)ActualTextures.add(ID);
@ -42,12 +56,12 @@ public class TextureCache {
}
return newTexture;
}
public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) {
public ITexture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) {
return AddTexture(VkCtx,ID,TexturePath,Format,false);
}
public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format, boolean PaddingTexture) {
public ITexture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format, boolean PaddingTexture) {
ImageSrc imageSrc = null;
Texture result = null;
ITexture result = null;
try{
imageSrc = GraphUtils.LoadImage(TexturePath);
result = AddTexture(VkCtx, ID, imageSrc, Format,PaddingTexture);
@ -63,7 +77,7 @@ public class TextureCache {
public void TransitionTexts(VulkanContext VkCtx, CommandPool CmdPool, Queue queue){
Logger.debug("Recording Texture Transition");
IndexedLinkedHashMap<String, Texture> NewTextureMap = new IndexedLinkedHashMap<>();
IndexedLinkedHashMap<String, ITexture> NewTextureMap = new IndexedLinkedHashMap<>();
TextureMap.forEach((name,texture)->{
if(ActualTextures.contains(name)){
NewTextureMap.put(name,texture);
@ -89,12 +103,12 @@ public class TextureCache {
TextureMap.forEach((key,value)->value.CleanUpStgBuffer(VkCtx));
Logger.debug("Recorded Texture Transition");
}
public Texture GetTexture(String TexturePath){
public ITexture GetTexture(String TexturePath){
Logger.debug("Fetching Texture -> [{}]",TexturePath.trim());
return TextureMap.get(TexturePath.trim());
}
public IndexedLinkedHashMap<String, Texture> GetTextureCache(){return TextureMap;}
public List<Texture> GetTextureList(){return new ArrayList<>(TextureMap.values());}
public IndexedLinkedHashMap<String, ITexture> GetTextureCache(){return TextureMap;}
public List<ITexture> GetTextureList(){return new ArrayList<>(TextureMap.values());}
public int GetPosition(String ID){
int result = -1;
if(ID != null){

View file

@ -71,7 +71,6 @@ public class PostProcess {
specConstants = new SpecializationConstants();
ShaderModule[] shaderModules = CreateShaderModules(VkCtx, specConstants);
pipeline = CreatePipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, FragmentUniformDescriptorSetLayout});
Arrays.asList(shaderModules).forEach(shader->shader.CleanUp(VkCtx));
Logger.debug("Post Process Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline());
@ -137,6 +136,7 @@ public class PostProcess {
new ShaderModule(VkCtx,VK_SHADER_STAGE_VERTEX_BIT,VERTEX_SHADER_FILE_SPV,null),
new ShaderModule(VkCtx,VK_SHADER_STAGE_FRAGMENT_BIT,ShaderPath,specConstants.GetSpecializationInfo())
};
}
public void Render(VulkanContext VkCtx, CommandBuffer commandBuffer, Attachment SrcAttachment){

View file

@ -8,6 +8,7 @@ import org.lwjgl.vulkan.VkDescriptorBufferInfo;
import org.lwjgl.vulkan.VkDescriptorImageInfo;
import org.lwjgl.vulkan.VkDescriptorSetAllocateInfo;
import org.lwjgl.vulkan.VkWriteDescriptorSet;
import org.tinylog.Logger;
import java.nio.LongBuffer;
import java.util.ArrayList;
@ -58,11 +59,24 @@ public class DescriptorSet {
SetImages(device, imageViews, textureSampler, BaseBinding);
}
public void SetImages(Device device, List<ImageView> imageViews, TextureSampler textureSampler, int BaseBinding){
if(textureSampler == null || textureSampler.GetVkSampler() == VK_NULL_HANDLE){
Logger.error("Null texture sampler during Set Images function");
throw new RuntimeException("yo this texture sampler ain't present");
}
try(var MemStack = MemoryStack.stackPush()){
int ImageCount = imageViews.size();
var DescriptorBuffer = VkWriteDescriptorSet.calloc(ImageCount,MemStack);
for(int i = 0; i < ImageCount; i++){
ImageView imageView = imageViews.get(i);
if(imageView == null || imageView.GetVulkanImageView() == VK_NULL_HANDLE){
Logger.error("Null Image View or Image View Handle during Set Images function");
throw new RuntimeException("yo this ImageView ain't present");
}
if(imageView.GetVulkanImage() == VK_NULL_HANDLE){
Logger.error("Null Image Handle during Set Images function");
throw new RuntimeException("yo this Image ain't present");
}
var ImageInfo = VkDescriptorImageInfo.calloc(1,MemStack)
.imageView(imageView.GetVulkanImageView())
.sampler(textureSampler.GetVkSampler());

View file

@ -0,0 +1,21 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shadows;
import org.joml.Matrix4f;
public class CascadeData {
private final Matrix4f ProjectionViewMatrix;
private float SplitDistance;
public CascadeData(){
ProjectionViewMatrix = new Matrix4f();
}
public Matrix4f GetProjectionViewMatrix(){return ProjectionViewMatrix;}
public float GetSplitDistance(){return SplitDistance;}
public void SetProjectionViewMatrix(Matrix4f ProjViewMat){
this.ProjectionViewMatrix.set(ProjViewMat);
}
public void SetSplitDistance(float splitDistance){
this.SplitDistance = splitDistance;
}
}

View file

@ -0,0 +1,19 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shadows;
import net.halbear.Terrain4J.EngineCore.Main.Scene.SceneLightingManager;
import java.util.ArrayList;
import java.util.List;
public class CascadeShadows {
private final List<CascadeData> cascadeDataList;
public CascadeShadows(){
this.cascadeDataList = new ArrayList<>();
for(int i = 0; i < SceneLightingManager.SHADOW_MAP_CASCADE_COUNT; i++){
cascadeDataList.add(new CascadeData());
}
}
public List<CascadeData> GetCascadeData(){return cascadeDataList;}
}

View file

@ -0,0 +1,22 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shadows;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_D32_SFLOAT;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R32G32_SFLOAT;
public class ShadowRenderer {
public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT;
private static final int ATTACHMENT_FORMATT = VK_FORMAT_R32G32_SFLOAT;
private static final String DESCRIPTOR_ID_MAT = "SHADOW_DESC_ID_MAT";
private static final String DESCRIPTOR_ID_PRJ = "SHADOW_DESC_ID_PRJ";
private static final String DESCRIPTOR_ID_TEXT = "SHADOW_SCN_DESC_ID_TEXT";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/shadow_frag.glsl";
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE;
private static final String SHADOW_GEOMETRY_SHADER_FILE_GLSL = "resources/EngineResources/shaders/shadow_geometry.glsl";
private static final String SHADOW_GEOMETRY_SHADER_FILE_SPV = SHADOW_GEOMETRY_SHADER_FILE_GLSL + ".spv";
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/shadow_vertex.glsl";
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
}

View file

@ -0,0 +1,144 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shadows;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
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.Vulkan.Rendering.Projection.Project3D;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import javax.swing.text.View;
import java.util.List;
public class ShadowUtils {
private static final float LAMBDA = 0.95f;
private static final Vector3f Up = new Vector3f(0.0f,1.0f,0.0f);
private static final Vector3f UpAlt = new Vector3f(0.0f,0.0f,1.0f);
private ShadowUtils(){
}
public static void UpdateCascadeShadows(CascadeShadows shadows, IScene scene){
Camera camera = scene.GetCamera();
Matrix4f ViewMatrix = camera.GetViewMatrix();
Project3D projection = scene.GetProjection();
Matrix4f ProjectionMatrix = projection.GetProjectionMatrix();
ILight[] lights = scene.GetLightingManager().GetLights();
int LightCount = lights.length;
ILight SkyLight = null;
for(int i = 0; i < LightCount; i++){
if(lights[i].IsDirectional()){
SkyLight = lights[i];
break;
}
}
if(SkyLight == null){
throw new RuntimeException("No SkyLight on scene");
}
Vector4f LightPosition = new Vector4f(SkyLight.GetPosition(),0.0f);
float[] CascadeSplits = new float[SceneLightingManager.SHADOW_MAP_CASCADE_COUNT];
float NearClip = Math.min(projection.GetNearZ(), projection.GetFarZ());
float FarClip = Math.max(projection.GetNearZ(), projection.GetFarZ());
float ClipRange = FarClip - NearClip;
float MinZ = NearClip;
float MaxZ = NearClip + ClipRange;
float Range = MaxZ - MinZ;
float Ratio = MaxZ/MinZ;
List<CascadeData> cascadeDataList = shadows.GetCascadeData();
int CascadeCount = cascadeDataList.size();
for(int i = 0; i < CascadeCount; i++){
float p = (i + 1) / (float) (SceneLightingManager.SHADOW_MAP_CASCADE_COUNT);
float Log = (float) (MinZ * Math.pow(Ratio, p));
float Uniform = MinZ + Range * p;
float d = LAMBDA * (Log - Uniform) + Uniform;
CascadeSplits[i] = (d - NearClip) / ClipRange;
}
float LastSplitDist = 0.0f;
for(int i = 0; i < CascadeCount; i++){
float SplitDist = CascadeSplits[i];
Vector3f[] FustrumCorners = new Vector3f[]{
new Vector3f(-1.0f, 1.0f, 0.0f),
new Vector3f(1.0f, 1.0f, 0.0f),
new Vector3f(1.0f, -1.0f, 0.0f),
new Vector3f(-1.0f, -1.0f, 0.0f),
new Vector3f(-1.0f, 1.0f, 1.0f),
new Vector3f(1.0f, 1.0f, 1.0f),
new Vector3f(1.0f, -1.0f, 1.0f),
new Vector3f(-1.0f, -1.0f, 1.0f)
};
var InvertedCam = (new Matrix4f(ProjectionMatrix).mul(ViewMatrix)).invert();
for(int j = 0; j < 8; j++){
Vector4f InvertedCorner = new Vector4f(FustrumCorners[j],1.0f).mul(InvertedCam);
FustrumCorners[j] = new Vector3f(InvertedCorner.x,InvertedCorner.y,InvertedCorner.z).div(InvertedCorner.w);
}
for(int j = 0; j < 4; j++){
var Distance = new Vector3f(FustrumCorners[j + 4]).sub(FustrumCorners[j]);
FustrumCorners[j + 4] = new Vector3f(FustrumCorners[j]).add(new Vector3f(Distance).mul(SplitDist));
FustrumCorners[j] = new Vector3f(FustrumCorners[j]).add(new Vector3f(Distance).mul(LastSplitDist));
}
var FustrumCenter = new Vector3f(0.0f);
for(int j = 0; j < 8; j++){
FustrumCenter.add(FustrumCorners[j]);
}
FustrumCenter.div(8);
var up = Up;
float SphereRadius = 0.0f;
for(int j = 0; j < 8; j++){
float Distance = new Vector3f(FustrumCorners[j]).sub(FustrumCenter).length();
SphereRadius = Math.max(SphereRadius,Distance);
}
SphereRadius = (float)Math.ceil(SphereRadius * 16.0f) / 16.0f;
var MaxExtents = new Vector3f(SphereRadius);
var MinExtents = new Vector3f(-SphereRadius);
var LightDirection = new Vector3f(LightPosition.x, LightPosition.y, LightPosition.z);
var ShadowCamPosition = new Vector3f(FustrumCenter).add(LightDirection.mul(MinExtents.z));
float Dot = Math.abs(new Vector3f(LightPosition.x, LightPosition.y, LightPosition.z).dot(up));
if(Dot == 1.0f){
up = UpAlt;
}
var LightViewMatrix = new Matrix4f().lookAt(ShadowCamPosition,FustrumCenter,up);
var LightOrthoMatrix = new Matrix4f().ortho(MinExtents.x,MaxExtents.x,MinExtents.y,MaxExtents.y,0.0f,MaxExtents.z - MinExtents.z,true);
int ShadowMapSize = EngineConfig.getInstance().GetShadowMapSize();
Vector4f ShadowOrigin = new Vector4f(0f,0f,0f,1f);
LightViewMatrix.transform(ShadowOrigin);
ShadowOrigin.mul(ShadowMapSize/2.0f);
Vector4f RoundedOrigin = new Vector4f(ShadowOrigin).round();
Vector4f RoundOffset = RoundedOrigin.sub(ShadowOrigin);
RoundOffset.mul(2.0f/ShadowMapSize);
RoundOffset.z = 0.0f;
RoundOffset.w = 0.0f;
LightOrthoMatrix.m30(LightOrthoMatrix.m30() + RoundOffset.x);
LightOrthoMatrix.m31(LightOrthoMatrix.m31() + RoundOffset.y);
LightOrthoMatrix.m32(LightOrthoMatrix.m32() + RoundOffset.z);
LightOrthoMatrix.m33(LightOrthoMatrix.m33() + RoundOffset.w);
CascadeData cascadeData = cascadeDataList.get(i);
cascadeData.SetSplitDistance((NearClip + SplitDist * ClipRange) * -1.0f);
cascadeData.SetProjectionViewMatrix(LightOrthoMatrix.mul(LightViewMatrix));
LastSplitDist = CascadeSplits[i];
}
}
}

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.ITexture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Texture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap;
@ -56,14 +57,14 @@ public class MaterialsCache {
boolean TransparentTexture;
Logger.debug("Material Texture Path -> [{}]",Material.TexturePath());
if(ValidTexture){
Texture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB);
ITexture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB);
if(newTexture == null) {
TransparentTexture = false;
TexturePath = "resources/EngineResources/Texture/DefaultTexture.png";
TexturePath = "resources/EngineResources/Texture/NoTexture.png";
}
else TransparentTexture = newTexture.HasTransparency();
} else{
TexturePath = "resources/EngineResources/Texture/DefaultTexture.png";
TexturePath = "resources/EngineResources/Texture/NoTexture.png";
TransparentTexture = Material.DiffuseColour().w < 1.0f;
}
VulkanMaterial newMaterial = new VulkanMaterial(Material.ID(),TransparentTexture);

View file

@ -1,18 +1,26 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorAllocator;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSet;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandPool;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.TransferBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.DeferredSceneRender;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.VkCommandBuffer;
import org.tinylog.Logger;
import java.io.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -28,6 +36,51 @@ public class ModelsCache {
ModelsMap = new HashMap<>();
}
private final java.util.Map<String, Long> SkyboxBuffers = new java.util.HashMap<>();
public String CreateSkybox(VulkanContext vulkanContext, float[] vertices, String SkyBoxID) {
long bufferSize = (long) vertices.length * Float.BYTES; // 36 * 4 bytes = 144 bytes
VulkanBuffer meshBuffer = VulkanUtils.CreateRawVertexAttrBuffer(vulkanContext, bufferSize);
long meshBuffPtr = meshBuffer.MapMemory(vulkanContext);
if (meshBuffPtr == 0 || meshBuffPtr == -1) {
throw new RuntimeException("CRITICAL ERROR: meshBuffer.MapMemory() returned an invalid native address pointer: " + meshBuffPtr
+ ". Check your underlying vkMapMemory/vmaMapMemory configurations.");
}
try {
java.nio.FloatBuffer floatBuffer = org.lwjgl.system.MemoryUtil.memFloatBuffer(meshBuffPtr, vertices.length);
floatBuffer.put(vertices);
floatBuffer.flip();
} catch (Exception e) {
throw new RuntimeException("Failed during FloatBuffer array memory payload copy wrapper pass", e);
} finally {
meshBuffer.UnMapMemory(vulkanContext);
}
this.SkyboxBuffers.put(SkyBoxID, meshBuffer.GetBuffer());
return SkyBoxID;
}
public void bindAndDrawCubeMesh(VkCommandBuffer commandHandle, String skyboxMeshBufferId) {
Long vkBufferHandle = SkyboxBuffers.get(skyboxMeshBufferId);
if (vkBufferHandle == null) {
throw new RuntimeException("Skybox mesh buffer ID [" + skyboxMeshBufferId + "] not loaded in ModelsCache!");
}
try (MemoryStack MemStack = MemoryStack.stackPush()) {
LongBuffer pBuffers = MemStack.longs(vkBufferHandle);
LongBuffer pOffsets = MemStack.longs(0);
vkCmdBindVertexBuffers(commandHandle, 0, pBuffers, pOffsets);
vkCmdDraw(commandHandle, 36, 1, 0, 0);
}
}
public void loadModels(VulkanContext VkCtx, List<ModelData> Models, CommandPool commandPool, Queue queue){
try {
List<VulkanBuffer> StagingBufferList = new ArrayList<>();

View file

@ -3,15 +3,11 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DeferredRendering.MultiRenderTargetAttachments;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Texture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.*;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PushConstantsRange;
@ -42,12 +38,16 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
private static final String DESCRIPTOR_ID_PRJ = "SCN_DESC_ID_PRJ";
private static final String DESCRIPTOR_ID_TEXT = "SCN_DESC_ID_TEXT";
private static final String DESCRIPTOR_ID_VIEW = "SCN_DESC_ID_VIEW";
private static final String DESCRIPTOR_ID_SKYBOX_VIEW = "SCN_DESC_ID_SKYBOX_VIEW";
public static final String DESCRIPTOR_ID_SKYBOX_CUBEMAP = "SCN_DESC_ID_SKYBOX_CUBEMAP";
private static final int PUSH_CONSTANTS_SIZE = VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.INT_SIZE;
private final VulkanBuffer BufferProjectionMatrix;
private final DescriptorSetLayout descriptorLayoutFragStorage;
private final DescriptorSetLayout descriptorLayoutTexture;
private final DescriptorSetLayout descriptorLayoutVertexUniform;
private DescriptorSet SkyboxDescriptorSet;
private final TextureSampler textureSampler;
public static String SkyBoxID = "SKYBOX_TEXTURE";
public static final int COLOUR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT;
@ -63,6 +63,11 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
public static long CYCLES = 0;
private static boolean DualPassRendering = false;
private static final String SKYBOX_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/skybox_fragment.glsl";
private static final String SKYBOX_FRAGMENT_SHADER_FILE_SPV = SKYBOX_FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String SKYBOX_VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/skybox_vertex.glsl";
private static final String SKYBOX_VERTEX_SHADER_FILE_SPV = SKYBOX_VERTEX_SHADER_FILE_GLSL + ".spv";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment_deferred.glsl";
private static final String FRAGMENT_TRANSLUCENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl";
private static final String FRAGMENT_OPAQUE_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl";
@ -75,12 +80,17 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
private Pipeline VkPipeline;
private Pipeline VkPipelineOpaque;
private Pipeline VkPipelineTranslucent;
private float R = 0.00f;
private float G = 0.05f;
private float B = 0.15f;
private float R = 0.4f;
private float G = 0.75f;
private float B = 1.0f;
private Matrix4f ProjectionMatrix;
private MultiRenderTargetAttachments MRTAttachments;
private DescriptorSetLayout descriptorLayoutSkyboxTexture;
private VulkanBuffer[] BufferSkyboxViewMatrices;
private Pipeline VkSkyboxPipeline;
private long skyboxMeshBufferId;
public static long GetGPUTimeNS(){
long time = 0;
if(CYCLES > 0){
@ -93,7 +103,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
public DeferredSceneRender(VulkanContext vulkanContext, EngineInstance engineInstance){
ClearValueColour = VkClearValue.calloc().color(
c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 0.5f));
c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f));
ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f));
MRTAttachments = new MultiRenderTargetAttachments(vulkanContext);
AttachmentInfoColour = CreateColourAttachmentInfo(MRTAttachments, ClearValueColour);
@ -120,6 +130,14 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
descriptorLayoutTexture = new DescriptorSetLayout(vulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, TextureCache.MAX_TEXTURES, VK_SHADER_STAGE_FRAGMENT_BIT));
descriptorLayoutSkyboxTexture = new DescriptorSetLayout(vulkanContext,
new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, 1, VK_SHADER_STAGE_FRAGMENT_BIT));
BufferSkyboxViewMatrices = VulkanUtils.CreateHostVisibleBuffers(vulkanContext, VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.MAX_IN_FLIGHT,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_SKYBOX_VIEW, descriptorLayoutVertexUniform);
CreatePipelines(vulkanContext);
Logger.debug("Deferred Renderer Pipeline -> [{}]",VkPipeline.GetVulkanPipeline());
@ -134,13 +152,24 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
};
ShaderModule[] shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,0);
VkPipeline = CreatePipeline(vulkanContext, shaderModules, layouts, true, false,EngineConfig.getInstance().AlphaToCoverage());
VkPipeline = CreatePipeline(vulkanContext, shaderModules, layouts, true,true, false,EngineConfig.getInstance().AlphaToCoverage(),0);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,1);
VkPipelineOpaque = CreatePipeline(vulkanContext, shaderModules, layouts, true, true,EngineConfig.getInstance().AlphaToCoverage());
VkPipelineOpaque = CreatePipeline(vulkanContext, shaderModules, layouts, true,false, true,EngineConfig.getInstance().AlphaToCoverage(),0);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
shaderModules = DeferredSceneRender.CreateShaderModules(vulkanContext,2);
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,EngineConfig.getInstance().AlphaToCoverage());
VkPipelineTranslucent = CreatePipeline(vulkanContext, shaderModules, layouts, false, true,true,EngineConfig.getInstance().AlphaToCoverage(),2);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
DescriptorSetLayout[] skyboxLayouts = new DescriptorSetLayout[]{
descriptorLayoutVertexUniform,
descriptorLayoutVertexUniform,
descriptorLayoutSkyboxTexture
};
shaderModules = DeferredSceneRender.CreateSkyboxShaderModules(vulkanContext);
VkSkyboxPipeline = CreateSkyboxPipeline(vulkanContext, shaderModules, skyboxLayouts, false, false, false,false);
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
}
@ -181,6 +210,17 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
.clearValue(clearValue);
}
private static ShaderModule[] CreateSkyboxShaderModules(VulkanContext VkCtx){
if(EngineConfig.getInstance().RecompileShaders()){
ShaderCompiler.CompileGLSLShaderOnChange(SKYBOX_VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
ShaderCompiler.CompileGLSLShaderOnChange( SKYBOX_FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader);
}
return new ShaderModule[]{
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, SKYBOX_VERTEX_SHADER_FILE_SPV,null),
new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, SKYBOX_FRAGMENT_SHADER_FILE_SPV,null)
};
}
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, int Translucent){
if(EngineConfig.getInstance().RecompileShaders()){
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
@ -192,7 +232,47 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
};
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean AlphaToCoverage){
private static Pipeline CreateSkyboxPipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage){
int[] skyboxFormats = new int[] {
MultiRenderTargetAttachments.POSITION_FORMAT,
MultiRenderTargetAttachments.ALBEDO_FORMAT,
MultiRenderTargetAttachments.NORMAL_FORMAT,
MultiRenderTargetAttachments.PBR_FORMAT
};
try (MemoryStack MemStack = MemoryStack.stackPush()) {
VkVertexInputBindingDescription.Buffer bindingDescription = VkVertexInputBindingDescription.calloc(1, MemStack)
.binding(0)
.stride(3 * Float.BYTES)
.inputRate(VK_VERTEX_INPUT_RATE_VERTEX);
VkVertexInputAttributeDescription.Buffer attributeDescription = VkVertexInputAttributeDescription.calloc(1, MemStack)
.binding(0)
.location(0)
.format(VK_FORMAT_R32G32B32_SFLOAT)
.offset(0);
VkPipelineVertexInputStateCreateInfo skyboxVertexInputState = VkPipelineVertexInputStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO)
.pVertexBindingDescriptions(bindingDescription)
.pVertexAttributeDescriptions(attributeDescription);
var BuildInfo = new PipelineBuildInfo(ShaderModules, skyboxVertexInputState, skyboxFormats)
.SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT)
.SetDepthWrite(false)
.SetDepthTest(true)
.SetPushConstantRanges(new PushConstantsRange[0])
.SetDescriptorSetLayouts(DescriptorSetLayouts)
.BlendingIsUsed(true)
.SetDualPass(false)
.SetAlphaToCoverage(false);
var pipeline = new DefaultPipeline(VkCtx, BuildInfo);
Logger.debug("Skybox Pipeline Created Successfully");
return pipeline;
}
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage, int BlendingMethod){
var vertexBufferStructure = new VertexBufferStructure();
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{
MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT})
@ -204,10 +284,12 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT,VulkanUtils.MATRIX4X4_SIZE,VulkanUtils.INT_SIZE)
})
.SetDescriptorSetLayouts(DescriptorSetLayouts)
.BlendingIsUsed(DualRender ? !DepthWrite : true)
.SetBlendingMethod(BlendingMethod)
.BlendingIsUsed(Blending)
.SetDualPass(DualRender)
.SetAlphaToCoverage(AlphaToCoverage);
var pipeline = new DefaultPipeline(VkCtx, BuildInfo);
Logger.debug("Pipeline Created");
vertexBufferStructure.cleanup();
return pipeline;
}
@ -255,6 +337,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
vkCmdSetScissor(CommandHandle, 0, Scissor);
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferViewMatrices[CurrentFrame],engineInstance.scene().GetCamera().GetViewMatrix(), 0); // here
DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator();
LongBuffer DescriptorSets = MemStack.mallocLong(4)
.put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet())
@ -264,14 +347,38 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, DualPassRendering ? VkPipelineOpaque.GetVulkanPipelineLayout() : VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, false);
Matrix4f skyboxViewMatrix = new Matrix4f().identity();
skyboxViewMatrix.set(engineInstance.scene().GetCamera().GetViewMatrix());
skyboxViewMatrix.m30(0.0f);
skyboxViewMatrix.m31(0.0f);
skyboxViewMatrix.m32(0.0f);
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferSkyboxViewMatrices[CurrentFrame], skyboxViewMatrix, 0);
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkSkyboxPipeline.GetVulkanPipeline());
LongBuffer skyboxDescriptorSets = MemStack.mallocLong(3)
.put(0, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet())
.put(1, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SKYBOX_VIEW, CurrentFrame).GetVkDescriptorSet())
.put(2, descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SKYBOX_CUBEMAP).GetVkDescriptorSet());
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkSkyboxPipeline.GetVulkanPipelineLayout(), 0, skyboxDescriptorSets, null);
modelsCache.bindAndDrawCubeMesh(CommandHandle, SkyBoxID);
VulkanUtils.CopyMatrixToBuffer(vulkanContext, BufferViewMatrices[CurrentFrame],engineInstance.scene().GetCamera().GetViewMatrix(), 0); // here
if(DualPassRendering) {
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineTranslucent.GetVulkanPipeline());
vkCmdSetViewport(CommandHandle, 0, Viewport);
vkCmdSetScissor(CommandHandle, 0, Scissor);
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineTranslucent.GetVulkanPipelineLayout(), 0, DescriptorSets, null);
//vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineOpaque.GetVulkanPipeline());
//vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipelineOpaque.GetVulkanPipelineLayout(), 0, DescriptorSets, null);
} else{
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipeline());
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
}
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true);
vkCmdEndRendering(CommandHandle);
GPUTIME += System.nanoTime() - InitialTime;
@ -346,9 +453,21 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
var buffer = materialsCache.GetMaterialsBuffer();
descSet.SetBuffer(device, buffer, buffer.GetRequestedSize(), layoutInfo.Binding(), layoutInfo.DescriptorType());
List<ImageView> imageViews = textureCache.GetTextureList().stream().map(Texture::GetImageView).toList();
List<ImageView> imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList();
descSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device, DESCRIPTOR_ID_TEXT, descriptorLayoutTexture);
descSet.SetImageArray(device, imageViews, textureSampler, 0);
DescriptorSet descSetSkyBox = descAllocator.AddDescriptorSet(device, DESCRIPTOR_ID_SKYBOX_CUBEMAP, descriptorLayoutSkyboxTexture);
ITexture SkyBoxTexture = textureCache.GetTexture(SkyBoxID);
if (SkyBoxTexture == null) {
throw new RuntimeException("Skybox texture map was not properly cached before descriptor binding phase!");
}
descSetSkyBox.SetImage(
device,
SkyBoxTexture.GetImageView(),
textureSampler,
descriptorLayoutSkyboxTexture.GetLayoutInfo().Binding()
);
}
private static VkRenderingInfo CreateRenderInfo(VulkanContext VkCtx, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo, VkRenderingAttachmentInfo DepthAttachmentInfo){
@ -368,6 +487,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
public void cleanup(VulkanContext VkCtx){
VkPipeline.CleanUp(VkCtx);
// VkSkyboxPipeline.CleanUp(VkCtx);
VkPipelineOpaque.CleanUp(VkCtx);
VkPipelineTranslucent.CleanUp(VkCtx);
Arrays.asList(BufferViewMatrices).forEach(b -> b.cleanup(VkCtx));

View file

@ -9,10 +9,7 @@ import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.DeferredRendering.MultiRenderTargetAttachments;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Image;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Texture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.*;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PushConstantsRange;
@ -60,7 +57,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
private final DescriptorSetLayout descriptorLayoutVertexUniform;
private final TextureSampler textureSampler;
private static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
private static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT_S8_UINT;
private static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT;
private final VkClearValue ClearValueDepth;
private final ByteBuffer PushConstBuffer;
private Attachment AttachmentDepth;
@ -356,7 +353,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
DescriptorSetLayout.LayoutInformation LayoutInfo = descriptorLayoutFragStorage.GetLayoutInfo();
var Buffer = materialsCache.GetMaterialsBuffer();
descriptorSet.SetBuffer(device,Buffer,Buffer.GetRequestedSize(),LayoutInfo.Binding(),LayoutInfo.DescriptorType());
List<ImageView> imageViews = textureCache.GetTextureList().stream().map(Texture::GetImageView).toList();
List<ImageView> imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList();
descriptorSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device,DESCRIPTOR_ID_TEXT,descriptorLayoutTexture);
descriptorSet.SetImageArray(device,imageViews,textureSampler,0);
}

View file

@ -17,6 +17,7 @@ import java.nio.LongBuffer;
import java.util.Arrays;
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.KHRSurface.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
import static org.lwjgl.vulkan.VK13.*;
public class SwapChain {
@ -43,7 +44,7 @@ public class SwapChain {
.imageArrayLayers(1)
.imageUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
.preTransform(SurfaceCapabilities.currentTransform())
.compositeAlpha(KHRSurface.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
.compositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)
.clipped(true);
if (VSYNC){
VulkanSwapChainCreateInfo.presentMode(KHRSurface.VK_PRESENT_MODE_FIFO_KHR);

View file

@ -87,7 +87,7 @@ public class SwapChainRender {
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){
var VertexBufferStruct = new EmptyVertexBufferStruct();
var BuildInfo = new PipelineBuildInfo(shaderModules, VertexBufferStruct.GetVertexInput(),new int[]{VkCtx.GetSurface().GetSurfaceFormat().ImageFormat()}).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true);
var BuildInfo = new PipelineBuildInfo(shaderModules, VertexBufferStruct.GetVertexInput(),new int[]{VkCtx.GetSurface().GetSurfaceFormat().ImageFormat()}).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(false);
var pipeline = new DefaultPipeline(VkCtx,BuildInfo);
VertexBufferStruct.CleanUp();
return pipeline;
@ -167,9 +167,16 @@ public class SwapChainRender {
vkCmdEndRendering(CommandHandle);
VulkanUtils.ImageBarrier(MemStack,CommandHandle,SwapChainImage,VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT, VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,
VK_PIPELINE_STAGE_2_NONE, VK_IMAGE_ASPECT_COLOR_BIT);
VulkanUtils.ImageBarrier(MemStack,
CommandHandle,
SwapChainImage,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, // Source Stage
VK_PIPELINE_STAGE_2_NONE, // Destination Stage (Replacing BOTTOM_OF_PIPE)
VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, // Source Access Mask
VK_ACCESS_2_NONE, // Destination Access Mask (Replacing Stage_2_None)
VK_IMAGE_ASPECT_COLOR_BIT);
}
}

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Util;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorAllocator;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSet;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout;
@ -9,6 +10,7 @@ import org.joml.Matrix4f;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@ -41,7 +43,16 @@ public class VulkanUtils {
matrix.get(Offset, matrixBuffer);
VkBuffer.UnMapMemory(VkCtx);
}
public static VulkanBuffer CreateRawVertexAttrBuffer(VulkanContext VkCtx, long BufferSize) {
return new VulkanBuffer(
VkCtx,
BufferSize,
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
);
}
public static VulkanBuffer[] CreateHostVisibleBuffers(VulkanContext VkCtx, long BufferSize, int BufferCount, int Usage, String ID, DescriptorSetLayout layout){
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
Device device = VkCtx.GetDevice();
@ -142,7 +153,12 @@ public class VulkanUtils {
case VK_ERROR_UNKNOWN -> "VK_ERROR_UNKNOWN";
default -> "Not mapped";
};
throw new RuntimeException(ErrorMessage + ": " + ErrorCode + " [" + Error + "]");
Logger.error("FATAL VULKAN ERROR -> " + ErrorMessage + ": " + ErrorCode + " [" + Error + "]\nAttempting To Restart Vulkan...");
if(PrimaryRuntime.GetRenderThread() != null)PrimaryRuntime.GetRenderThread().RestartCrashedRenderer();
else{
PrimaryRuntime.GetEngineInstance().window().setShouldClose();
PrimaryRuntime.CloseRuntime();
}
}
}

View file

@ -27,6 +27,8 @@ compatibility_mode=false
#0 = Forward rendering
#1 = Deferred rendering
Renderer=1
ShadowMapSize=16
MaxAllowedVulkanCrashes=10
AlphaToCoverage=false
DualPassRendering=false
#AA settings
@ -43,7 +45,7 @@ vkValidated=true
vsync=false
#Swap Chain Images
RequestedImages=3
DefaultTexturePath=resources/EngineResources/Texture/DefaultTexture.png
DefaultTexturePath=resources/EngineResources/Texture/NoTexture.png
#This is the name of the GPU you want the engine to use
PhysicalDeviceName=