post processing, FXAA and MSAA 2x-8x

This commit is contained in:
Halbear 2026-06-11 16:16:41 +01:00
parent fa266ee48d
commit 8ce30cae83
46 changed files with 1749 additions and 350 deletions

View file

@ -0,0 +1,55 @@
#version 450
layout(constant_id = 0) const int USE_AA = 0;
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;
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2DMS inputTexture;
layout(set = 1, binding = 0) uniform ScreenSize{
vec2 size;
} screenSize;
vec4 gamma(vec4 color){
return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
}
vec4 msaa(int sampleCount, sampler2DMS textureIn,vec2 TextCoord){
ivec2 pixelCoords = ivec2(TextCoord * textureSize(textureIn));
vec4 colorSum = vec4(0.0);
for(int i = 0; i < sampleCount; ++i) {
vec4 sampleColor = texelFetch(textureIn, pixelCoords, i);
sampleColor.rgb = sampleColor.rgb / (sampleColor.rgb + vec3(1.0));
colorSum += sampleColor;
}
return colorSum / float(sampleCount);
}
void main(){
ivec2 pixelCoords = ivec2(inTextCoord * textureSize(inputTexture));
if(USE_AA == 0){
outFragColor = texelFetch(inputTexture,pixelCoords,0);
}
if(USE_AA == 1){
outFragColor = texelFetch(inputTexture,pixelCoords,0);
}
if(USE_AA == 2){
outFragColor = msaa(2,inputTexture,inTextCoord);
}
if(USE_AA == 3){
outFragColor = msaa(4,inputTexture,inTextCoord);
}
if(USE_AA == 4){
outFragColor = msaa(8,inputTexture,inTextCoord);
}
outFragColor = gamma(outFragColor);
}

View file

@ -0,0 +1,91 @@
#version 450
layout(constant_id = 0) const int USE_AA = 0;
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;
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2D inputTexture;
layout(set = 1, binding = 0) uniform ScreenSize{
vec2 size;
} screenSize;
vec4 gamma(vec4 color){
return color = vec4(pow(color.rgb,vec3(GAMMA_CONST)),color.a);
}
// Sourced from: https://mini.gmshaders.com/p/gm-shaders-mini-fxaa
vec4 fxaa(sampler2D tex, vec2 uv) {
vec2 u_texel = 1.0 / screenSize.size;
//Sample center and 4 corners
vec3 rgbCC = texture(tex, uv).rgb;
vec3 rgb00 = texture(tex, uv+vec2(-0.5,-0.5)*u_texel).rgb;
vec3 rgb10 = texture(tex, uv+vec2(+0.5,-0.5)*u_texel).rgb;
vec3 rgb01 = texture(tex, uv+vec2(-0.5,+0.5)*u_texel).rgb;
vec3 rgb11 = texture(tex, uv+vec2(+0.5,+0.5)*u_texel).rgb;
//Luma coefficients
const vec3 luma = vec3(0.299, 0.587, 0.114);
//Get luma from the 5 samples
float lumaCC = dot(rgbCC, luma);
float luma00 = dot(rgb00, luma);
float luma10 = dot(rgb10, luma);
float luma01 = dot(rgb01, luma);
float luma11 = dot(rgb11, luma);
//Compute gradient from luma values
vec2 dir = vec2((luma01 + luma11) - (luma00 + luma10), (luma00 + luma01) - (luma10 + luma11));
//Diminish dir length based on total luma
float dirReduce = max((luma00 + luma10 + luma01 + luma11) * REDUCE_MUL, REDUCE_MIN);
//Divide dir by the distance to nearest edge plus dirReduce
float rcpDir = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
//Multiply by reciprocal and limit to pixel span
dir = clamp(dir * rcpDir, -SPAN_MAX, SPAN_MAX) * u_texel.xy;
//Average middle texels along dir line
vec4 A = 0.5 * (
texture(tex, uv - dir * (1.0/6.0)) +
texture(tex, uv + dir * (1.0/6.0)));
//Average with outer texels along dir line
vec4 B = A * 0.5 + 0.25 * (
texture(tex, uv - dir * (0.5)) +
texture(tex, uv + dir * (0.5)));
//Get lowest and highest luma values
float lumaMin = min(lumaCC, min(min(luma00, luma10), min(luma01, luma11)));
float lumaMax = max(lumaCC, max(max(luma00, luma10), max(luma01, luma11)));
//Get average luma
float lumaB = dot(B.rgb, luma);
//If the average is outside the luma range, using the middle average
return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? A : B;
}
void main(){
if(USE_AA == 1){
outFragColor = fxaa(inputTexture, inTextCoord);
outFragColor = gamma(outFragColor);
return;
}
if(USE_AA == 2){
}
if(USE_AA == 3){
}
if(USE_AA == 4){
}
outFragColor = gamma(texture(inputTexture,inTextCoord));
}

View file

@ -0,0 +1,9 @@
#version 450
layout(location = 0 ) out vec2 outTextCoord;
void main()
{
outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f);
}

View file

@ -1,6 +1,6 @@
#version 450 #version 450
const int MAX_TEXTURES = 100; const int MAX_TEXTURES = 500;
layout(location = 0) in vec2 inTextCoords; layout(location = 0) in vec2 inTextCoords;
layout(location = 0) out vec4 outFragColor; layout(location = 0) out vec4 outFragColor;
@ -26,7 +26,9 @@ void main()
{ {
Material material = matUniform.materials[push_constants.materialIdx]; Material material = matUniform.materials[push_constants.materialIdx];
if(material.hasTexture == 1){ if(material.hasTexture == 1){
outFragColor = texture(textSampler[material.textureIdx],inTextCoords); vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords);
if(texColor.a < 0.1){discard;}
outFragColor = texColor;
} else{ } else{
outFragColor = material.diffuseColor; outFragColor = material.diffuseColor;
} }

View file

@ -0,0 +1,10 @@
#version 450
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2D albedoSampler;
void main() {
vec3 albedo = texture(albedoSampler, inTextCoord).rgb;
outFragColor = vec4(albedo,1.0);
}

View file

@ -0,0 +1,8 @@
#version 450
layout(location = 0) out vec2 outTextCoord;
void main() {
outTextCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(outTextCoord.x * 2.0f - 1.0f, outTextCoord.y * -2.0f + 1.0f,0.0f,1.0f);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Before After
Before After

View file

@ -4,17 +4,17 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.InitData; import net.halbear.Terrain4J.EngineCore.Logic.InitData;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing.PostProcess;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialsCache; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.*;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelsCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; 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.CommandPool;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Fence; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Fence;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Semaphore; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Semaphore;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRender; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRender;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SceneRenderer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChainRender;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.VkCommandBufferSubmitInfo; import org.lwjgl.vulkan.VkCommandBufferSubmitInfo;
@ -22,11 +22,11 @@ import org.lwjgl.vulkan.VkExtent2D;
import org.lwjgl.vulkan.VkSemaphoreSubmitInfo; import org.lwjgl.vulkan.VkSemaphoreSubmitInfo;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.lwjgl.vulkan.VK13.VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT; import static org.lwjgl.vulkan.VK13.*;
import static org.lwjgl.vulkan.VK13.VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
public class Render { public class Render {
@ -39,14 +39,22 @@ public class Render {
private final Semaphore[] PresentCompleteSemaphores; private final Semaphore[] PresentCompleteSemaphores;
private final Queue.PresentQueue PresentQueue; private final Queue.PresentQueue PresentQueue;
private final Semaphore[] RenderCompleteSemaphores; private final Semaphore[] RenderCompleteSemaphores;
private final SceneRender sceneRender; private final SceneRenderer sceneRender;
private final PostProcess PostProcessor;
private final SwapChainRender swapChainRender;
private int CurrentFrame; private int CurrentFrame;
private final VulkanContext RendererContext; private final VulkanContext RendererContext;
private boolean Resize = false; private boolean Resize = false;
private List<MaterialData> Materials = new ArrayList<>();
private List<ModelData> Models = new ArrayList<>();
private List<CompatibleVoxelMesh.VoxelModelData> VoxelModels = new ArrayList<>();
private final MaterialsCache materialsCache; private final MaterialsCache materialsCache;
private TextureCache textureCache; private TextureCache textureCache;
public TextureCache GetTextureCache(){return textureCache;}
public MaterialsCache GetMaterialsCache(){return materialsCache;}
public Render(EngineInstance engineInstance) { public Render(EngineInstance engineInstance) {
RendererContext = new VulkanContext(engineInstance.window()); RendererContext = new VulkanContext(engineInstance.window());
CurrentFrame = 0; CurrentFrame = 0;
@ -68,6 +76,8 @@ public class Render {
RenderCompleteSemaphores[i] = new Semaphore(RendererContext); RenderCompleteSemaphores[i] = new Semaphore(RendererContext);
} }
sceneRender = new SceneRender(RendererContext); sceneRender = new SceneRender(RendererContext);
PostProcessor = new PostProcess(RendererContext,sceneRender.GetAttachmentColour());
swapChainRender = new SwapChainRender(RendererContext,PostProcessor.GetAttachment());
textureCache = new TextureCache(); textureCache = new TextureCache();
materialsCache = new MaterialsCache(); materialsCache = new MaterialsCache();
modelsCache = new ModelsCache(); modelsCache = new ModelsCache();
@ -76,19 +86,27 @@ public class Render {
public void Initialise(InitData initData){ public void Initialise(InitData initData){
List<MaterialData> Materials = initData.Materials(); Materials.addAll(initData.Materials());
Logger.debug("Loading {} Materials", Materials.size()); Logger.debug("Loading {} Materials", Materials.size());
//materialsCache.CleanUp(RendererContext);
materialsCache.LoadMaterials(RendererContext, Materials,textureCache, CommandPools[0], GraphicsQueue); materialsCache.LoadMaterials(RendererContext, Materials,textureCache, CommandPools[0], GraphicsQueue);
Logger.debug("Loaded {} Materials", Materials.size()); Logger.debug("Loaded {} Materials", Materials.size());
Logger.debug("Transitioning Textures"); Logger.debug("Transitioning Textures");
//textureCache.CleanUp(RendererContext);
textureCache.TransitionTexts(RendererContext, CommandPools[0], GraphicsQueue); textureCache.TransitionTexts(RendererContext, CommandPools[0], GraphicsQueue);
Logger.debug("Transitioned Textures"); Logger.debug("Transitioned Textures");
List<ModelData> Models = initData.Models(); Models.addAll(initData.Models());
Logger.debug("Loading {} models", Models.size()); Logger.debug("Loading {} models", Models.size());
//modelsCache.CleanUp(RendererContext);
modelsCache.loadModels(RendererContext, Models, CommandPools[0], GraphicsQueue); modelsCache.loadModels(RendererContext, Models, CommandPools[0], GraphicsQueue);
Logger.debug("Loaded {} models", Models.size()); Logger.debug("Loaded {} models", Models.size());
VoxelModels.addAll(initData.voxelModels());
Logger.debug("Loading {} Voxel models", VoxelModels.size());
modelsCache.loadVoxelModels(RendererContext, VoxelModels, CommandPools[0], GraphicsQueue);
Logger.debug("Loaded {} Voxel models", VoxelModels.size());
sceneRender.LoadMaterials(RendererContext,materialsCache,textureCache); sceneRender.LoadMaterials(RendererContext,materialsCache,textureCache);
} }
@ -105,6 +123,8 @@ public class Render {
RendererContext.GetDevice().waitIdle(); RendererContext.GetDevice().waitIdle();
Logger.debug("Waiting Vulkan Context"); Logger.debug("Waiting Vulkan Context");
sceneRender.cleanup(RendererContext); sceneRender.cleanup(RendererContext);
PostProcessor.CleanUp(RendererContext);
swapChainRender.CleanUp(RendererContext);
Logger.debug("Dynamic Renderer Cleaned up"); Logger.debug("Dynamic Renderer Cleaned up");
Arrays.asList(RenderCompleteSemaphores).forEach(i->i.cleanup(RendererContext)); Arrays.asList(RenderCompleteSemaphores).forEach(i->i.cleanup(RendererContext));
Logger.debug("Render Semaphores cleaned up"); Logger.debug("Render Semaphores cleaned up");
@ -128,12 +148,18 @@ public class Render {
var CommandPool = CommandPools[CurrentFrame]; var CommandPool = CommandPools[CurrentFrame];
var CommandBuffer = CommandBuffers[CurrentFrame]; var CommandBuffer = CommandBuffers[CurrentFrame];
RecordingStart(CommandPool, CommandBuffer); RecordingStart(CommandPool, CommandBuffer);
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame);
PostProcessor.Render(RendererContext,CommandBuffer,sceneRender.GetAttachmentColour());
int ImageIndex;// = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame]); int ImageIndex;// = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame]);
if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame])) < 0){ if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame])) < 0){
resize(engineInstance); resize(engineInstance);
return; return;
} }
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,ImageIndex,CurrentFrame);
swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex);
RecordingStop(CommandBuffer); RecordingStop(CommandBuffer);
Submit(CommandBuffer, CurrentFrame, ImageIndex); Submit(CommandBuffer, CurrentFrame, ImageIndex);
Resize = swapChain.PresentImage(PresentQueue, RenderCompleteSemaphores[ImageIndex],ImageIndex); Resize = swapChain.PresentImage(PresentQueue, RenderCompleteSemaphores[ImageIndex],ImageIndex);
@ -161,6 +187,8 @@ public class Render {
VkExtent2D extend = RendererContext.GetSwapChain().GetSwapChainExtent(); VkExtent2D extend = RendererContext.GetSwapChain().GetSwapChainExtent();
engineInstance.scene().GetProjection().Resize(extend.width(),extend.height()); engineInstance.scene().GetProjection().Resize(extend.width(),extend.height());
sceneRender.Resize(engineInstance,RendererContext); sceneRender.Resize(engineInstance,RendererContext);
PostProcessor.Resize(RendererContext,sceneRender.GetAttachmentColour());
swapChainRender.Resize(RendererContext,PostProcessor.GetAttachment());
} }
private void ResetFence(int currentFrame){ private void ResetFence(int currentFrame){

View file

@ -30,6 +30,7 @@ public class MouseListener {
middleButtonPressed = button == GLFW_MOUSE_BUTTON_3 && action == GLFW_PRESS; middleButtonPressed = button == GLFW_MOUSE_BUTTON_3 && action == GLFW_PRESS;
}); });
} }
public boolean IsWindowFocused(){return FocusWindow;}
public Vector2f getCurrentPos() { public Vector2f getCurrentPos() {
return currentPos; return currentPos;
} }

View file

@ -8,6 +8,8 @@ import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Properties; import java.util.Properties;
import static org.lwjgl.vulkan.VK10.*;
public class EngineConfig { public class EngineConfig {
public static final double DegToRad = Math.PI/180.0; public static final double DegToRad = Math.PI/180.0;
public static final double RadToDeg = 180.0/Math.PI; public static final double RadToDeg = 180.0/Math.PI;
@ -51,6 +53,8 @@ public class EngineConfig {
private float zNearPlane; private float zNearPlane;
private boolean GPU_SUPPORTS_LOGGING = true; private boolean GPU_SUPPORTS_LOGGING = true;
private int MaxDescriptors = 1000; private int MaxDescriptors = 1000;
private int AAValue = 1;
private AntiAliasType AAMode = AntiAliasType.FXAA;
public void GPU_Does_Not_Support_Logging(){ public void GPU_Does_Not_Support_Logging(){
GPU_SUPPORTS_LOGGING = false; GPU_SUPPORTS_LOGGING = false;
@ -58,6 +62,32 @@ public class EngineConfig {
public boolean doesGPUSupportLogging(){return GPU_SUPPORTS_LOGGING;} public boolean doesGPUSupportLogging(){return GPU_SUPPORTS_LOGGING;}
public String GetDefaultTexturePath(){return DefaultTexturePath;} public String GetDefaultTexturePath(){return DefaultTexturePath;}
public int GetMaxDescriptors(){return MaxDescriptors;} public int GetMaxDescriptors(){return MaxDescriptors;}
public int RenderAA(){return AAValue;}
public enum AntiAliasType{
NONE,
FXAA,
MSAAx2,
MSAAx4,
MSAAx8
}
public int GetRenderSampleCount(){
switch(AAMode){
case MSAAx2:
return VK_SAMPLE_COUNT_2_BIT;
case MSAAx4:
return VK_SAMPLE_COUNT_4_BIT;
case MSAAx8:
return VK_SAMPLE_COUNT_8_BIT;
case FXAA:
return VK_SAMPLE_COUNT_1_BIT;
case NONE:
return VK_SAMPLE_COUNT_1_BIT;
default:
return VK_SAMPLE_COUNT_1_BIT;
}
}
private EngineConfig() { private EngineConfig() {
var EngineConfigVar = new Properties(); var EngineConfigVar = new Properties();
@ -120,6 +150,25 @@ public class EngineConfig {
FOV = (float)(DegToRad * Float.parseFloat(EngineConfigVar.getOrDefault("field_of_view", 60.0f).toString())); FOV = (float)(DegToRad * Float.parseFloat(EngineConfigVar.getOrDefault("field_of_view", 60.0f).toString()));
zNearPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_near_plane", 1.0f).toString())); zNearPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_near_plane", 1.0f).toString()));
zFarPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_far_plane", 100.0f).toString())); zFarPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_far_plane", 100.0f).toString()));
AAValue = (Integer.parseInt(EngineConfigVar.getOrDefault("anti_alias_mode", 1).toString()));
switch(AAValue){
case 0:
AAMode = AntiAliasType.NONE;
break;
case 2:
AAMode = AntiAliasType.MSAAx2;
break;
case 3:
AAMode = AntiAliasType.MSAAx4;
break;
case 4:
AAMode = AntiAliasType.MSAAx8;
break;
case 1:
default:
AAMode = AntiAliasType.FXAA;
break;
}
DefaultTexturePath = EngineConfigVar.getOrDefault("DefaultTexturePath","/EngineResources/Texture/DefaultTexture.png").toString(); DefaultTexturePath = EngineConfigVar.getOrDefault("DefaultTexturePath","/EngineResources/Texture/DefaultTexture.png").toString();
Logger.debug("\n\nsuccessfully loaded configuration: \n{}\n\n",EngineConfigVar.toString()); Logger.debug("\n\nsuccessfully loaded configuration: \n{}\n\n",EngineConfigVar.toString());
} }
@ -149,6 +198,7 @@ public class EngineConfig {
EngineConfigVar.setProperty("z_far_plane","100"); EngineConfigVar.setProperty("z_far_plane","100");
EngineConfigVar.setProperty("DefaultTexturePath",DefaultTexturePath); EngineConfigVar.setProperty("DefaultTexturePath",DefaultTexturePath);
EngineConfigVar.setProperty("MaxDescriptors","1000"); EngineConfigVar.setProperty("MaxDescriptors","1000");
EngineConfigVar.setProperty("anti_alias_mode","1");
EngineConfigVar.store(new FileWriter(path.toAbsolutePath().toString() + "/" + FILENAME), "created new properties file"); EngineConfigVar.store(new FileWriter(path.toAbsolutePath().toString() + "/" + FILENAME), "created new properties file");
Logger.debug("Wrote New Config File [{}]", ConfigFile.getAbsolutePath()); Logger.debug("Wrote New Config File [{}]", ConfigFile.getAbsolutePath());
} catch (IOException excp2) { } catch (IOException excp2) {

View file

@ -1,9 +1,14 @@
package net.halbear.Terrain4J.EngineCore.Logic; package net.halbear.Terrain4J.EngineCore.Logic;
import net.halbear.Terrain4J.EngineCore.Display.Render;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Display.Window;
import net.halbear.Terrain4J.EngineCore.Threads.FastTickThread;
import net.halbear.Terrain4J.EngineCore.Threads.MainThread;
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
public record EngineInstance(Window window, Scene scene) { public record EngineInstance(Window window, Scene scene, PrimaryRuntime PrimaryThread) {
public void cleanup(){ public void cleanup(){
window.cleanup(); window.cleanup();
} }

View file

@ -2,8 +2,9 @@ package net.halbear.Terrain4J.EngineCore.Logic;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.CompatibleVoxelMesh;
import java.util.List; import java.util.List;
public record InitData(List<ModelData> Models, List<MaterialData> Materials) { public record InitData(List<ModelData> Models, List<CompatibleVoxelMesh.VoxelModelData> voxelModels, List<MaterialData> Materials) {
} }

View file

@ -0,0 +1,9 @@
package net.halbear.Terrain4J.EngineCore.Logic;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.CompatibleVoxelMesh;
import java.util.List;
public record InitVoxelData(List<CompatibleVoxelMesh.VoxelModelData> Models, List<MaterialData> Materials) {
}

View file

@ -208,7 +208,7 @@ public class ModelCompiler {
int EmbeddedTextureIndex = matcher.matches() && matcher.groupCount() > 0 ? Integer.parseInt(matcher.group(1)) : -1; int EmbeddedTextureIndex = matcher.matches() && matcher.groupCount() > 0 ? Integer.parseInt(matcher.group(1)) : -1;
if (EmbeddedTextureIndex >= 0 && EmbeddedTextureIndex < EmbeddedTextureCount){ if (EmbeddedTextureIndex >= 0 && EmbeddedTextureIndex < EmbeddedTextureCount){
var aiTexture = AITexture.create(aiScene.mTextures().get(EmbeddedTextureIndex)); var aiTexture = AITexture.create(aiScene.mTextures().get(EmbeddedTextureIndex));
String BaseFile = aiTexture.mFilename().dataString() + ".png"; String BaseFile = aiTexture.mFilename().dataString() + "ModelTexture" +EmbeddedTextureIndex + ".png";
TexturePath = BaseDirectory + File.separator + BaseFile; TexturePath = BaseDirectory + File.separator + BaseFile;
Logger.info("Dumping Texture File to [{}]",TexturePath); Logger.info("Dumping Texture File to [{}]",TexturePath);
var Channel = FileChannel.open(Path.of(TexturePath), StandardOpenOption.CREATE,StandardOpenOption.WRITE); var Channel = FileChannel.open(Path.of(TexturePath), StandardOpenOption.CREATE,StandardOpenOption.WRITE);

View file

@ -7,7 +7,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorAlloca
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.PhysicalDevice;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.SwapChain; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.VulkanInstance;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanMemoryAllocator; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanMemoryAllocator;
import org.tinylog.Logger; import org.tinylog.Logger;

View file

@ -3,16 +3,15 @@ package net.halbear.Terrain4J.EngineCore.Main;
import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Display.Window;
import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput; import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput;
import net.halbear.Terrain4J.EngineCore.Input.MouseListener; import net.halbear.Terrain4J.EngineCore.Input.MouseListener;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.*;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.GameLogic;
import net.halbear.Terrain4J.EngineCore.Logic.InitData;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.ModelLoader;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Camera; import net.halbear.Terrain4J.EngineCore.Main.Scene.Camera;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
import net.halbear.Terrain4J.EngineCore.Main.Util.Maths.T4Math;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelData;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.CompatibleVoxelMesh;
import org.joml.Vector2f; import org.joml.Vector2f;
import org.joml.Vector3f; import org.joml.Vector3f;
import org.tinylog.Logger; import org.tinylog.Logger;
@ -33,6 +32,8 @@ public class GameCore implements GameLogic {
private List<Vector3f> Velocities = new ArrayList<>(); private List<Vector3f> Velocities = new ArrayList<>();
private Actor CubeActor; private Actor CubeActor;
private List<Actor> CubeActors = new ArrayList<>(); private List<Actor> CubeActors = new ArrayList<>();
private Vector2f LastMousePos = new Vector2f(0,0);
private int Ticks = 0;
@Override @Override
public void cleanup() { public void cleanup() {
@ -41,50 +42,80 @@ public class GameCore implements GameLogic {
@Override @Override
public InitData Initialise(EngineInstance engineInstance) { public InitData Initialise(EngineInstance engineInstance) {
CompatibleVoxelMesh GrassCube = new CompatibleVoxelMesh("GrassBlock")
.CreateMeshFace(CompatibleVoxelMesh.FaceDirection.North, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture1.png")
.CreateMeshFace(CompatibleVoxelMesh.FaceDirection.East, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture14.png")
.CreateMeshFace(CompatibleVoxelMesh.FaceDirection.South, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture13.png")
.CreateMeshFace(CompatibleVoxelMesh.FaceDirection.West, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture12.png")
.CreateMeshFace(CompatibleVoxelMesh.FaceDirection.Up, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture15.png")
.CreateMeshFace(CompatibleVoxelMesh.FaceDirection.Down, "resources/EngineResources/Texture/VoxelTextures/VoxelTexture0.png").CompileMesh();
InitVoxelData Voxels = CompatibleVoxelMesh.GetVoxelModelsGenerated();
List<CompatibleVoxelMesh.VoxelModelData> VoxelModels = Voxels.Models();
for(int i = 0; i < VoxelModels.size(); i++){
Logger.debug("Voxel -> [{}]",VoxelModels.get(i).ID());
}
Scene scene = engineInstance.scene(); Scene scene = engineInstance.scene();
List<ModelData> models = new ArrayList<>(); List<ModelData> models = new ArrayList<>();
//ModelData SponzaData = ModelLoader.LoadModel("resources/models/Unit02/evangelion_unit-02.json");
//List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Unit02/evangelion_unit-02_mat.json");
ModelData SponzaData = ModelLoader.LoadModel("resources/models/Sponza/Sponza.json"); ModelData SponzaData = ModelLoader.LoadModel("resources/models/Sponza/Sponza.json");
List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Sponza/Sponza_mat.json"); List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Sponza/Sponza_mat.json");
scene.AddActor(new Actor("Sponza", SponzaData.ID(), new Vector3f(0,0,-5f))); scene.AddActor(new Actor("Sponza", SponzaData.ID(), new Vector3f(0,0,-5f)));
models.add(ModelLoader.LoadModel("resources/models/Metro/OBJ/MetroLeadCar.json")); models.add(ModelLoader.LoadModel("resources/models/Metro/OBJ/MetroLeadCar.json"));
models.add(ModelLoader.LoadModel("resources/models/Corvette/CorvetteOBJ.json"));
//models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json"));
models.add(ModelLoader.LoadModel("resources/models/melona/melona.json")); models.add(ModelLoader.LoadModel("resources/models/melona/melona.json"));
models.add(ModelLoader.LoadModel("resources/models/Alice/Welsh040Alice.json")); models.add(ModelLoader.LoadModel("resources/models/Alice/Welsh040Alice.json"));
models.add(ModelLoader.LoadModel("resources/models/Sloop/SloopOBJ.json"));
models.add(ModelLoader.LoadModel("resources/models/Corvette/corvetteclass.json"));
for(int i = 0; i < 50000; i++) { for(int i = 0; i < 50000; i++) {
CubeActors.add(new Actor("CubeEntity" + i, models.get((int)Math.round(Math.min(Math.max((Math.random() * models.size() - 1),0),models.size() - 1))).ID(), new Vector3f((float)(-200 + Math.random() * 400), (float)(-50 + Math.random() * 100), (float)(250 + Math.random() * -500)))); CubeActors.add(new Actor("AdvancedModel" + i, models.get((int)Math.round(Math.min(Math.max(Math.random() *(Math.random() * models.size() - 1),0),models.size() - 1))).ID(), new Vector3f((float)(-200 + Math.random() * 400), (float)(-50 + Math.random() * 100), (float)(250 + Math.random() * -500))));
angles.add((float)(Math.random() * 360)); angles.add((float)(Math.random() * 360));
rotatingAngles.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2))); rotatingAngles.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2)));
Velocities.add(new Vector3f((float)(Math.random()*2), (float)(Math.random()*2), (float)(Math.random()*2))); Velocities.add(new Vector3f((float)(-2 + Math.random()*4), -2 + (float)(Math.random()*4), -2 + (float)(Math.random()*4)));
} }
CubeActors.forEach(scene::AddActor); CubeActors.forEach(scene::AddActor);
List<MaterialData> materials = new ArrayList<>(); List<MaterialData> materials = new ArrayList<>();
materials.addAll(ModelLoader.LoadMaterials("resources/models/Metro/OBJ/MetroLeadCar_mat.json")); materials.addAll(ModelLoader.LoadMaterials("resources/models/Metro/OBJ/MetroLeadCar_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/CorvetteOBJ_mat.json")); materials.addAll(ModelLoader.LoadMaterials("resources/models/Corvette/corvetteclass_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json")); materials.addAll(ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Alice/Welsh040Alice_mat.json")); materials.addAll(ModelLoader.LoadMaterials("resources/models/Alice/Welsh040Alice_mat.json"));
materials.addAll(ModelLoader.LoadMaterials("resources/models/Sloop/SloopOBJ_mat.json"));
materials.addAll(SponzaMaterial); materials.addAll(SponzaMaterial);
materials.addAll(Voxels.Materials());
models.add(SponzaData); models.add(SponzaData);
Camera camera = scene.GetCamera(); Camera camera = scene.GetCamera();
camera.SetPosition(0.0f, 0.0f, 0.0f); camera.SetPosition(40.0f, 155.0f, -42.0f);
camera.SetRotation((float) Math.toRadians(0.0f), (float) Math.toRadians(0.0f),0); camera.SetPosition(0,0,0);
return new InitData(models,materials); camera.SetRotation((float) Math.toRadians(10.0f), (float) Math.toRadians(-90.0f),0);
camera.SetRotation(0,0,0);
return new InitData(models,VoxelModels,materials);
} }
@Override @Override
public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) { public void CameraInput(EngineInstance engineInstance, long FrameDiffNanoSeconds) {
float Multiplier = MOUSE_SENSITIVITY;
Scene scene = engineInstance.scene(); Scene scene = engineInstance.scene();
Window window = engineInstance.window(); Window window = engineInstance.window();
Camera camera = scene.GetCamera(); Camera camera = scene.GetCamera();
MouseListener MouseInput = window.getMouseInput(); MouseListener MouseInput = window.getMouseInput();
Vector2f CurrentMousePos = window.getMouseInput().getCurrentPos();
Vector2f deltaPos = new Vector2f(0,0);
deltaPos.x = 0;
deltaPos.y = 0;
if (LastMousePos.x >= 0 && LastMousePos.y >= 0 && window.getMouseInput().IsWindowFocused()) {
deltaPos.x = CurrentMousePos.x - LastMousePos.x;
deltaPos.y = CurrentMousePos.y - LastMousePos.y;
}
LastMousePos.x = CurrentMousePos.x;
LastMousePos.y = CurrentMousePos.y;
if(MouseInput.isRightButtonPressed()){ if(MouseInput.isRightButtonPressed()){
Vector2f deltaPos = MouseInput.getDeltaPos();
camera.AddRotation((float)Math.toRadians(-deltaPos.y * MOUSE_SENSITIVITY),(float)Math.toRadians(-deltaPos.x * MOUSE_SENSITIVITY),0); camera.AddRotation((float)Math.toRadians(-deltaPos.y * Multiplier),(float)Math.toRadians(-deltaPos.x * Multiplier),0);
} }
} }
@ -122,9 +153,13 @@ public class GameCore implements GameLogic {
for(int i = 0; i < angles.size()/2; i++) { for(int i = 0; i < angles.size()/2; i++) {
angles.set(i, (angles.get(i) + 0.1f* DeltaTime) % 360); angles.set(i, (angles.get(i) + 0.1f* DeltaTime) % 360);
CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i)); CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i));
//CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime);
CubeActors.get(i).UpdateModelMatrix(); CubeActors.get(i).UpdateModelMatrix();
} }
Ticks++;
if(Ticks == 1000){
}
} }
@Override @Override
@ -133,7 +168,7 @@ public class GameCore implements GameLogic {
for(int i = angles.size()/2; i < angles.size(); i++) { for(int i = angles.size()/2; i < angles.size(); i++) {
angles.set(i, (angles.get(i) + 1.0f* DeltaTime) % 360); angles.set(i, (angles.get(i) + 1.0f* DeltaTime) % 360);
CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i)); CubeActors.get(i).GetRotation().identity().rotateAxis((float) EngineConfig.DegToRad * angles.get(i), rotatingAngles.get(i));
// CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime); CubeActors.get(i).GetPosition().add((Velocities.get(i).x/100.0f) * DeltaTime,(Velocities.get(i).y/100.0f) * DeltaTime,(Velocities.get(i).z/100.0f) * DeltaTime);
CubeActors.get(i).UpdateModelMatrix(); CubeActors.get(i).UpdateModelMatrix();
} }
} }

View file

@ -10,6 +10,11 @@ import net.halbear.Terrain4J.EngineCore.Threads.MainThread;
import net.halbear.Terrain4J.EngineCore.Threads.RenderThread; import net.halbear.Terrain4J.EngineCore.Threads.RenderThread;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PrimaryRuntime { public class PrimaryRuntime {
private int Frames = 0; private int Frames = 0;
private int TickFrames = 0; private int TickFrames = 0;
@ -30,9 +35,23 @@ public class PrimaryRuntime {
private static GameLogic gameLogic; private static GameLogic gameLogic;
public PrimaryRuntime(String windowTitle, GameLogic appLogic) { public PrimaryRuntime(String windowTitle, GameLogic appLogic) {
String[] knownDLSSfiles = {"nvngx_dlss.dll", "nvngx_dlssg.dll", "_nvngx.dll"};
for (String dllName : knownDLSSfiles) {
Path dllPath = Paths.get(System.getProperty("user.dir"), dllName);
if (Files.exists(dllPath)) {
try {
Logger.warn("DLSS is not supported, and is not allowed to be used with Terrain4J: [{}]",dllName);
Files.delete(dllPath);
Logger.info("removed local DLSS hook.");
} catch (IOException e) {
Logger.error("Could not remove DLSS DLL. Exiting to prevent pipeline corruption.");
System.exit(1);
}
}
}
window = new Window(windowTitle); window = new Window(windowTitle);
gameLogic = appLogic; gameLogic = appLogic;
engineInstance = new EngineInstance(window, new Scene(window)); engineInstance = new EngineInstance(window, new Scene(window),this);
InitData initData = appLogic.Initialise(engineInstance); InitData initData = appLogic.Initialise(engineInstance);
PrimaryThread = new MainThread(engineInstance, appLogic); PrimaryThread = new MainThread(engineInstance, appLogic);
FastThread = new FastTickThread(engineInstance, appLogic); FastThread = new FastTickThread(engineInstance, appLogic);
@ -40,6 +59,9 @@ public class PrimaryRuntime {
cpuProfiler = new CPUMonitor(); cpuProfiler = new CPUMonitor();
Thread.currentThread().setName("Terrain4J Primary Runtime Thread"); Thread.currentThread().setName("Terrain4J Primary Runtime Thread");
} }
public static MainThread GetMainThread(){return PrimaryThread;}
public static RenderThread GetRenderThread(){return DrawingThread;}
public static FastTickThread GetFastThread(){return FastThread;}
public static void UpdateFrameAccuracy(){ public static void UpdateFrameAccuracy(){
if(EngineConfig.getInstance().IsEngineThrottled()){ if(EngineConfig.getInstance().IsEngineThrottled()){
Logger.debug("ThrottlingEngine"); Logger.debug("ThrottlingEngine");
@ -101,7 +123,6 @@ public class PrimaryRuntime {
EngineConfig.FrameRate_PRIMARYTHREAD = Frames; EngineConfig.FrameRate_PRIMARYTHREAD = Frames;
EngineConfig.TPS = TickFrames; EngineConfig.TPS = TickFrames;
Logger.info("Primary Thread FPS: " + Frames + " TPS: " + TickFrames + " Window Draw FPS: " + EngineConfig.RENDERFRAMES); Logger.info("Primary Thread FPS: " + Frames + " TPS: " + TickFrames + " Window Draw FPS: " + EngineConfig.RENDERFRAMES);
Logger.info(cpuProfiler.LogCPUUsage() + "\t");
Frames = 0; Frames = 0;
TickFrames = 0; TickFrames = 0;
EngineConfig.RENDERFRAMES = 0; EngineConfig.RENDERFRAMES = 0;

View file

@ -4,4 +4,5 @@ public class T4Math {
public static double Log2(int n){ public static double Log2(int n){
return Math.log(n) / Math.log(n); return Math.log(n) / Math.log(n);
} }
public static double Square(double n){return n*n;}
} }

View file

@ -15,6 +15,7 @@ public class FastTickThread extends EngineThread {
@Override @Override
public void TickEvent(long nsTimeDiff){ public void TickEvent(long nsTimeDiff){
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (nsTimeDiff));
gameLogic.UpdateFastThread(PrimaryRuntime.GetEngineInstance(), nsTimeDiff); gameLogic.UpdateFastThread(PrimaryRuntime.GetEngineInstance(), nsTimeDiff);
} }
@Override @Override

View file

@ -10,7 +10,7 @@ public class MainThread extends EngineThread {
@Override @Override
public void TickEvent(long nsTimeDiff){ public void TickEvent(long nsTimeDiff){
gameLogic.Update(PrimaryRuntime.GetEngineInstance(), nsTimeDiff);
} }
@Override @Override
public void FrameEvent(long now, long InitialTime){ public void FrameEvent(long now, long InitialTime){

View file

@ -18,13 +18,14 @@ public class RenderThread extends EngineThread {
render.Initialise(initData); render.Initialise(initData);
} }
public Render GetRenderer(){return render;}
@Override @Override
public void TickEvent(long nsTimeDiff){ public void TickEvent(long nsTimeDiff){
} }
@Override @Override
public void FrameEvent(long now, long InitialTime){ public void FrameEvent(long now, long InitialTime){
gameLogic.Input(PrimaryRuntime.GetEngineInstance(), (now - InitialTime)); gameLogic.Update(PrimaryRuntime.GetEngineInstance(), (now - InitialTime));
render.render(PrimaryRuntime.GetEngineInstance()); render.render(PrimaryRuntime.GetEngineInstance());
} }
@Override @Override

View file

@ -0,0 +1,16 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering;
import org.lwjgl.vulkan.VkPipelineVertexInputStateCreateInfo;
public class EmptyVertexBufferStruct {
private final VkPipelineVertexInputStateCreateInfo VertexInput;
public EmptyVertexBufferStruct(){
VertexInput = VkPipelineVertexInputStateCreateInfo.calloc();
VertexInput.sType$Default();
}
public void CleanUp(){VertexInput.free();}
public VkPipelineVertexInputStateCreateInfo GetVertexInput(){return VertexInput;}
}

View file

@ -0,0 +1,193 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.ShaderModule;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import static org.lwjgl.vulkan.VK13.*;
import static org.lwjgl.vulkan.VK13.VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
import static org.lwjgl.vulkan.VK13.VK_BLEND_FACTOR_SRC_ALPHA;
import static org.lwjgl.vulkan.VK13.VK_BLEND_FACTOR_ZERO;
import static org.lwjgl.vulkan.VK13.VK_BLEND_OP_ADD;
import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_A_BIT;
import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_B_BIT;
import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_G_BIT;
import static org.lwjgl.vulkan.VK13.VK_COLOR_COMPONENT_R_BIT;
import static org.lwjgl.vulkan.VK13.VK_CULL_MODE_NONE;
import static org.lwjgl.vulkan.VK13.VK_DYNAMIC_STATE_SCISSOR;
import static org.lwjgl.vulkan.VK13.VK_DYNAMIC_STATE_VIEWPORT;
import static org.lwjgl.vulkan.VK13.VK_FORMAT_UNDEFINED;
import static org.lwjgl.vulkan.VK13.VK_FRONT_FACE_CLOCKWISE;
import static org.lwjgl.vulkan.VK13.VK_NULL_HANDLE;
import static org.lwjgl.vulkan.VK13.VK_SAMPLE_COUNT_1_BIT;
import static org.lwjgl.vulkan.VK13.VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
import static org.lwjgl.vulkan.VK13.vkCreateGraphicsPipelines;
import static org.lwjgl.vulkan.VK13.vkCreatePipelineLayout;
import static org.lwjgl.vulkan.VK13.vkDestroyPipeline;
import static org.lwjgl.vulkan.VK13.vkDestroyPipelineLayout;
public class DefaultPipeline implements Pipeline {
private final long VulkanPipeline;
private final long VulkanPipelineLayout;
public DefaultPipeline(VulkanContext VkCtx, PipelineBuildInfo BuildInfo){
Logger.debug("Creating Pipeline");
Device device = VkCtx.GetDevice();
try(var MemStack = MemoryStack.stackPush()){
LongBuffer longPtr = MemStack.mallocLong(1);
ByteBuffer main = MemStack.UTF8("main");
ShaderModule[] ShaderModules = BuildInfo.GetShaderModules();
int ModuleCount = ShaderModules.length;
var ShaderStages = VkPipelineShaderStageCreateInfo.calloc(ModuleCount, MemStack);
for(int i = 0; i < ModuleCount; i++){
ShaderModule shaderModule = ShaderModules[i];
ShaderStages.get(i)
.sType$Default()
.stage(shaderModule.GetShaderStage())
.module(shaderModule.GetHandle())
.pName(main);
if(shaderModule.GetSpecializationInfo() != null){
ShaderStages.get(i).pSpecializationInfo(shaderModule.GetSpecializationInfo());
}
}
var AssemblyStateCreateInfo = VkPipelineInputAssemblyStateCreateInfo.calloc(MemStack)
.sType$Default()
.topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
var ViewportCreateStateInfo = VkPipelineViewportStateCreateInfo.calloc(MemStack)
.sType$Default()
.viewportCount(1)
.scissorCount(1);
var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO)
.polygonMode(VK_POLYGON_MODE_FILL)
.cullMode(VK_CULL_MODE_NONE)
.frontFace(VK_FRONT_FACE_CLOCKWISE)
.lineWidth(1.0f);
int sampleCount = EngineConfig.getInstance().GetRenderSampleCount();
var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack)
.sType$Default()
.rasterizationSamples(sampleCount)
.sampleShadingEnable(false)
.minSampleShading(1.0f)
.pSampleMask(null)
.alphaToCoverageEnable(false)
.alphaToOneEnable(false);
VkPipelineDepthStencilStateCreateInfo DepthStencil = null;
if(BuildInfo.GetDepthFormat() != VK_FORMAT_UNDEFINED){
DepthStencil = VkPipelineDepthStencilStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO)
.depthTestEnable(true)
.depthWriteEnable(true)
.depthCompareOp(VK_COMPARE_OP_GREATER_OR_EQUAL)
.depthBoundsTestEnable(false)
.stencilTestEnable(false);
}
VkPipelineDynamicStateCreateInfo VulkanPipelineDynamicStateCreateInfo = VkPipelineDynamicStateCreateInfo.calloc(MemStack)
.sType$Default()
.pDynamicStates(MemStack.ints(
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
));
VkPushConstantRange.Buffer VkPushConstRangeBuffer = null;
PushConstantsRange[] PushConstRanges = BuildInfo.GetPushConstantRanges();
int PushConstCount = PushConstRanges != null ? PushConstRanges.length != 0 ? PushConstRanges.length : 0 : 0;
if(PushConstCount > 0){
VkPushConstRangeBuffer = VkPushConstantRange.calloc(PushConstCount,MemStack);
for(int i = 0; i < PushConstCount; i++){
PushConstantsRange pushConstantsRange = PushConstRanges[i];
VkPushConstRangeBuffer.get(i)
.stageFlags(pushConstantsRange.Stage())
.offset(pushConstantsRange.Offset())
.size(pushConstantsRange.Size());
}
}
DescriptorSetLayout[] descriptorSetLayouts = BuildInfo.GetDescriptorSetLayouts();
int LayoutCount = descriptorSetLayouts != null ? descriptorSetLayouts.length : 0;
LongBuffer ppLayout = MemStack.mallocLong(LayoutCount);
for(int i = 0; i < LayoutCount; i++){
ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout());
}
var BlendAttributeState = VkPipelineColorBlendAttachmentState.calloc(1,MemStack)
.colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)
.blendEnable(BuildInfo.BlendingUsed());
if(BuildInfo.BlendingUsed()){
BlendAttributeState.get(0).colorBlendOp(VK_BLEND_OP_ADD)
.alphaBlendOp(VK_BLEND_OP_ADD)
.srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA)
.dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA)
.srcAlphaBlendFactor(VK_BLEND_FACTOR_ONE)
.dstAlphaBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
}
var ColourBlendState = VkPipelineColorBlendStateCreateInfo.calloc(MemStack)
.sType$Default()
.pAttachments(BlendAttributeState);
IntBuffer ColourFormats = MemStack.mallocInt(1);
ColourFormats.put(0,BuildInfo.GetColourFormat());
var RendererCreateInfo = VkPipelineRenderingCreateInfo.calloc(MemStack)
.sType$Default()
.colorAttachmentCount(1)
.pColorAttachmentFormats(ColourFormats);
if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());}
var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack)
.sType$Default()
.pSetLayouts(ppLayout)
.pPushConstantRanges(VkPushConstRangeBuffer);
VulkanUtils.vkCheck(vkCreatePipelineLayout(device.FetchVulkanDevice(), PipelineLayoutCreateInfoPtr,null,longPtr)
,"Unable to create new pipeline layout");
VulkanPipelineLayout = longPtr.get(0);
var PipelineCreateInfo = VkGraphicsPipelineCreateInfo.calloc(1,MemStack)
.sType$Default()
.renderPass(VK_NULL_HANDLE)
.pStages(ShaderStages)
.pVertexInputState(BuildInfo.GetVertexInputStateCreateInfo())
.pInputAssemblyState(AssemblyStateCreateInfo)
.pViewportState(ViewportCreateStateInfo)
.pRasterizationState(RasterizationStateCreateInfo)
.pColorBlendState(ColourBlendState)
.pMultisampleState(MultisampleStateCreateInfo)
.pDynamicState(VulkanPipelineDynamicStateCreateInfo)
.layout(VulkanPipelineLayout)
.pNext(RendererCreateInfo);
if(DepthStencil != null){PipelineCreateInfo.pDepthStencilState(DepthStencil);}
VulkanUtils.vkCheck(vkCreateGraphicsPipelines(device.FetchVulkanDevice(),
VkCtx.GetVkPipelineCache().GetVkPipelineCache(), PipelineCreateInfo,
null, longPtr),"Could not create new pipeline");
VulkanPipeline = longPtr.get(0);
}
}
public long GetVulkanPipeline(){return VulkanPipeline;}
public long GetVulkanPipelineLayout(){return VulkanPipelineLayout;}
public void CleanUp(VulkanContext VkCtx){
Logger.debug("destroying Pipeline");
VkDevice vkDevice = VkCtx.GetDevice().FetchVulkanDevice();
vkDestroyPipelineLayout(vkDevice,VulkanPipelineLayout,null);
vkDestroyPipeline(vkDevice,VulkanPipeline,null);
}
}

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline; package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline;
import net.halbear.Terrain4J.EngineCore.Display.GLFWImageParser; import net.halbear.Terrain4J.EngineCore.Display.GLFWImageParser;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.ImageSrc; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.ImageSrc;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.tinylog.Logger; import org.tinylog.Logger;
@ -29,8 +30,8 @@ public class GraphUtils {
IntBuffer height = MemStack.mallocInt(1); IntBuffer height = MemStack.mallocInt(1);
image = stbi_load(Filename, width, height, channels, 4); image = stbi_load(Filename, width, height, channels, 4);
if (image == null) { if (image == null) {
Logger.error("Could not load or find image inputted."); Logger.error("Could not load or find image inputted. Image file [" + Filename + "] not loaded: " + stbi_failure_reason());
throw new IOException("Image file [" + Filename + "] not loaded: " + stbi_failure_reason()); image = stbi_load(EngineConfig.getInstance().GetDefaultTexturePath(), width, height, channels, 4);
} }
newImage = new ImageSrc(image, width.get(0), height.get(0), channels.get(0)); newImage = new ImageSrc(image, width.get(0), height.get(0), channels.get(0));
} }

View file

@ -1,5 +1,6 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images; package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView;
@ -11,8 +12,8 @@ public class Attachment {
private boolean DepthAttachment; private boolean DepthAttachment;
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){ public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){
var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format) var ImageData = new Image.ImageData().Width(Width).Height(Height)
.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT).MemoryUsage(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT); .Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT).Format(Format).MemoryUsage(VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT).SampleCount(EngineConfig.getInstance().GetRenderSampleCount());
VkImage = new Image(VkCtx, ImageData); VkImage = new Image(VkCtx, ImageData);
int AspectMask = 0; int AspectMask = 0;
@ -25,7 +26,7 @@ public class Attachment {
DepthAttachment = true; DepthAttachment = true;
} }
var ImageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(AspectMask); var ImageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(AspectMask);
VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), ImageViewData,false); VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), ImageViewData,DepthAttachment);
} }
public Image GetVkImage(){return VkImage;} public Image GetVkImage(){return VkImage;}

View file

@ -1,5 +1,6 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images; package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
@ -22,12 +23,19 @@ public class Image {
private final int Format; private final int Format;
private final int MipLevels; private final int MipLevels;
private final long VulkanImage; private final long VulkanImage;
private final int Width;
private final int Height;
//private final long VulkanMemory; //private final long VulkanMemory;
public int GetWidth(){return Width;}
public int GetHeight(){return Height;}
public Image(VulkanContext VkCtx, ImageData imageData){ public Image(VulkanContext VkCtx, ImageData imageData){
try(var MemStack = MemoryStack.stackPush()){ try(var MemStack = MemoryStack.stackPush()){
this.Format = imageData.Format; this.Format = imageData.Format;
this.MipLevels = imageData.MipMapLevels; this.MipLevels = imageData.MipMapLevels;
this.Width = imageData.Width;
this.Height = imageData.Height;
VkImageCreateInfo vkImageCreateInfo = VkImageCreateInfo.calloc(MemStack) VkImageCreateInfo vkImageCreateInfo = VkImageCreateInfo.calloc(MemStack)
.sType$Default() .sType$Default()

View file

@ -9,6 +9,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.*; import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;

View file

@ -4,6 +4,7 @@ import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.GraphUtils; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.GraphUtils;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.IndexedLinkedHashMap;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.VulkanMaterial;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; 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.CommandPool;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue;
@ -17,25 +18,16 @@ import java.util.UUID;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB;
public class TextureCache { public class TextureCache {
public static final int MAX_TEXTURES = 100; public static final int MAX_TEXTURES = 500;
private final IndexedLinkedHashMap<String, Texture> TextureMap; private final IndexedLinkedHashMap<String, Texture> TextureMap;
private final IndexedLinkedHashMap<String, Texture> UnpaddedTextureMap;
public TextureCache(){ public TextureCache(){
TextureMap = new IndexedLinkedHashMap<>(); TextureMap = new IndexedLinkedHashMap<>();
UnpaddedTextureMap = new IndexedLinkedHashMap<>();
} }
public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format){ public Texture AddToMainMap(VulkanContext VkCtx, String ID, String TexturePath, int Format) {
if(TextureMap.size() > MAX_TEXTURES){
throw new IllegalArgumentException("Texture Cache Is Full");
}
Texture newTexture = TextureMap.get(ID);
if(newTexture == null){
newTexture = new Texture(VkCtx, ID, imageSrc, Format);
TextureMap.put(ID, newTexture);
}
return newTexture;
}
public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) {
ImageSrc imageSrc = null; ImageSrc imageSrc = null;
Texture result = null; Texture result = null;
try{ try{
@ -50,15 +42,45 @@ public class TextureCache {
} }
return result; return result;
} }
public Texture AddTexture(VulkanContext VkCtx, String ID, ImageSrc imageSrc, int Format){
if(TextureMap.size() > MAX_TEXTURES){
throw new IllegalArgumentException("Texture Cache Is Full");
}
Texture newTexture = UnpaddedTextureMap.get(ID);
if(newTexture == null){
newTexture = new Texture(VkCtx, ID, imageSrc, Format);
UnpaddedTextureMap.put(ID, newTexture);
TextureMap.put(ID, newTexture);
}
return newTexture;
}
public Texture AddTexture(VulkanContext VkCtx, String ID, String TexturePath, int Format) {
ImageSrc imageSrc = null;
Texture result = null;
try{
imageSrc = GraphUtils.LoadImage(TexturePath);
result = AddTexture(VkCtx, ID, imageSrc, Format);
} catch (IOException exception){
Logger.error("Could not load texture from patch [{}], exception: {}",TexturePath, exception);
} finally{
if(imageSrc != null){
GraphUtils.CleanImageData(imageSrc);
}
}
return result;
}
public void TransitionTexts(VulkanContext VkCtx, CommandPool CmdPool, Queue queue){ public void TransitionTexts(VulkanContext VkCtx, CommandPool CmdPool, Queue queue){
Logger.debug("Recording Texture Transition"); Logger.debug("Recording Texture Transition");
TextureMap.clear();
TextureMap.putAll(UnpaddedTextureMap);
int TextureCount = TextureMap.size(); int TextureCount = TextureMap.size();
if(TextureCount < MAX_TEXTURES){ if(TextureCount < MAX_TEXTURES){
int PaddingTextCount = MAX_TEXTURES - TextureCount; int PaddingTextCount = MAX_TEXTURES - TextureCount;
String DefaultTexturePath = EngineConfig.getInstance().GetDefaultTexturePath(); String DefaultTexturePath = EngineConfig.getInstance().GetDefaultTexturePath();
for(int i = 0; i < PaddingTextCount; i++){ for(int i = 0; i < PaddingTextCount; i++){
AddTexture(VkCtx, UUID.randomUUID().toString(), DefaultTexturePath, VK_FORMAT_R8G8B8A8_SRGB); AddToMainMap(VkCtx, UUID.randomUUID().toString(), DefaultTexturePath, VK_FORMAT_R8G8B8A8_SRGB);
} }
} }
var CommandBuffer = new CommandBuffer(VkCtx, CmdPool, true, true); var CommandBuffer = new CommandBuffer(VkCtx, CmdPool, true, true);
@ -71,6 +93,7 @@ public class TextureCache {
Logger.debug("Recorded Texture Transition"); Logger.debug("Recorded Texture Transition");
} }
public IndexedLinkedHashMap<String, Texture> GetTextureCache(){return TextureMap;}
public List<Texture> GetTextureList(){return new ArrayList<>(TextureMap.values());} public List<Texture> GetTextureList(){return new ArrayList<>(TextureMap.values());}
public int GetPosition(String ID){ public int GetPosition(String ID){
int result = -1; int result = -1;

View file

@ -3,6 +3,7 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
public class IndexedLinkedHashMap<K,V> extends LinkedHashMap<K,V> { public class IndexedLinkedHashMap<K,V> extends LinkedHashMap<K,V> {
private final List<K> IndexList = new ArrayList<>(); private final List<K> IndexList = new ArrayList<>();
@ -20,4 +21,11 @@ public class IndexedLinkedHashMap<K,V> extends LinkedHashMap<K,V> {
if(!super.containsKey(key)) IndexList.add(key); if(!super.containsKey(key)) IndexList.add(key);
return super.put(key,value); return super.put(key,value);
} }
//@Override
//public void putAll(Map<? extends K, ? extends V> m) {
// m.forEach((k, v)->{
// put(k,v);
// IndexList.add(k);
// });
//}
} }

View file

@ -1,163 +1,10 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline; package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.ShaderModule;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.ByteBuffer; public interface Pipeline {
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
public class Pipeline {
private final long VulkanPipeline;
private final long VulkanPipelineLayout;
public Pipeline(VulkanContext VkCtx, PipelineBuildInfo BuildInfo){
Logger.debug("Creating Pipeline");
Device device = VkCtx.GetDevice();
try(var MemStack = MemoryStack.stackPush()){
LongBuffer longPtr = MemStack.mallocLong(1);
ByteBuffer main = MemStack.UTF8("main");
ShaderModule[] ShaderModules = BuildInfo.GetShaderModules();
int ModuleCount = ShaderModules.length;
var ShaderStages = VkPipelineShaderStageCreateInfo.calloc(ModuleCount, MemStack);
for(int i = 0; i < ModuleCount; i++){
ShaderModule shaderModule = ShaderModules[i];
ShaderStages.get(i)
.sType$Default()
.stage(shaderModule.GetShaderStage())
.module(shaderModule.GetHandle())
.pName(main);
}
var AssemblyStateCreateInfo = VkPipelineInputAssemblyStateCreateInfo.calloc(MemStack)
.sType$Default()
.topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
var ViewportCreateStateInfo = VkPipelineViewportStateCreateInfo.calloc(MemStack)
.sType$Default()
.viewportCount(1)
.scissorCount(1);
var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack)
.sType$Default()
.polygonMode(VK_POLYGON_MODE_FILL)
.cullMode(VK_CULL_MODE_NONE)
.frontFace(VK_FRONT_FACE_CLOCKWISE)
.lineWidth(1.0f);
var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack)
.sType$Default()
.rasterizationSamples(VK_SAMPLE_COUNT_1_BIT);
VkPipelineDepthStencilStateCreateInfo DepthStencil = null;
if(BuildInfo.GetDepthFormat() != VK_FORMAT_UNDEFINED){
DepthStencil = VkPipelineDepthStencilStateCreateInfo.calloc(MemStack)
.sType$Default()
.depthTestEnable(true)
.depthWriteEnable(true)
.depthCompareOp(VK_COMPARE_OP_LESS_OR_EQUAL)
.depthBoundsTestEnable(false)
.stencilTestEnable(false);
}
VkPipelineDynamicStateCreateInfo VulkanPipelineDynamicStateCreateInfo = VkPipelineDynamicStateCreateInfo.calloc(MemStack)
.sType$Default()
.pDynamicStates(MemStack.ints(
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR
));
VkPushConstantRange.Buffer VkPushConstRangeBuffer = null;
PushConstantsRange[] PushConstRanges = BuildInfo.GetPushConstantRanges();
int PushConstCount = PushConstRanges.length != 0 ? PushConstRanges.length : 0;
if(PushConstCount > 0){
VkPushConstRangeBuffer = VkPushConstantRange.calloc(PushConstCount,MemStack);
for(int i = 0; i < PushConstCount; i++){
PushConstantsRange pushConstantsRange = PushConstRanges[i];
VkPushConstRangeBuffer.get(i)
.stageFlags(pushConstantsRange.Stage())
.offset(pushConstantsRange.Offset())
.size(pushConstantsRange.Size());
}
}
DescriptorSetLayout[] descriptorSetLayouts = BuildInfo.GetDescriptorSetLayouts();
int LayoutCount = descriptorSetLayouts != null ? descriptorSetLayouts.length : 0;
LongBuffer ppLayout = MemStack.mallocLong(LayoutCount);
for(int i = 0; i < LayoutCount; i++){
ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout());
}
var BlendAttributeState = VkPipelineColorBlendAttachmentState.calloc(1,MemStack)
.colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)
.blendEnable(BuildInfo.BlendingUsed());
if(BuildInfo.BlendingUsed()){
BlendAttributeState.get(0).colorBlendOp(VK_BLEND_OP_ADD)
.alphaBlendOp(VK_BLEND_OP_ADD)
.srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA)
.dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA)
.srcAlphaBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA)
.dstAlphaBlendFactor(VK_BLEND_FACTOR_ZERO);
}
var ColourBlendState = VkPipelineColorBlendStateCreateInfo.calloc(MemStack)
.sType$Default()
.pAttachments(BlendAttributeState);
IntBuffer ColourFormats = MemStack.mallocInt(1);
ColourFormats.put(0,BuildInfo.GetColourFormat());
var RendererCreateInfo = VkPipelineRenderingCreateInfo.calloc(MemStack)
.sType$Default()
.colorAttachmentCount(1)
.pColorAttachmentFormats(ColourFormats);
if(DepthStencil != null){RendererCreateInfo.depthAttachmentFormat(BuildInfo.GetDepthFormat());}
var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack)
.sType$Default()
.pSetLayouts(ppLayout)
.pPushConstantRanges(VkPushConstRangeBuffer);
VulkanUtils.vkCheck(vkCreatePipelineLayout(device.FetchVulkanDevice(), PipelineLayoutCreateInfoPtr,null,longPtr)
,"Unable to create new pipeline layout");
VulkanPipelineLayout = longPtr.get(0);
var PipelineCreateInfo = VkGraphicsPipelineCreateInfo.calloc(1,MemStack)
.sType$Default()
.renderPass(VK_NULL_HANDLE)
.pStages(ShaderStages)
.pVertexInputState(BuildInfo.GetVertexInputStateCreateInfo())
.pInputAssemblyState(AssemblyStateCreateInfo)
.pViewportState(ViewportCreateStateInfo)
.pRasterizationState(RasterizationStateCreateInfo)
.pColorBlendState(ColourBlendState)
.pMultisampleState(MultisampleStateCreateInfo)
.pDynamicState(VulkanPipelineDynamicStateCreateInfo)
.layout(VulkanPipelineLayout)
.pNext(RendererCreateInfo);
if(DepthStencil != null){PipelineCreateInfo.pDepthStencilState(DepthStencil);}
VulkanUtils.vkCheck(vkCreateGraphicsPipelines(device.FetchVulkanDevice(),
VkCtx.GetVkPipelineCache().GetVkPipelineCache(), PipelineCreateInfo,
null, longPtr),"Could not create new pipeline");
VulkanPipeline = longPtr.get(0);
}
}
public long GetVulkanPipeline(){return VulkanPipeline;}
public long GetVulkanPipelineLayout(){return VulkanPipelineLayout;}
public void CleanUp(VulkanContext VkCtx){
Logger.debug("destroying Pipeline");
VkDevice vkDevice = VkCtx.GetDevice().FetchVulkanDevice();
vkDestroyPipelineLayout(vkDevice,VulkanPipelineLayout,null);
vkDestroyPipeline(vkDevice,VulkanPipeline,null);
}
public long GetVulkanPipeline();
public long GetVulkanPipelineLayout();
public void CleanUp(VulkanContext VkCtx);
} }

View file

@ -0,0 +1,174 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import java.nio.LongBuffer;
import static org.lwjgl.vulkan.VK10.*;
public class VoxelPipeline implements Pipeline{
private final long VulkanPipeline;
private final long VulkanPipelineLayout;
public VoxelPipeline(VulkanContext VkCtx, PipelineBuildInfo BuildInfo){
Device device = VkCtx.GetDevice();
try(var MemStack = MemoryStack.stackPush()) {
LongBuffer longPtr = MemStack.mallocLong(1);
VkPushConstantRange.Buffer VkPushConstRangeBuffer = null;
PushConstantsRange[] PushConstRanges = BuildInfo.GetPushConstantRanges();
int PushConstCount = PushConstRanges.length != 0 ? PushConstRanges.length : 0;
if (PushConstCount > 0) {
VkPushConstRangeBuffer = VkPushConstantRange.calloc(PushConstCount, MemStack);
for (int i = 0; i < PushConstCount; i++) {
PushConstantsRange pushConstantsRange = PushConstRanges[i];
VkPushConstRangeBuffer.get(i)
.stageFlags(pushConstantsRange.Stage())
.offset(pushConstantsRange.Offset())
.size(pushConstantsRange.Size());
}
}
DescriptorSetLayout[] descriptorSetLayouts = BuildInfo.GetDescriptorSetLayouts();
int LayoutCount = descriptorSetLayouts != null ? descriptorSetLayouts.length : 0;
LongBuffer ppLayout = MemStack.mallocLong(LayoutCount);
for (int i = 0; i < LayoutCount; i++) {
ppLayout.put(i, descriptorSetLayouts[i].GetVkDescriptorLayout());
}
var PipelineLayoutCreateInfoPtr = VkPipelineLayoutCreateInfo.calloc(MemStack)
.sType$Default()
.pSetLayouts(ppLayout)
.pPushConstantRanges(VkPushConstRangeBuffer);
VulkanUtils.vkCheck(vkCreatePipelineLayout(device.FetchVulkanDevice(), PipelineLayoutCreateInfoPtr, null, longPtr)
, "Unable to create new pipeline layout");
VulkanPipelineLayout = longPtr.get(0);
VulkanPipeline = CreateVoxelPipeline(VkCtx,device.FetchVulkanDevice(), 0, VulkanPipelineLayout,MemStack);
}
}
public static long CreatePipelineLayout(VkDevice device,LongBuffer DescriptorSetLayout, MemoryStack MemStack){
VkDescriptorSetLayoutBinding.Buffer BindingBuffer = VkDescriptorSetLayoutBinding.calloc(2,MemStack);
BindingBuffer.get(0)
.binding(0)
.descriptorType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
.descriptorCount(1)
.stageFlags(VK_SHADER_STAGE_VERTEX_BIT);
BindingBuffer.get(1)
.binding(1)
.descriptorType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
.descriptorCount(1)
.stageFlags(VK_SHADER_STAGE_FRAGMENT_BIT);
VkDescriptorSetLayoutCreateInfo LayoutInfo = VkDescriptorSetLayoutCreateInfo.calloc(MemStack)
.sType$Default()
.pBindings(BindingBuffer);
LongBuffer LongPtr = MemStack.mallocLong(1);
VulkanUtils.vkCheck(vkCreateDescriptorSetLayout(device, LayoutInfo,
null, LongPtr),"Could not create new Descriptor Set Layout");
Long pDescriptorSetLayout = LongPtr.get(0);
DescriptorSetLayout.put(0,pDescriptorSetLayout);
LongBuffer LayoutPointer = MemStack.longs(pDescriptorSetLayout);
VkPipelineLayoutCreateInfo PipelineLayoutInfo = VkPipelineLayoutCreateInfo.calloc(MemStack)
.sType$Default()
.pSetLayouts(LayoutPointer);
VulkanUtils.vkCheck(vkCreatePipelineLayout(device, PipelineLayoutInfo,
null, LongPtr),"Could not create Pipeline Layout");
return LongPtr.get(0);
}
public static long CreateVoxelPipeline(VulkanContext VkCtx,VkDevice device, long RenderPass, long PipelineLayout, MemoryStack MemStack) {
LongBuffer longPtr = MemStack.mallocLong(1);
VkVertexInputBindingDescription.Buffer BindingDescriptionBuffer = VkVertexInputBindingDescription.calloc(1, MemStack)
.binding(0)
.stride(5)
.inputRate(VK_VERTEX_INPUT_RATE_VERTEX);
VkVertexInputAttributeDescription.Buffer AttributeDescriptionsBuffer = VkVertexInputAttributeDescription.calloc(2, MemStack);
AttributeDescriptionsBuffer.get(0)
.location(0)
.binding(0)
.format(VK_FORMAT_R8G8B8_UINT)
.offset(0);
AttributeDescriptionsBuffer.get(1)
.location(1)
.binding(0)
.format(VK_FORMAT_R8G8_UINT);
VkPipelineVertexInputStateCreateInfo VertexInputInfo = VkPipelineVertexInputStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO)
.pVertexBindingDescriptions(BindingDescriptionBuffer)
.pVertexAttributeDescriptions(AttributeDescriptionsBuffer);
var AssemblyStateCreateInfo = VkPipelineInputAssemblyStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO)
.topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST).primitiveRestartEnable(false);
var ViewportCreateStateInfo = VkPipelineViewportStateCreateInfo.calloc(MemStack)
.sType$Default()
.viewportCount(1)
.scissorCount(1);
var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO)
.depthClampEnable(false)
.rasterizerDiscardEnable(false)
.polygonMode(VK_POLYGON_MODE_FILL)
.cullMode(VK_CULL_MODE_BACK_BIT)
.frontFace(VK_FRONT_FACE_CLOCKWISE)
.lineWidth(1.0f)
.depthBiasEnable(false);
var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack)
.sType$Default()
.sampleShadingEnable(false)
.rasterizationSamples(VK_SAMPLE_COUNT_1_BIT);
VkPipelineColorBlendAttachmentState.Buffer ColourBlendAttachment = VkPipelineColorBlendAttachmentState.calloc(1, MemStack)
.colorWriteMask(VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT)
.blendEnable(false);
VkPipelineColorBlendStateCreateInfo ColourBlending = VkPipelineColorBlendStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO)
.logicOpEnable(false)
.pAttachments(ColourBlendAttachment);
VkGraphicsPipelineCreateInfo.Buffer PipelineInfo = VkGraphicsPipelineCreateInfo.calloc(1)
.sType(VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO)
.pVertexInputState(VertexInputInfo)
.pInputAssemblyState(AssemblyStateCreateInfo)
.pViewportState(ViewportCreateStateInfo)
.pRasterizationState(RasterizationStateCreateInfo)
.pMultisampleState(MultisampleStateCreateInfo)
.pColorBlendState(ColourBlending)
.layout(PipelineLayout)
.renderPass(RenderPass)
.subpass(0);
VulkanUtils.vkCheck(vkCreateGraphicsPipelines(device,
VkCtx.GetVkPipelineCache().GetVkPipelineCache(), PipelineInfo,
null, longPtr),"Could not create new pipeline");
// Clean up allocation structs
PipelineInfo.free(); ColourBlending.free(); ColourBlendAttachment.free();
MultisampleStateCreateInfo.free(); RasterizationStateCreateInfo.free(); ViewportCreateStateInfo.free();
AssemblyStateCreateInfo.free(); VertexInputInfo.free(); AssemblyStateCreateInfo.free();
BindingDescriptionBuffer.free();
return longPtr.get(0);
}
@Override
public long GetVulkanPipeline() {
return VulkanPipeline;
}
@Override
public long GetVulkanPipelineLayout() {
return VulkanPipelineLayout;
}
@Override
public void CleanUp(VulkanContext VkCtx) {
Logger.debug("destroying Pipeline");
VkDevice vkDevice = VkCtx.GetDevice().FetchVulkanDevice();
vkDestroyPipelineLayout(vkDevice,VulkanPipelineLayout,null);
vkDestroyPipeline(vkDevice,VulkanPipeline,null);
}
}

View file

@ -0,0 +1,219 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.EmptyVertexBufferStruct;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Image;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.*;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.shaderc.Shaderc;
import org.lwjgl.vulkan.*;
import java.nio.FloatBuffer;
import java.nio.LongBuffer;
import java.util.Arrays;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.*;
public class PostProcess {
public static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
private static final String DESCRIPTOR_ID_ATTACHMENT = "POST_DESC_ID_ATT";
private static final String DESCRIPTOR_ID_SCREEN_SIZE = "POST_DESC_ID_SCREEN_SIZE";
private static final String MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl";
private static final String MULTI_PASS_FRAGMENT_SHADER_FILE_SPV = MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/post_process_frag.glsl";
private static final String SINGLE_PASS_FRAGMENT_SHADER_FILE_SPV = SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/post_process_vtx.glsl";
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
private final VkClearValue ClearValueColour;
private final DescriptorSetLayout FragmentUniformDescriptorSetLayout;
private final Pipeline pipeline;
private final VulkanBuffer ScreenSizeBuffer;
private final SpecializationConstants specConstants;
private final TextureSampler textureSampler;
private Attachment ColourAttachment;
private VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo;
private VkRenderingInfo RenderingInfo;
public PostProcess(VulkanContext VkCtx, Attachment SrcAttachment){
ClearValueColour = VkClearValue.calloc();
ClearValueColour.color(c->c.float32(0,0.0f).float32(1,0.0f).float32(2,0.0f).float32(3,0.0f));
ColourAttachment = CreateColourAttachment(VkCtx);
ColourAttachmentInfo = CreateColourAttachmentInfo(ColourAttachment,ClearValueColour);
RenderingInfo = CreateRenderInfo(ColourAttachment,ColourAttachmentInfo);
var TextureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK,1,true);
textureSampler = new TextureSampler(VkCtx, TextureSamplerInfo);
var LayoutInfo = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,0,1,VK_SHADER_STAGE_FRAGMENT_BIT);
AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, LayoutInfo);
CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, SrcAttachment,textureSampler);
LayoutInfo = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0,1,VK_SHADER_STAGE_FRAGMENT_BIT);
FragmentUniformDescriptorSetLayout = new DescriptorSetLayout(VkCtx, LayoutInfo);
ScreenSizeBuffer = VulkanUtils.CreateHostVisibleBuffer(VkCtx, VulkanUtils.VEC2_SIZE, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,DESCRIPTOR_ID_SCREEN_SIZE,FragmentUniformDescriptorSetLayout);
SetScreenSizeBuffer(VkCtx);
specConstants = new SpecializationConstants();
ShaderModule[] shaderModules = CreateShaderModules(VkCtx, specConstants);
pipeline = CreatePipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, FragmentUniformDescriptorSetLayout});
Arrays.asList(shaderModules).forEach(shader->shader.CleanUp(VkCtx));
}
private static Attachment CreateColourAttachment(VulkanContext VkCtx){
SwapChain swapChain = VkCtx.GetSwapChain();
VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent();
return new Attachment(VkCtx,SwapChainExtent.width(),SwapChainExtent.height(),COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
}
private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment SrcAttachment, VkClearValue ClearValue){
return VkRenderingAttachmentInfo.calloc(1)
.sType$Default()
.imageView(SrcAttachment.GetVkImageView().GetVulkanImageView())
.imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
.clearValue(ClearValue);
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){
var VertexBufferStruct = new EmptyVertexBufferStruct();
var BuildInfo = new PipelineBuildInfo(shaderModules,VertexBufferStruct.GetVertexInput(),COLOUR_FORMAT).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true);
var PipeLine = new DefaultPipeline(VkCtx,BuildInfo);
VertexBufferStruct.CleanUp();
return PipeLine;
}
private static VkRenderingInfo CreateRenderInfo(Attachment ColourAttachment, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo){
VkRenderingInfo renderingInfo;
try(var MemStack = MemoryStack.stackPush()){
Image image = ColourAttachment.GetVkImage();
VkExtent2D extent2D = VkExtent2D.calloc(MemStack).width(image.GetWidth()).height(image.GetHeight());
var RenderArea = VkRect2D.calloc(MemStack).extent(extent2D);
renderingInfo = VkRenderingInfo.calloc()
.sType$Default()
.renderArea(RenderArea)
.layerCount(1)
.pColorAttachments(ColourAttachmentInfo);
}
return renderingInfo;
}
private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descriptorSetLayout, Attachment attachment, TextureSampler textureSampler){
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
Device device = VkCtx.GetDevice();
DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device,DESCRIPTOR_ID_ATTACHMENT,1 , descriptorSetLayout)[0];
descriptorSet.SetImage(device,attachment.GetVkImageView(),textureSampler,0);
}
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, SpecializationConstants specConstants){
String ShaderPath = SINGLE_PASS_FRAGMENT_SHADER_FILE_GLSL;
if(EngineConfig.getInstance().RecompileShaders()){
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
if(EngineConfig.getInstance().RenderAA() > 1) ShaderPath = MULTI_PASS_FRAGMENT_SHADER_FILE_GLSL;
ShaderCompiler.CompileGLSLShaderOnChange(ShaderPath, Shaderc.shaderc_glsl_fragment_shader);
}
ShaderPath = SINGLE_PASS_FRAGMENT_SHADER_FILE_SPV;
if(EngineConfig.getInstance().RenderAA() > 1) ShaderPath = MULTI_PASS_FRAGMENT_SHADER_FILE_SPV;
return new ShaderModule[]{
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){
try(var MemStack = MemoryStack.stackPush()){
SwapChain swapChain = VkCtx.GetSwapChain();
VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer();
VulkanUtils.ImageBarrier(MemStack, CommandHandle, SrcAttachment.GetVkImage().getVulkanImage(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_SHADER_READ_BIT,VK_IMAGE_ASPECT_COLOR_BIT);
VulkanUtils.ImageBarrier(MemStack,CommandHandle,ColourAttachment.GetVkImage().getVulkanImage(),
VK_IMAGE_LAYOUT_UNDEFINED,VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_2_NONE,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_IMAGE_ASPECT_COLOR_BIT);
vkCmdBeginRendering(CommandHandle,RenderingInfo);
vkCmdBindPipeline(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipeline());
VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent();
int Width = SwapChainExtent.width();
int Height = SwapChainExtent.height();
var Viewport = VkViewport.calloc(1,MemStack)
.x(0)
.y(Height)
.height(-Height)
.width(Width)
.minDepth(0.0f)
.maxDepth(1.0f);
vkCmdSetViewport(CommandHandle,0,Viewport);
var Scissor = VkRect2D.calloc(1,MemStack)
.extent(it->it.width(Width).height(Height))
.offset(it->it.x(0).y(0));
vkCmdSetScissor(CommandHandle,0,Scissor);
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
LongBuffer DescriptorSets = MemStack.mallocLong(2)
.put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT).GetVkDescriptorSet())
.put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_SCREEN_SIZE).GetVkDescriptorSet());
vkCmdBindDescriptorSets(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
vkCmdDraw(CommandHandle,3,1,0,0);
vkCmdEndRendering(CommandHandle);
}
}
public void Resize(VulkanContext VkCtx, Attachment SrcAttachment){
RenderingInfo.free();;
ColourAttachment.CleanUp(VkCtx);
ColourAttachmentInfo.free();
ColourAttachment = CreateColourAttachment(VkCtx);
ColourAttachmentInfo = CreateColourAttachmentInfo(ColourAttachment,ClearValueColour);
RenderingInfo = CreateRenderInfo(ColourAttachment,ColourAttachmentInfo);
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT);
descriptorSet.SetImage(VkCtx.GetDevice(),SrcAttachment.GetVkImageView(),textureSampler,0);
SetScreenSizeBuffer(VkCtx);
}
private void SetScreenSizeBuffer(VulkanContext VkCtx){
long MappedMemory = ScreenSizeBuffer.MapMemory(VkCtx);
FloatBuffer dataBuffer = MemoryUtil.memFloatBuffer(MappedMemory,(int)ScreenSizeBuffer.GetRequestedSize());
VkExtent2D SwapChainExtent = VkCtx.GetSwapChain().GetSwapChainExtent();
dataBuffer.put(0,SwapChainExtent.width());
dataBuffer.put(1,SwapChainExtent.height());
ScreenSizeBuffer.UnMapMemory(VkCtx);
}
public Attachment GetAttachment(){return ColourAttachment;}
public void CleanUp(VulkanContext VkCtx){
ClearValueColour.free();
ColourAttachment.CleanUp(VkCtx);
textureSampler.CleanUp(VkCtx);
AttachmentDescriptorSetLayout.CleanUp(VkCtx);
FragmentUniformDescriptorSetLayout.CleanUp(VkCtx);
pipeline.CleanUp(VkCtx);
RenderingInfo.free();
ColourAttachmentInfo.free();
ScreenSizeBuffer.cleanup(VkCtx);
specConstants.CleanUp();
}
}

View file

@ -0,0 +1,39 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.PostProcessing;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.VkSpecializationInfo;
import org.lwjgl.vulkan.VkSpecializationMapEntry;
import java.nio.ByteBuffer;
public class SpecializationConstants {
private final ByteBuffer data;
private final VkSpecializationMapEntry.Buffer SpecializationEntryMap;
private final VkSpecializationInfo SpecializationInfo;
public SpecializationConstants(){
var EngineCfg = EngineConfig.getInstance();
data = MemoryUtil.memAlloc(VulkanUtils.INT_SIZE);
data.putInt(EngineCfg.RenderAA());
data.flip();
SpecializationEntryMap = VkSpecializationMapEntry.calloc(1);
SpecializationEntryMap.get(0)
.constantID(0)
.size(VulkanUtils.INT_SIZE)
.offset(0);
SpecializationInfo = VkSpecializationInfo.calloc();
SpecializationInfo.pData(data).pMapEntries(SpecializationEntryMap);
}
public void CleanUp(){
MemoryUtil.memFree(SpecializationEntryMap);
SpecializationInfo.free();
MemoryUtil.memFree(data);
}
public VkSpecializationInfo GetSpecializationInfo(){return SpecializationInfo;}
}

View file

@ -6,6 +6,8 @@ import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.VkShaderModuleCreateInfo; import org.lwjgl.vulkan.VkShaderModuleCreateInfo;
import static org.lwjgl.vulkan.VK13.vkCreateShaderModule; import static org.lwjgl.vulkan.VK13.vkCreateShaderModule;
import static org.lwjgl.vulkan.VK13.vkDestroyShaderModule; import static org.lwjgl.vulkan.VK13.vkDestroyShaderModule;
import org.lwjgl.vulkan.VkSpecializationInfo;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.File; import java.io.File;
@ -18,12 +20,14 @@ import java.nio.file.Files;
public class ShaderModule { public class ShaderModule {
private final long Handle; private final long Handle;
private final int ShaderStage; private final int ShaderStage;
private final VkSpecializationInfo SpecializationInfo;
public ShaderModule(VulkanContext VkCtx, int ShaderStage, String ShaderSPVFile){ public ShaderModule(VulkanContext VkCtx, int ShaderStage, String ShaderSPVFile,VkSpecializationInfo SpecializationInfo){
try{ try{
byte[] Contents = Files.readAllBytes(new File(ShaderSPVFile).toPath()); byte[] Contents = Files.readAllBytes(new File(ShaderSPVFile).toPath());
Handle = CreateShaderModule(VkCtx, Contents); Handle = CreateShaderModule(VkCtx, Contents);
this.ShaderStage = ShaderStage; this.ShaderStage = ShaderStage;
this.SpecializationInfo = SpecializationInfo;
} catch(IOException exception){ } catch(IOException exception){
Logger.error("Cannot Read Shader Files",exception); Logger.error("Cannot Read Shader Files",exception);
throw new RuntimeException(exception); throw new RuntimeException(exception);
@ -42,6 +46,8 @@ public class ShaderModule {
} }
} }
public VkSpecializationInfo GetSpecializationInfo(){return SpecializationInfo;}
public void CleanUp(VulkanContext VkCtx){ public void CleanUp(VulkanContext VkCtx){
vkDestroyShaderModule(VkCtx.GetDevice().FetchVulkanDevice(), Handle, null); vkDestroyShaderModule(VkCtx.GetDevice().FetchVulkanDevice(), Handle, null);
} }

View file

@ -0,0 +1,225 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel;
import net.halbear.Terrain4J.EngineCore.Display.Render;
import net.halbear.Terrain4J.EngineCore.Logic.InitVoxelData;
import org.joml.Vector4f;
import org.lwjgl.system.MemoryUtil;
import org.tinylog.Logger;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class CompatibleVoxelMesh {
private static final int VERTEX_STRIDE = 6;
public static List<VoxelModelInitData> voxelModels = new ArrayList<>();
public static List<String> TexturePaths = new ArrayList<>();
private Render renderInstance;
private float[] VertexArray;
private int[] IndicesArray;
private final String ID;
private boolean[] Faces = new boolean[]{false,false,false,false,false,false};
private int[] Textureindex = new int[6];
private Vector4f[] DiffuseColours = new Vector4f[]{new Vector4f(0.6f, 0.6f, 0.6f, 1.0f),new Vector4f(0.5f, 0.5f, 0.5f, 1.0f),new Vector4f(0.4f, 0.4f, 0.4f, 1.0f),new Vector4f(0.5f, 0.5f, 0.5f, 1.0f),new Vector4f(0.7f, 0.7f, 0.7f, 1.0f),new Vector4f(0.3f, 0.3f, 0.3f, 1.0f)};
static{
TexturePaths.add("resources/EngineResources/Texture/DefaultTexture.png");
}
public enum FaceDirection{
North(0),
South(2),
East(1),
West(3),
Up(4),
Down(5);
private final int value;
FaceDirection(int value) {
this.value = value;
}
// 3. Add a getter method to access the number
public int getValue() {
return value;
}
}
public record VoxelModelInitData(VoxelModelData voxelModel, List<MaterialData> materialData){}
public record VoxelModelData(String ID, List<MeshData> meshes, FloatBuffer vertexBuffer, IntBuffer indexBuffer){}
public record VoxelMeshData(String ID, FloatBuffer vertexBuffer, IntBuffer indexBuffer, int VertexCount, int IndexCount){}
public CompatibleVoxelMesh(String VoxelID){
VertexArray = new float[6 * 20];
IndicesArray = new int[6 * 6];
ID = VoxelID;
}
public CompatibleVoxelMesh(Render rendererInstance, String VoxelID){
renderInstance = rendererInstance;
VertexArray = new float[6 * 20];
IndicesArray = new int[6 * 6];
ID = VoxelID;
}
public CompatibleVoxelMesh SetSideTexture(int SideNumber, String TextureID){
int index = TexturePaths.indexOf(TextureID);
if(index < 0){
TexturePaths.add(TextureID);
index = TexturePaths.indexOf(TextureID);
}
Textureindex[SideNumber] = index;
return this;
}
public CompatibleVoxelMesh CreateMeshFace(FaceDirection faceDirection, String TextureID){
int side = faceDirection.getValue();
Faces[side] = true;
int index = TexturePaths.indexOf(TextureID);
if (index < 0) {
TexturePaths.add(TextureID);
index = TexturePaths.indexOf(TextureID);
}
Textureindex[side] = index;
float[] srcFace = switch (faceDirection) {
case North -> FrontFace;
case South -> BackFace;
case East -> RightFace;
case West -> LeftFace;
case Up -> TopFace;
case Down -> BottomFace;
};
System.arraycopy(srcFace, 0, VertexArray, side * 20, 20);
return this;
}
public static InitVoxelData GetVoxelModelsGenerated(){
List<VoxelModelData> models = new ArrayList<>();
List<MaterialData> materials = new ArrayList<>();
for(int i = 0; i < voxelModels.size(); i++){
models.add(voxelModels.get(i).voxelModel());
materials.addAll(voxelModels.get(i).materialData());
}
return new InitVoxelData(models,materials);
}
public CompatibleVoxelMesh CompileMesh(){
CompileMeshNoReturn();
return this;
}
public void CompileMeshNoReturn() {
List<MeshData> meshes = new ArrayList<>();
List<MaterialData> materials = new ArrayList<>();
List<String> AddedMaterials = new ArrayList<>();
int faceCount = 0;
for (int i = 0; i < 6; i++) {
if (Faces[i]) {
faceCount++;
}
}
VoxelMeshData data = new VoxelMeshData(ID, MemoryUtil.memAllocFloat(20*faceCount), MemoryUtil.memAllocInt(6*faceCount), 4, 6);
float[] vertexArray = new float[faceCount * 20];
faceCount = 0;
for(int i = 0; i < 6; i++){
if(Faces[i]){
String TextureID = "N/A_NULL";
if(Textureindex[i] >= 0 && Textureindex[i] < TexturePaths.size()) TextureID = TexturePaths.get(Textureindex[i]);
else TextureID = "resources/EngineResources/Texture/DefaultTexture.png";
if(!AddedMaterials.contains(TextureID)) {
materials.add(new MaterialData(TextureID, TextureID,DiffuseColours[i]));
AddedMaterials.add(TextureID);
}
for(int j = 0; j < 20; j++){
vertexArray[(faceCount * 20) + j] = VertexArray[(i * 20) + j];
}
if(!Objects.equals(TextureID, "N/A_NULL")){
meshes.add(new MeshData(ID + "_" + i, TextureID,faceCount * 20, 20, faceCount * 6, 6));
}
int offset = faceCount * 4;
data.indexBuffer.put(offset);
data.indexBuffer.put(offset + 1);
data.indexBuffer.put(offset + 2);
data.indexBuffer.put(offset + 2);
data.indexBuffer.put(offset + 3);
data.indexBuffer.put(offset);
faceCount++;
}
}
Logger.debug("Voxel with [{}] sides generated",faceCount);
data.indexBuffer.flip();
data.vertexBuffer.put(vertexArray).flip();
VoxelModelData model = new VoxelModelData(ID,meshes, data.vertexBuffer, data.indexBuffer);
voxelModels.add(new VoxelModelInitData(model, materials));
}
public float[] FetchFaceWithTexture(float TextureIndex, FaceDirection direction){
float[] meshData = new float[20];
this.Textureindex[direction.getValue()] = (int) TextureIndex;
switch (direction){
case North -> {
System.arraycopy(FrontFace, 0, meshData, 0, 20);
}
case South -> {
System.arraycopy(BackFace, 0, meshData, 0, 20);
}
case East -> {
System.arraycopy(RightFace, 0, meshData, 0, 20);
}
case West -> {
System.arraycopy(LeftFace, 0, meshData, 0, 20);
}
case Up -> {
System.arraycopy(TopFace, 0, meshData, 0, 20);
}
case Down -> {
System.arraycopy(BottomFace, 0, meshData, 0, 20);
}
}
return meshData;
}
public static final float[] FrontFace = new float[]{
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f
};
public static final float[] BackFace = new float[]{
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f
};
public static final float[] TopFace = new float[]{
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f
};
public static final float[] BottomFace = new float[]{
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f
};
public static final float[] LeftFace = new float[]{
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f
};
public static final float[] RightFace = new float[]{
0.5f, -0.5f, 0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f
};
}

View file

@ -56,15 +56,19 @@ public class MaterialsCache {
if(ValidTexture){ if(ValidTexture){
Logger.debug("Loading Texture [{}]",TexturePath); Logger.debug("Loading Texture [{}]",TexturePath);
Texture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB); Texture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB);
TransparentTexture = newTexture.HasTransparency(); if(newTexture == null) {
TransparentTexture = false;
TexturePath = "resources/EngineResources/Texture/DefaultTexture.png";
}
else TransparentTexture = newTexture.HasTransparency();
} else{ } else{
TexturePath = "resources/EngineResources/Texture/DefaultTexture.png";
TransparentTexture = Material.DiffuseColour().w < 1.0f; TransparentTexture = Material.DiffuseColour().w < 1.0f;
} }
VulkanMaterial newMaterial = new VulkanMaterial(Material.ID(),TransparentTexture); VulkanMaterial newMaterial = new VulkanMaterial(Material.ID(),TransparentTexture);
MaterialsMap.put(newMaterial.ID(), newMaterial); MaterialsMap.put(newMaterial.ID(), newMaterial);
Logger.trace(Material.toString()); Logger.trace(Material.toString());
data.position(Offset); Material.DiffuseColour().get(Offset,data);
Material.DiffuseColour().get(data);
Logger.debug("Set Diffuse Colour -> [{}]",Material.DiffuseColour()); Logger.debug("Set Diffuse Colour -> [{}]",Material.DiffuseColour());
data.putInt(Offset + VulkanUtils.VEC4_SIZE, ValidTexture ? 1 : 0); data.putInt(Offset + VulkanUtils.VEC4_SIZE, ValidTexture ? 1 : 0);
data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE, textureCache.GetPosition(TexturePath)); data.putInt(Offset + VulkanUtils.VEC4_SIZE + VulkanUtils.INT_SIZE, textureCache.GetPosition(TexturePath));
@ -76,6 +80,7 @@ public class MaterialsCache {
} }
data.position(0); data.position(0);
SrcBuffer.Flush(VkCtx);
SrcBuffer.UnMapMemory(VkCtx); SrcBuffer.UnMapMemory(VkCtx);
transferBuffer.RecordTransferCommand(CmdBuffer); transferBuffer.RecordTransferCommand(CmdBuffer);
CmdBuffer.EndRecording(); CmdBuffer.EndRecording();
@ -91,6 +96,7 @@ public class MaterialsCache {
} }
} }
public IndexedLinkedHashMap<String, VulkanMaterial> GetMaterialCache(){return MaterialsMap;}
public VulkanMaterial GetMaterial(String ID){return MaterialsMap.get(ID);} public VulkanMaterial GetMaterial(String ID){return MaterialsMap.get(ID);}
public VulkanBuffer GetMaterialsBuffer(){return MaterialsBuffer;} public VulkanBuffer GetMaterialsBuffer(){return MaterialsBuffer;}

View file

@ -10,10 +10,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import org.tinylog.Logger; import org.tinylog.Logger;
import java.io.BufferedInputStream; import java.io.*;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.ArrayList; import java.util.ArrayList;
@ -31,6 +28,39 @@ public class ModelsCache {
ModelsMap = new HashMap<>(); ModelsMap = new HashMap<>();
} }
public void loadVoxelModels(VulkanContext VkCtx, List<CompatibleVoxelMesh.VoxelModelData> Models, CommandPool commandPool, Queue queue){
try {
List<VulkanBuffer> StagingBufferList = new ArrayList<>();
var Command = new CommandBuffer(VkCtx, commandPool, true, true);
Command.BeginRecording();
for (CompatibleVoxelMesh.VoxelModelData modelData : Models) {
VulkanModel VKModel = new VulkanModel(modelData.ID());
ModelsMap.put(VKModel.GetID(), VKModel);
for (MeshData meshData : modelData.meshes()) {
TransferBuffer VerticesBuffers = CreateVoxelVerticesBuffer(VkCtx, meshData,modelData.vertexBuffer());
TransferBuffer IndicesBuffers = CreateVoxelIndicesBuffer(VkCtx, meshData,modelData.indexBuffer());
StagingBufferList.add(VerticesBuffers.SrcBuffer());
StagingBufferList.add(IndicesBuffers.SrcBuffer());
VerticesBuffers.RecordTransferCommand(Command);
IndicesBuffers.RecordTransferCommand(Command);
Logger.debug("Creating new Vulkan Mesh -> ID=[{}] MaterialID=[{}]",meshData.ID(),meshData.MaterialID());
VulkanMesh VkMesh = new VulkanMesh(meshData.ID(), VerticesBuffers.DstBuffer(), IndicesBuffers.DstBuffer(),
meshData.IndexSize(), meshData.MaterialID());
VKModel.GetVkMeshList().add(VkMesh);
}
}
Command.EndRecording();
Command.SubmitAndWait(VkCtx,queue);
Command.cleanup(VkCtx,commandPool);
StagingBufferList.forEach(b -> b.cleanup(VkCtx));
} catch (Exception exception){
throw new RuntimeException(exception);
}
}
public void loadModels(VulkanContext VkCtx, List<ModelData> Models, CommandPool commandPool, Queue queue){ public void loadModels(VulkanContext VkCtx, List<ModelData> Models, CommandPool commandPool, Queue queue){
try { try {
List<VulkanBuffer> StagingBufferList = new ArrayList<>(); List<VulkanBuffer> StagingBufferList = new ArrayList<>();
@ -69,6 +99,43 @@ public class ModelsCache {
} }
} }
private static TransferBuffer CreateVoxelIndicesBuffer(VulkanContext VkCtx, MeshData meshData, IntBuffer IndexBuffer) throws IOException{
int BufferSize = meshData.IndexSize();
var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
var DstBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
long MappedMemory = SrcBuffer.MapMemory(VkCtx);
IntBuffer data = MemoryUtil.memIntBuffer(MappedMemory,(int) SrcBuffer.GetRequestedSize());
IndexBuffer.rewind();
for(int i = 0; i < meshData.IndexSize(); i++){
data.put(IndexBuffer.get(meshData.OffsetIndex() + i));
}
SrcBuffer.UnMapMemory(VkCtx);
return new TransferBuffer(SrcBuffer,DstBuffer);
}
private static TransferBuffer CreateVoxelVerticesBuffer(VulkanContext VkCtx, MeshData meshData, FloatBuffer VertexBuffer) throws IOException {
Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize());
int BufferSize = meshData.VertexSize();
var SrcBuffer = new VulkanBuffer(VkCtx,BufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO,VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
var DstBuffer = new VulkanBuffer(VkCtx, BufferSize,
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO,0,0);
if (BufferSize <= 0) {
Logger.error("Computed buffer allocation size cannot be 0. SrcBuffer -> [{}] DstBuffer -> [{}]",SrcBuffer,DstBuffer);
throw new RuntimeException("Computed buffer allocation size cannot be 0. SrcBuffer -> ["+SrcBuffer+"] DstBuffer -> ["+DstBuffer+"]");
}
Logger.debug("Starting to create vertex Transfer Buffer");
long MappedMemory = SrcBuffer.MapMemory(VkCtx);
FloatBuffer data = MemoryUtil.memFloatBuffer(MappedMemory, (int) SrcBuffer.GetRequestedSize());
VertexBuffer.rewind();
for(int i = 0; i < meshData.VertexSize(); i++){
data.put(VertexBuffer.get(meshData.OffsetVertex() + i));
}
SrcBuffer.UnMapMemory(VkCtx);
return new TransferBuffer(SrcBuffer,DstBuffer);
}
private static TransferBuffer CreateVerticesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream VertexStream) throws IOException { private static TransferBuffer CreateVerticesBuffer(VulkanContext VkCtx, MeshData meshData, DataInputStream VertexStream) throws IOException {
Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize()); Logger.debug("Creating Vertices Transfer Buffer, Mesh Data -> ID=[{}] VertexSize=[{}]",meshData.ID(),meshData.VertexSize());
int BufferSize = meshData.VertexSize(); int BufferSize = meshData.VertexSize();

View file

@ -3,11 +3,12 @@ package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.GameCore;
import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene; import net.halbear.Terrain4J.EngineCore.Main.Scene.Scene;
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.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.Texture;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline;
@ -18,6 +19,7 @@ import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VertexBufferStructure;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.*; import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.*;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain.SwapChain;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils; import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.joml.Matrix4f; import org.joml.Matrix4f;
@ -32,11 +34,10 @@ import java.nio.LongBuffer;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.lwjgl.vulkan.KHRSwapchain.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
import static org.lwjgl.vulkan.KHRSynchronization2.VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR; import static org.lwjgl.vulkan.KHRSynchronization2.VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR;
import static org.lwjgl.vulkan.VK13.*; import static org.lwjgl.vulkan.VK13.*;
public class SceneRender {//dynamic rendering public class SceneRender implements SceneRenderer {//dynamic rendering
private static final String DESCRIPTOR_ID_MAT = "SCN_DESC_ID_MAT"; private static final String DESCRIPTOR_ID_MAT = "SCN_DESC_ID_MAT";
private static final String DESCRIPTOR_ID_PRJ = "SCN_DESC_ID_PRJ"; private static final String DESCRIPTOR_ID_PRJ = "SCN_DESC_ID_PRJ";
@ -49,26 +50,28 @@ public class SceneRender {//dynamic rendering
private final DescriptorSetLayout descriptorLayoutVertexUniform; private final DescriptorSetLayout descriptorLayoutVertexUniform;
private final TextureSampler textureSampler; private final TextureSampler textureSampler;
private static final int COLOUR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT;
private static final int DEPTH_FORMAT = VK_FORMAT_D16_UNORM; private static final int DEPTH_FORMAT = VK_FORMAT_D16_UNORM;
private final VkClearValue ClearValueDepth; private final VkClearValue ClearValueDepth;
private final ByteBuffer PushConstBuffer; private final ByteBuffer PushConstBuffer;
private Attachment[] AttDepth; private Attachment AttachmentDepth;
private VkRenderingAttachmentInfo[] AttInfoDepth; private Attachment AttachmentColour;
private VkRenderingAttachmentInfo AttachmentInfoDepth;
private VkClearValue ClearValueColour; private VkClearValue ClearValueColour;
private VkRenderingAttachmentInfo.Buffer[] AttachmentInfoColour; private VkRenderingAttachmentInfo.Buffer AttachmentInfoColour;
private VkRenderingInfo[] RenderInfo; private VkRenderingInfo RenderInfo;
private float R = 0f; private float R = 0.5f;
private float G = 0.5f; private float G = 0.75f;
private float B = 0.7f; private float B = 1.0f;
private boolean Rb = false; private boolean Rb = false;
private boolean Gb = true; private boolean Gb = true;
private boolean Bb = false; private boolean Bb = false;
public int Frames = 0; public int Frames = 0;
private static String LastGPULog = ""; private static String LastGPULog = "";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/shaders/scene_fragment.glsl"; private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_fragment.glsl";
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String VERTEX_SHADER_FILE_GLSL = "resources/shaders/scene_vertex.glsl"; private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/scene_vertex.glsl";
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
private final VulkanBuffer[] BufferViewMatrices; private final VulkanBuffer[] BufferViewMatrices;
private final Pipeline VkPipeline; private final Pipeline VkPipeline;
@ -76,14 +79,14 @@ public class SceneRender {//dynamic rendering
public SceneRender(VulkanContext vulkanContext){ public SceneRender(VulkanContext vulkanContext){
ClearValueColour = VkClearValue.calloc().color( ClearValueColour = VkClearValue.calloc().color(
c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f)); c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f));
//ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 1.0f)); ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f));
ClearValueDepth = VkClearValue.calloc().depthStencil(c -> c.depth(1.0f).stencil()); AttachmentColour = CreateColourAttachment(vulkanContext);
AttDepth = createDepthAttachments(vulkanContext); AttachmentDepth = CreateDepthAttachment(vulkanContext);
AttInfoDepth = createDepthAttachmentsInfo(vulkanContext, AttDepth, ClearValueDepth); AttachmentInfoDepth = CreateDepthAttachmentInfo(AttachmentDepth, ClearValueDepth);
ClearValueColour = VkClearValue.calloc().color(c->c.float32(0,R).float32(1,G).float32(2,B).float32(3,1.0f)); AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour,ClearValueColour);
AttachmentInfoColour = CreateColourAttachmentsInfo(vulkanContext,ClearValueColour); RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour, AttachmentInfoDepth);
RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttInfoDepth);
ShaderModule[] shaderModules = SceneRender.CreateShaderModules(vulkanContext); ShaderModule[] shaderModules = SceneRender.CreateShaderModules(vulkanContext);
PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE)); PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE));
@ -114,6 +117,40 @@ public class SceneRender {//dynamic rendering
Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext)); Arrays.asList(shaderModules).forEach(shaderModule -> shaderModule.CleanUp(vulkanContext));
} }
private static Attachment CreateColourAttachment(VulkanContext VkCtx){
SwapChain swapChain = VkCtx.GetSwapChain();
VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent();
return new Attachment(VkCtx, SwapChainExtent.width(), SwapChainExtent.height(), COLOUR_FORMAT,VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
}
private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue ClearValue){
return VkRenderingAttachmentInfo.calloc(1)
.sType$Default()
.imageView(attachment.GetVkImageView().GetVulkanImageView())
.imageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
.clearValue(ClearValue);
}
private static Attachment CreateDepthAttachment(VulkanContext VkCtx){
SwapChain swapChain = VkCtx.GetSwapChain();
VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent();
return new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(),
DEPTH_FORMAT,VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
}
private static VkRenderingAttachmentInfo CreateDepthAttachmentInfo(Attachment DepthAttachment, VkClearValue clearValue){
return VkRenderingAttachmentInfo.calloc()
.sType$Default()
.imageView(DepthAttachment.GetVkImageView().GetVulkanImageView())
.imageLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
.storeOp(VK_ATTACHMENT_STORE_OP_DONT_CARE)
.clearValue(clearValue);
}
private static Attachment[] createDepthAttachments(VulkanContext VkCtx){ private static Attachment[] createDepthAttachments(VulkanContext VkCtx){
SwapChain swapChain = VkCtx.GetSwapChain(); SwapChain swapChain = VkCtx.GetSwapChain();
int ImageCount = swapChain.GetImageCount(); int ImageCount = swapChain.GetImageCount();
@ -149,15 +186,14 @@ public class SceneRender {//dynamic rendering
ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader);
} }
return new ShaderModule[]{ return new ShaderModule[]{
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV), new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV,null),
new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV) new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV,null)
}; };
} }
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts){ private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts){
var vertexBufferStructure = new VertexBufferStructure(); var vertexBufferStructure = new VertexBufferStructure();
var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(), var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),COLOUR_FORMAT)
VkCtx.GetSurface().GetSurfaceFormat().ImageFormat())
.SetDepthFormat(DEPTH_FORMAT) .SetDepthFormat(DEPTH_FORMAT)
.SetPushConstantRanges( .SetPushConstantRanges(
new PushConstantsRange[]{ new PushConstantsRange[]{
@ -166,62 +202,33 @@ public class SceneRender {//dynamic rendering
}) })
.SetDescriptorSetLayouts(DescriptorSetLayouts) .SetDescriptorSetLayouts(DescriptorSetLayouts)
.BlendingIsUsed(true); .BlendingIsUsed(true);
var pipeline = new Pipeline(VkCtx, BuildInfo); var pipeline = new DefaultPipeline(VkCtx, BuildInfo);
vertexBufferStructure.cleanup(); vertexBufferStructure.cleanup();
return pipeline; return pipeline;
} }
public void UpdateColours(VulkanContext vulkanContext){
if (Gb){
if (G < 1.0f && Math.random() <0.5) G+=0.0005f;
else if (G >= 1.0f) Gb = false;
} else{
if (G >0.0f&& Math.random() <0.5) G-=0.0005f;
else if (G <= 0.0f) Gb = true;
}
if (Rb){
if (R < 1.0f&& Math.random() <0.3) R+=0.0005f;
else if (R >= 1.0f) Rb = false;
} else{
if (R >0.0f&& Math.random() <0.3) R-=0.0005f;
else if (R <= 0.0f) Rb = true;
}
if (Bb){
if (B < 1.0f&& Math.random() <0.7) B+=0.0005f;
else if (B >= 1.0f) Bb = false;
} else{
if (B >0.0f&& Math.random() <0.7) B-=0.0005f;
else if (B <= 0.0f) Bb = true;
}
//ClearValueColour = VkClearValue.calloc().color(c->c.float32(0,R).float32(1,G).float32(2,B).float32(3,1.0f));
//AttachmentInfoColour = CreateColourAttachmentsInfo(vulkanContext,ClearValueColour);
//RenderInfo = CreateRenderInfo(vulkanContext, AttachmentInfoColour, AttInfoDepth);
}
public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int ImageIndex, int CurrentFrame){ public void Render(EngineInstance engineInstance,VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache,MaterialsCache materialsCache, int CurrentFrame){
UpdateColours(vulkanContext);
try(var MemStack = MemoryStack.stackPush()){ try(var MemStack = MemoryStack.stackPush()){
SwapChain swapChain = vulkanContext.GetSwapChain();
long SwapChainImage = swapChain.GetVulkanImageView(ImageIndex).GetVulkanImage();
VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer(); VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer();
VulkanUtils.ImageBarrier(MemStack, CommandHandle, SwapChainImage, VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttachmentColour.GetVkImage().getVulkanImage(),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT); VK_ACCESS_2_NONE, VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttDepth[ImageIndex].GetVkImage().getVulkanImage(), VulkanUtils.ImageBarrier(MemStack, CommandHandle, AttachmentDepth.GetVkImage().getVulkanImage(),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_IMAGE_ASPECT_DEPTH_BIT); VK_IMAGE_ASPECT_DEPTH_BIT);
vkCmdBeginRendering(CommandHandle, RenderInfo[ImageIndex]); vkCmdBeginRendering(CommandHandle, RenderInfo);
vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipeline()); vkCmdBindPipeline(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipeline());
VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent(); Image ColourImage = AttachmentColour.GetVkImage();
int width = swapChainExtent.width(); int width = ColourImage.GetWidth();
int height = swapChainExtent.height(); int height = ColourImage.GetHeight();
var Viewport = VkViewport.calloc(1,MemStack) var Viewport = VkViewport.calloc(1,MemStack)
.x(0) .x(0)
.y(height) .y(height)
@ -239,7 +246,7 @@ public class SceneRender {//dynamic rendering
DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator(); DescriptorAllocator descriptorAllocator = vulkanContext.GetDescriptorAllocator();
LongBuffer DescriptorSets = MemStack.mallocLong(4) LongBuffer DescriptorSets = MemStack.mallocLong(4)
.put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet()) .put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ).GetVkDescriptorSet())
.put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW).GetVkDescriptorSet()) .put(1,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_VIEW, CurrentFrame).GetVkDescriptorSet())
.put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet()) .put(2,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet())
.put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet()); .put(3,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet());
vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null); vkCmdBindDescriptorSets(CommandHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, VkPipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
@ -248,12 +255,6 @@ public class SceneRender {//dynamic rendering
RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true); RenderActors(engineInstance, CommandHandle, modelsCache, materialsCache, true);
vkCmdEndRendering(CommandHandle); 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);
} }
} }
@ -294,19 +295,23 @@ public class SceneRender {//dynamic rendering
private void SetPushConstants(VkCommandBuffer CmdHandle, Matrix4f ModelMatrix, int MaterialIndex){ private void SetPushConstants(VkCommandBuffer CmdHandle, Matrix4f ModelMatrix, int MaterialIndex){
ModelMatrix.get(0,PushConstBuffer); ModelMatrix.get(0,PushConstBuffer);
PushConstBuffer.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex); PushConstBuffer.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex);
vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, PushConstBuffer.slice(0,VulkanUtils.MATRIX4X4_SIZE)); vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0,
vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE, PushConstBuffer.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE)); PushConstBuffer.slice(0,VulkanUtils.MATRIX4X4_SIZE));
vkCmdPushConstants(CmdHandle, VkPipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE,
PushConstBuffer.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE));
} }
public void Resize(EngineInstance instance, VulkanContext VkCtx){ public void Resize(EngineInstance instance, VulkanContext VkCtx){
Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free); RenderInfo.free();
Arrays.asList(AttInfoDepth).forEach(VkRenderingAttachmentInfo::free); AttachmentInfoColour.free();
Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free); AttachmentColour.CleanUp(VkCtx);
Arrays.asList(AttDepth).forEach(Attachment->Attachment.CleanUp(VkCtx)); AttachmentDepth.CleanUp(VkCtx);
AttDepth = createDepthAttachments(VkCtx); AttachmentInfoDepth.free();
AttachmentInfoColour = CreateColourAttachmentsInfo(VkCtx, ClearValueColour); AttachmentColour = CreateColourAttachment(VkCtx);
AttInfoDepth = createDepthAttachmentsInfo(VkCtx, AttDepth, ClearValueDepth); AttachmentDepth = CreateDepthAttachment(VkCtx);
RenderInfo = CreateRenderInfo(VkCtx, AttachmentInfoColour, AttInfoDepth); AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour, ClearValueColour);
AttachmentInfoDepth = CreateDepthAttachmentInfo(AttachmentDepth, ClearValueDepth);
RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour, AttachmentInfoDepth);
VulkanUtils.CopyMatrixToBuffer(VkCtx, BufferProjectionMatrix, instance.scene().GetProjection().GetProjectionMatrix(),0); VulkanUtils.CopyMatrixToBuffer(VkCtx, BufferProjectionMatrix, instance.scene().GetProjection().GetProjectionMatrix(),0);
} }
@ -322,24 +327,19 @@ public class SceneRender {//dynamic rendering
descriptorSet.SetImageArray(device,imageViews,textureSampler,0); descriptorSet.SetImageArray(device,imageViews,textureSampler,0);
} }
private static VkRenderingInfo[] CreateRenderInfo(VulkanContext vulkanContext, VkRenderingAttachmentInfo.Buffer[] ColourAttachments, VkRenderingAttachmentInfo[] DepthAttachments){ private static VkRenderingInfo CreateRenderInfo(Attachment ColourAttachment, VkRenderingAttachmentInfo.Buffer ColourAttachmentInfo, VkRenderingAttachmentInfo DepthAttachmentInfo){
SwapChain swapChain = vulkanContext.GetSwapChain(); VkRenderingInfo Result;
int ImageCount = swapChain.GetImageCount();
var Result = new VkRenderingInfo[ImageCount];
try(var MemStack = MemoryStack.stackPush()){ try(var MemStack = MemoryStack.stackPush()){
VkExtent2D Extent = swapChain.GetSwapChainExtent(); VkExtent2D Extent = VkExtent2D.calloc(MemStack);
Extent.width(ColourAttachment.GetVkImage().GetWidth());
Extent.height(ColourAttachment.GetVkImage().GetHeight());
var RenderArea = VkRect2D.calloc(MemStack).extent(Extent); var RenderArea = VkRect2D.calloc(MemStack).extent(Extent);
Result = VkRenderingInfo.calloc()
for(int i = 0; i < ImageCount; i++){ .sType$Default()
var RenderInfo = VkRenderingInfo.calloc() .renderArea(RenderArea)
.sType$Default() .layerCount(1)
.renderArea(RenderArea) .pColorAttachments(ColourAttachmentInfo)
.layerCount(1) .pDepthAttachment(DepthAttachmentInfo);
.pColorAttachments(ColourAttachments[i])
.pDepthAttachment(DepthAttachments[i]);
Result[i] = RenderInfo;
}
} }
return Result; return Result;
} }
@ -361,12 +361,12 @@ public class SceneRender {//dynamic rendering
} }
public void cleanup(VulkanContext VkCtx){ public void cleanup(VulkanContext VkCtx){
VkPipeline.CleanUp(VkCtx); VkPipeline.CleanUp(VkCtx);
Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free);
Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx)); Arrays.asList(BufferViewMatrices).forEach(buffer -> buffer.cleanup(VkCtx));
Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free); RenderInfo.free();
Arrays.asList(AttInfoDepth).forEach(VkRenderingAttachmentInfo::free); AttachmentInfoColour.free();
Arrays.asList(AttachmentInfoColour).forEach(VkRenderingAttachmentInfo.Buffer::free); AttachmentColour.CleanUp(VkCtx);
Arrays.asList(AttDepth).forEach(Attachment->Attachment.CleanUp(VkCtx)); AttachmentDepth.CleanUp(VkCtx);
AttachmentInfoDepth.free();
MemoryUtil.memFree(PushConstBuffer); MemoryUtil.memFree(PushConstBuffer);
ClearValueDepth.free(); ClearValueDepth.free();
ClearValueColour.free(); ClearValueColour.free();
@ -376,4 +376,9 @@ public class SceneRender {//dynamic rendering
descriptorLayoutVertexUniform.CleanUp(VkCtx); descriptorLayoutVertexUniform.CleanUp(VkCtx);
textureSampler.CleanUp(VkCtx); textureSampler.CleanUp(VkCtx);
} }
@Override
public Attachment GetAttachmentColour() {
return AttachmentColour;
}
} }

View file

@ -0,0 +1,24 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.DescriptorSetLayout;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.ShaderModule;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.MaterialsCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.VkModel.ModelsCache;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import org.lwjgl.vulkan.VkClearValue;
import org.lwjgl.vulkan.VkCommandBuffer;
import org.lwjgl.vulkan.VkRenderingAttachmentInfo;
public interface SceneRenderer {
public void Render(EngineInstance engineInstance, VulkanContext vulkanContext, CommandBuffer commandBuffer, ModelsCache modelsCache, MaterialsCache materialsCache, int CurrentFrame);
public void Resize(EngineInstance instance, VulkanContext VkCtx);
public void LoadMaterials(VulkanContext VkCtx, MaterialsCache materialsCache, TextureCache textureCache);
public void cleanup(VulkanContext VkCtx);
public Attachment GetAttachmentColour();
}

View file

@ -15,6 +15,7 @@ import java.nio.IntBuffer;
import java.nio.LongBuffer; import java.nio.LongBuffer;
import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck; import static net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils.vkCheck;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_B8G8R8A8_UNORM;
import static org.lwjgl.vulkan.VK13.VK_FORMAT_B8G8R8A8_SRGB; import static org.lwjgl.vulkan.VK13.VK_FORMAT_B8G8R8A8_SRGB;
public class Surface { public class Surface {
@ -52,11 +53,11 @@ public class Surface {
var SurfaceFormats = VkSurfaceFormatKHR.calloc(SurfaceFormatCount, MemStack); var SurfaceFormats = VkSurfaceFormatKHR.calloc(SurfaceFormatCount, MemStack);
vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDevice.GetPhysicalDevice(),VulkanSurface, IntPointer, SurfaceFormats), "Failed to get surface formats"); vkCheck(KHRSurface.vkGetPhysicalDeviceSurfaceFormatsKHR(PhysDevice.GetPhysicalDevice(),VulkanSurface, IntPointer, SurfaceFormats), "Failed to get surface formats");
ImageFormat = VK_FORMAT_B8G8R8A8_SRGB; ImageFormat = VK_FORMAT_B8G8R8A8_UNORM;
ColourSpace = SurfaceFormats.get(0).colorSpace(); ColourSpace = SurfaceFormats.get(0).colorSpace();
for(int i = 0; i < SurfaceFormatCount; i++){ for(int i = 0; i < SurfaceFormatCount; i++){
VkSurfaceFormatKHR SurfaceFormatKHR = SurfaceFormats.get(i); VkSurfaceFormatKHR SurfaceFormatKHR = SurfaceFormats.get(i);
if (SurfaceFormatKHR.format() == VK_FORMAT_B8G8R8A8_SRGB && SurfaceFormatKHR.colorSpace() == KHRSurface.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){ if (SurfaceFormatKHR.format() == VK_FORMAT_B8G8R8A8_UNORM && SurfaceFormatKHR.colorSpace() == KHRSurface.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR){
ImageFormat = SurfaceFormatKHR.format(); ImageFormat = SurfaceFormatKHR.format();
ColourSpace = SurfaceFormatKHR.colorSpace(); ColourSpace = SurfaceFormatKHR.colorSpace();
break; break;

View file

@ -1,10 +1,12 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen; package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain;
import net.halbear.Terrain4J.EngineCore.Display.Window; import net.halbear.Terrain4J.EngineCore.Display.Window;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Semaphore; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.GPUSynchronisation.Semaphore;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue; import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Queues.Queue;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.ImageView;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DisplayToScreen.Surface;
import org.lwjgl.system.MemoryStack; import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.*; import org.lwjgl.vulkan.*;

View file

@ -0,0 +1,192 @@
package net.halbear.Terrain4J.EngineCore.Vulkan.Structure.SwapChain;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.EmptyVertexBufferStruct;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.DefaultPipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Images.Attachment;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.Pipeline;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
import net.halbear.Terrain4J.EngineCore.Vulkan.Rendering.Shader.*;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.util.shaderc.Shaderc;
import org.lwjgl.vulkan.*;
import java.nio.LongBuffer;
import java.util.Arrays;
import static org.lwjgl.vulkan.KHRSwapchain.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
import static org.lwjgl.vulkan.KHRSynchronization2.VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.*;
public class SwapChainRender {
private static final String DESCRIPTOR_ID_ATTACHMENT = "FWD_DESC_ID_ATT";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/swap_frag.glsl";
private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv";
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/swap_vtx.glsl";
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
private final DescriptorSetLayout AttachmentDescriptorSetLayout;
private final VkClearValue ClearValueColour;
private final Pipeline pipeline;
private final TextureSampler textureSampler;
private VkRenderingAttachmentInfo.Buffer[] ColourAttachmentsInfo;
private VkRenderingInfo[] RenderInfo;
public SwapChainRender(VulkanContext VkCtx, Attachment SrcAttachment){
ClearValueColour = VkClearValue.calloc();
ClearValueColour.color(c->c.float32(0,0.0f).float32(1,0.0f).float32(2,0.0f).float32(3,0.0f));
ColourAttachmentsInfo = CreateColourAttachmentsInfo(VkCtx,ClearValueColour);
RenderInfo = CreateRenderInfo(VkCtx,ColourAttachmentsInfo);
var TextureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,VK_BORDER_COLOR_INT_OPAQUE_BLACK,1,true);
textureSampler = new TextureSampler(VkCtx,TextureSamplerInfo);
var LayoutInfo = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,0,1,VK_SHADER_STAGE_FRAGMENT_BIT);
AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx,LayoutInfo);
CreateAttachmentDescriptorSet(VkCtx,AttachmentDescriptorSetLayout,SrcAttachment,textureSampler);
ShaderModule[] shaderModules = CreateShaderModules(VkCtx);
pipeline = CreatePipeline(VkCtx,shaderModules,new DescriptorSetLayout[]{AttachmentDescriptorSetLayout});
Arrays.asList(shaderModules).forEach(s->s.CleanUp(VkCtx));
}
private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descriptorSetLayout, Attachment attachment, TextureSampler sampler){
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
Device device = VkCtx.GetDevice();
DescriptorSet descriptorSet = descriptorAllocator.AddDescriptorSets(device,DESCRIPTOR_ID_ATTACHMENT,1,descriptorSetLayout)[0];
descriptorSet.SetImage(device,attachment.GetVkImageView(),sampler,0);
}
private static VkRenderingAttachmentInfo.Buffer[] CreateColourAttachmentsInfo(VulkanContext VkCtx, VkClearValue ClearView){
SwapChain swapChain = VkCtx.GetSwapChain();
int ImageCount = swapChain.GetImageCount();
var Result = new VkRenderingAttachmentInfo.Buffer[ImageCount];
for(int i = 0; i < ImageCount; i++){
var Attachments = VkRenderingAttachmentInfo.calloc(1);
Attachments.get(0)
.sType$Default()
.imageView(swapChain.GetVulkanImageView(i).GetVulkanImageView())
.imageLayout(VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL_KHR)
.loadOp(VK_ATTACHMENT_LOAD_OP_CLEAR)
.storeOp(VK_ATTACHMENT_STORE_OP_STORE)
.clearValue(ClearView);
Result[i] = Attachments;
}
return Result;
}
private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] shaderModules, DescriptorSetLayout[] descriptorSetLayouts){
var VertexBufferStruct = new EmptyVertexBufferStruct();
var BuildInfo = new PipelineBuildInfo(shaderModules, VertexBufferStruct.GetVertexInput(),VkCtx.GetSurface().GetSurfaceFormat().ImageFormat()).SetDescriptorSetLayouts(descriptorSetLayouts).BlendingIsUsed(true);
var pipeline = new DefaultPipeline(VkCtx,BuildInfo);
VertexBufferStruct.CleanUp();
return pipeline;
}
private static VkRenderingInfo[] CreateRenderInfo(VulkanContext VkCtx, VkRenderingAttachmentInfo.Buffer[] ColourAttachments){
SwapChain swapChain = VkCtx.GetSwapChain();
int ImageCount = swapChain.GetImageCount();
var Result = new VkRenderingInfo[ImageCount];
try(var MemStack = MemoryStack.stackPush()){
VkExtent2D extent2D = swapChain.GetSwapChainExtent();
var RenderArea = VkRect2D.calloc(MemStack).extent(extent2D);
for(int i = 0; i < ImageCount; i++){
var renderingInfo = VkRenderingInfo.calloc()
.sType$Default()
.renderArea(RenderArea)
.layerCount(1)
.pColorAttachments(ColourAttachments[i]);
Result[i] = renderingInfo;
}
}
return Result;
}
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx){
if(EngineConfig.getInstance().RecompileShaders()){
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader);
}
return new ShaderModule[]{
new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV, null),
new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, null)
};
}
public void Render(VulkanContext VkCtx, CommandBuffer commandBuffer, Attachment SrcAttachment, int ImageIndex){
try(var MemStack = MemoryStack.stackPush()){
SwapChain swapChain = VkCtx.GetSwapChain();
long SwapChainImage = swapChain.GetVulkanImageView(ImageIndex).GetVulkanImage();
VkCommandBuffer CommandHandle = commandBuffer.GetVulkanCommandBuffer();
VulkanUtils.ImageBarrier(MemStack,CommandHandle,SwapChainImage,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_2_NONE,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_IMAGE_ASPECT_COLOR_BIT);
VulkanUtils.ImageBarrier(MemStack,CommandHandle,SrcAttachment.GetVkImage().getVulkanImage(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT,VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT,VK_ACCESS_2_SHADER_READ_BIT,VK_IMAGE_ASPECT_COLOR_BIT);
vkCmdBeginRendering(CommandHandle, RenderInfo[ImageIndex]);
vkCmdBindPipeline(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipeline());
VkExtent2D SwapChainExtent = swapChain.GetSwapChainExtent();
int Width = SwapChainExtent.width();
int Height = SwapChainExtent.height();
var Viewport = VkViewport.calloc(1,MemStack)
.x(0)
.y(Height)
.height(-Height)
.width(Width)
.minDepth(0.0f)
.maxDepth(1.0f);
vkCmdSetViewport(CommandHandle,0,Viewport);
var Scissor = VkRect2D.calloc(1,MemStack)
.extent(it->it.width(Width).height(Height))
.offset(it->it.x(0).y(0));
vkCmdSetScissor(CommandHandle,0,Scissor);
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
LongBuffer DescriptorSets = MemStack.mallocLong(1).put(0,descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT).GetVkDescriptorSet());
vkCmdBindDescriptorSets(CommandHandle,VK_PIPELINE_BIND_POINT_GRAPHICS,pipeline.GetVulkanPipelineLayout(),0,DescriptorSets,null);
vkCmdDraw(CommandHandle,3,1,0,0);
vkCmdEndRendering(CommandHandle);
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);
}
}
public void Resize(VulkanContext VkCtx, Attachment SrcAttachment){
Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free);
Arrays.asList(ColourAttachmentsInfo).forEach(VkRenderingAttachmentInfo.Buffer::free);
ColourAttachmentsInfo = CreateColourAttachmentsInfo(VkCtx,ClearValueColour);
RenderInfo = CreateRenderInfo(VkCtx,ColourAttachmentsInfo);
DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator();
DescriptorSet descriptorSet = descriptorAllocator.GetDescriptorSet(DESCRIPTOR_ID_ATTACHMENT);
descriptorSet.SetImage(VkCtx.GetDevice(),SrcAttachment.GetVkImageView(),textureSampler,0);
}
public void CleanUp(VulkanContext VkCtx){
textureSampler.CleanUp(VkCtx);
AttachmentDescriptorSetLayout.CleanUp(VkCtx);
pipeline.CleanUp(VkCtx);
Arrays.asList(RenderInfo).forEach(VkRenderingInfo::free);
Arrays.asList(ColourAttachmentsInfo).forEach(VkRenderingAttachmentInfo.Buffer::free);
ClearValueColour.free();
}
}

View file

@ -56,27 +56,6 @@ public class VulkanBuffer {
Buffer = LongPointer.get(0); Buffer = LongPointer.get(0);
Allocation = AllocationPointer.get(0); Allocation = AllocationPointer.get(0);
pointerBuffer = MemoryUtil.memAllocPointer(1); pointerBuffer = MemoryUtil.memAllocPointer(1);
/* var MemoryRequirements = VkMemoryRequirements.calloc(MemStack);
vkGetBufferMemoryRequirements(device.FetchVulkanDevice(), Buffer, MemoryRequirements);
var MemoryAllocation = VkMemoryAllocateInfo.calloc(MemStack)
.sType$Default()
.allocationSize(MemoryRequirements.size())
.memoryTypeIndex(VulkanUtils.MemoryTypeFromProperties(vulkanContext, MemoryRequirements.memoryTypeBits(), RequestMask));
vkCheck(vkAllocateMemory(device.FetchVulkanDevice(),MemoryAllocation,null,LongPointer),"Failed to allocate memory for Vulkan");
AllocationSize = MemoryAllocation.allocationSize();
Memory = LongPointer.get(0);
pointerBuffer = MemoryUtil.memAllocPointer(1);
if (Buffer == 0) {
Logger.error("Vulkan crash blocked: Native bufferHandle cannot be 0!");
throw new IllegalArgumentException("Vulkan crash blocked: Native bufferHandle cannot be 0!");
}
if (Memory == 0) {
Logger.error("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed.");
throw new IllegalArgumentException("Vulkan crash blocked: Native memoryHandle cannot be 0! Device out of memory or allocation failed.");
}
vkCheck(vkBindBufferMemory(device.FetchVulkanDevice(),Buffer,Memory,0),"Failed to Bind Vulkan Memory Buffer");*/
} }
} }
public void cleanup(VulkanContext vulkanContext){ public void cleanup(VulkanContext vulkanContext){

View file

@ -10,7 +10,13 @@ import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.*; import org.lwjgl.vulkan.*;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Locale; import java.util.Locale;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT; import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
@ -25,6 +31,7 @@ public class VulkanUtils {
public static final int INT_SIZE = 4; public static final int INT_SIZE = 4;
public static final int MATRIX4X4_SIZE = 16 * FLOAT_SIZE; public static final int MATRIX4X4_SIZE = 16 * FLOAT_SIZE;
public static final int VEC4_SIZE = 4 * FLOAT_SIZE; public static final int VEC4_SIZE = 4 * FLOAT_SIZE;
public static final int VEC2_SIZE = 2 * FLOAT_SIZE;
public static void CopyMatrixToBuffer(VulkanContext VkCtx, VulkanBuffer VkBuffer, Matrix4f matrix, int Offset){ public static void CopyMatrixToBuffer(VulkanContext VkCtx, VulkanBuffer VkBuffer, Matrix4f matrix, int Offset){
long MappedMemory = VkBuffer.MapMemory(VkCtx); long MappedMemory = VkBuffer.MapMemory(VkCtx);
@ -136,4 +143,24 @@ public class VulkanUtils {
throw new RuntimeException(ErrorMessage + ": " + ErrorCode + " [" + Error + "]"); throw new RuntimeException(ErrorMessage + ": " + ErrorCode + " [" + Error + "]");
} }
} }
public static InputStream convertFloatBufferToInputStream(FloatBuffer floatBuffer) {
floatBuffer.rewind();
byte[] byteArray = new byte[floatBuffer.remaining() * 4];
ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
byteBuffer.order(ByteOrder.nativeOrder());
byteBuffer.asFloatBuffer().put(floatBuffer);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
return new BufferedInputStream(byteArrayInputStream);
}
public static InputStream convertIntBufferToInputStream(IntBuffer intBuffer) {
intBuffer.rewind();
byte[] byteArray = new byte[intBuffer.remaining() * 4];
ByteBuffer byteBuffer = ByteBuffer.wrap(byteArray);
byteBuffer.order(ByteOrder.nativeOrder());
byteBuffer.asIntBuffer().put(intBuffer);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArray);
return new BufferedInputStream(byteArrayInputStream);
}
} }

View file

@ -13,14 +13,21 @@ frame_accuracy=0
throttle_on_unfocus=true throttle_on_unfocus=true
throttle_accuracy=500000000 throttle_accuracy=500000000
#event tick rate for game process #event tick rate for game process
master_tick_rate=120 master_tick_rate=240
main_thread_tickrate=120 main_thread_tickrate=120
fast_thread_tickrate=240 fast_thread_tickrate=240
cap_master_to_tickrate=false cap_master_to_tickrate=true
cap_main_to_tickrate=true cap_main_to_tickrate=true
cap_fast_to_tickrate=true cap_fast_to_tickrate=true
#Renderer Properties #Renderer Properties
#AA settings
#0=No AA
#1=FXAA
#2=MSAAx2
#3=MSAAx4
#4=MSAAx8
anti_alias_mode=0
Debug_Shaders = false Debug_Shaders = false
ShaderRecompiling = true ShaderRecompiling = true
#Vulkan Debugging toggle #Vulkan Debugging toggle
@ -34,7 +41,7 @@ PhysicalDeviceName=
#3D Projection Properties #3D Projection Properties
field_of_view=60.0f field_of_view=60.0f
z_near_plane=0.10f z_far_plane=1f
z_far_plane=1000.0f z_near_plane=10000.0f