Shadows, broke OpenGL, broke graphics settings, Exception raised when closing software

This commit is contained in:
Halbear 2026-08-30 01:06:23 +01:00
parent f7127e0878
commit 0d41f3e15b
36 changed files with 1187 additions and 219 deletions

View file

@ -0,0 +1,233 @@
#version 450
#extension GL_EXT_scalar_block_layout: require
// CREDITS: Most of the functions here have been obtained from this link: https://github.com/SaschaWillems/Vulkan
// developed by Sascha Willems, https://twitter.com/JoeyDeVriez, and licensed under the terms of the MIT License (MIT)
layout (constant_id = 0) const int SHADOW_MAP_CASCADE_COUNT = 6;
layout (constant_id = 1) const int DEBUG_SHADOWS = 0;
const float PI = 3.14159265359;
struct Light {
vec3 position;
uint directional;
float intensity;
vec3 color;
};
struct CascadeShadow {
mat4 projViewMatrix;
vec4 splitDistance;
};
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out vec4 outFragColor;
layout(set = 0, binding = 0) uniform sampler2D posSampler;
layout(set = 0, binding = 1) uniform sampler2D albedoSampler;
layout(set = 0, binding = 2) uniform sampler2D normalsSampler;
layout(set = 0, binding = 3) uniform sampler2D pbrSampler;
layout(set = 0, binding = 4) uniform sampler2DArray shadowSampler;
layout(scalar, set = 1, binding = 0) readonly buffer Lights {
Light lights[];
} lights;
layout(set = 2, binding = 0) readonly buffer Shadows {
CascadeShadow cascadeshadows[];
} shadows;
layout(scalar, set = 3, binding = 0) uniform SceneInfo {
vec3 camPos;
float ambientLightIntensity;
vec3 ambientLightColor;
uint numLights;
mat4 viewMatrix;
} sceneInfo;
float chebyshevUpperBound(vec2 moments, float t) {
// Surface is fully lit if the current fragment is before the light occluder
if (t <= moments.x)
return 1.0;
// Compute variance
float variance = moments.y - (moments.x * moments.x);
variance = max(variance, 0.00002); // Small epsilon to avoid divide by zero
// Compute probabilistic upper bound
float d = t - moments.x;
float p_max = variance / (variance + d * d);
// Reduce light bleeding
p_max = smoothstep(0.2, 1.0, p_max);
return p_max;
}
float calcVisibility(vec4 worldPosition, uint cascadeIndex) {
vec4 shadowMapPosition = shadows.cascadeshadows[cascadeIndex].projViewMatrix * worldPosition;
shadowMapPosition.xyz /= shadowMapPosition.w;
vec2 uv = vec2(
shadowMapPosition.x * 0.5 + 0.5,
shadowMapPosition.y * -0.5 + 0.5
);
float depth = shadowMapPosition.z;
if (uv.x < 0.0 || uv.x > 1.0 ||
uv.y < 0.0 || uv.y > 1.0 ||
depth < 0.0 || depth > 1.0) {
return 1.0;
}
vec2 moments = texture(shadowSampler, vec3(uv, cascadeIndex)).rg;
float visibility = chebyshevUpperBound(moments, depth);
return visibility;
}
float distributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;
float nom = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return nom / denom;
}
float geometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;
float nom = NdotV;
float denom = NdotV * (1.0 - k) + k;
return nom / denom;
}
float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = geometrySchlickGGX(NdotV, roughness);
float ggx1 = geometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
}
vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 tmpSub = light.position - worldPos;
vec3 L = normalize(tmpSub);
vec3 H = normalize(V + L);
// Calculate distance and attenuation
float distance = length(tmpSub);
float attenuation = 1.0 / (distance * distance);
float intensity = 10.0f;
vec3 radiance = light.color * light.intensity * attenuation;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) {
vec3 L = normalize(-light.position);
vec3 H = normalize(V + L);
vec3 radiance = light.color * light.intensity;
// Cook-Torrance BRDF
float NDF = distributionGGX(N, H, roughness);
float G = geometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
vec3 specular = numerator / denominator;
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metallic;
float NdotL = max(dot(N, L), 0.0);
return (kD * albedo / PI + specular) * radiance * NdotL;
}
void main() {
vec3 albedo = texture(albedoSampler, inTextCoord).rgb;
vec3 normal = texture(normalsSampler, inTextCoord).rgb;
vec4 worldPosW = texture(posSampler, inTextCoord);
vec3 worldPos = worldPosW.xyz;
vec3 pbr = texture(pbrSampler, inTextCoord).rgb;
float roughness = pbr.g;
float metallic = pbr.b;
vec3 N = normalize(normal);
vec3 V = normalize(sceneInfo.camPos - worldPos);
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo, metallic);
uint cascadeIndex = 0;
vec4 viewPos = sceneInfo.viewMatrix * worldPosW;
for (uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i) {
if (viewPos.z < shadows.cascadeshadows[i].splitDistance.x) {
cascadeIndex = i + 1;
}
}
float shadow = calcVisibility(vec4(worldPos, 1), cascadeIndex);
vec3 Lo = vec3(0.0);
for (uint i = 0; i < sceneInfo.numLights; i++) {
Light light = lights.lights[i];
if (light.directional == 1) {
Lo += calculateDirectionalLight(light, V, N, F0, albedo, metallic, roughness) * shadow;
} else {
Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness);
}
}
vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity;
outFragColor = vec4(Lo + ambient, 1.0f);
if (DEBUG_SHADOWS == 1) {
switch (cascadeIndex) {
case 0:
outFragColor.rgb *= vec3(1.0f, 0.25f, 0.25f);
break;
case 1:
outFragColor.rgb *= vec3(0.25f, 1.0f, 0.25f);
break;
case 2:
outFragColor.rgb *= vec3(0.25f, 0.25f, 1.0f);
break;
default:
outFragColor.rgb *= vec3(1.0f, 1.0f, 0.25f);
break;
}
}
if (length(normal) < 0.001) {
outFragColor = vec4(albedo,1.0f);
return;
}
}

View file

@ -1,5 +1,51 @@
#version 450 #version 450
void main() { // Keep in sync manually with Java code
const int MAX_TEXTURES = 256;
layout (location = 0) in vec2 inTextCoords;
layout (location = 1) in flat uint inMaterialIdx;
layout(location = 0) out vec2 outFragColor;
struct Material {
vec4 diffuseColor;
uint hasTexture;
uint textureIdx;
uint hasNormalMap;
uint normalMapIdx;
uint hasRoughMap;
uint roughMapIdx;
float roughnessFactor;
float metallicFactor;
};
layout(set = 1, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES];
layout(set = 2, binding = 0) readonly buffer MaterialUniform {
Material materials[];
} matUniform;
void main()
{
Material material = matUniform.materials[inMaterialIdx];
vec4 albedo;
if (material.hasTexture == 1) {
albedo = texture(textSampler[material.textureIdx], inTextCoords);
} else {
albedo = material.diffuseColor;
}
if (albedo.a < 0.5) {
discard;
}
float depth = gl_FragCoord.z;
float moment1 = depth;
float moment2 = depth * depth;
// Adjust moments to avoid light bleeding
float dx = dFdx(depth);
float dy = dFdy(depth);
moment2 += 0.25 * (dx * dx + dy * dy);
outFragColor = vec2(moment1, moment2);
} }

View file

@ -1,5 +1,29 @@
#version 450 #version 450
void main() { #define SHADOW_MAP_CASCADE_COUNT 6
layout (triangles, invocations = SHADOW_MAP_CASCADE_COUNT) in;
layout (triangle_strip, max_vertices = 3) out;
layout (location = 0) in vec2 inTextCoords[];
layout (location = 1) in flat uint inMaterialIdx[];
layout (location = 0) out vec2 outTextCoords;
layout (location = 1) out flat uint outMaterialIdx;
layout(set = 0, binding = 0) uniform ProjUniforms {
mat4 projViewMatrices[SHADOW_MAP_CASCADE_COUNT];
} projUniforms;
void main()
{
for (int i = 0; i < 3; i++)
{
outTextCoords = inTextCoords[i];
outMaterialIdx = inMaterialIdx[i];
gl_Layer = gl_InvocationID;
gl_Position = projUniforms.projViewMatrices[gl_InvocationID] * gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
} }

View file

@ -1,5 +1,23 @@
#version 450 #version 450
void main() { layout(location = 0) in vec3 entityPos;
layout(location = 1) in vec3 entityNormal;
layout(location = 2) in vec3 entityTangent;
layout(location = 3) in vec3 entityBitangent;
layout(location = 4) in vec2 entityTextCoords;
layout(push_constant) uniform matrices {
mat4 modelMatrix;
uint materialIdx;
} push_constants;
layout (location = 0) out vec2 outTextCoord;
layout (location = 1) out flat uint outMaterialIdx;
void main()
{
outTextCoord = entityTextCoords;
outMaterialIdx = push_constants.materialIdx;
gl_Position = push_constants.modelMatrix * vec4(entityPos, 1.0f);
} }

View file

@ -7,7 +7,5 @@ layout(location = 1) out vec4 outColor;
layout(set = 2, binding = 0) uniform samplerCube skyboxSampler; layout(set = 2, binding = 0) uniform samplerCube skyboxSampler;
void main() { void main() {
vec3 textureIn = texture(skyboxSampler, outTexCoords).rgb; outColor = texture(skyboxSampler, outTexCoords);// * vec4(0.0,0.05,0.1,1);
vec3 adjusted =vec3(0.0,textureIn.y/200.0,textureIn.z/150.0);
outColor = vec4(adjusted, 1.0);
} }

View file

@ -14,5 +14,5 @@ void main() {
outTexCoords = inPosition; outTexCoords = inPosition;
mat4 skyView = mat4(mat3(uboView.view)); mat4 skyView = mat4(mat3(uboView.view));
vec4 pos = uboProj.proj * skyView * vec4(inPosition, 1.0); vec4 pos = uboProj.proj * skyView * vec4(inPosition, 1.0);
gl_Position = vec4(pos.xy, 0.0, pos.w); gl_Position = vec4(pos.xy, pos.w, pos.w);
} }

View file

@ -9,8 +9,10 @@ import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiRenderer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiRenderer;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiTexture; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.GUI.GuiTexture;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRendering.LightRenderer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRendering.LightRenderer;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Attachment;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.TextureCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.PostProcessing.PostProcess; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.PostProcessing.PostProcess;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shadows.ShadowRenderer;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.SpriteRendering.SpriteRenderer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.SpriteRendering.SpriteRenderer;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer;
@ -53,6 +55,7 @@ public class VulkanRenderer implements Renderer {
private final LightRenderer lightRenderer; private final LightRenderer lightRenderer;
private final PostProcess PostProcessor; private final PostProcess PostProcessor;
private final SwapChainRender swapChainRender; private final SwapChainRender swapChainRender;
private final ShadowRenderer shadowRender;
private final GuiRenderer GuiRender; private final GuiRenderer GuiRender;
private int CurrentFrame; private int CurrentFrame;
private final VulkanContext RendererContext; private final VulkanContext RendererContext;
@ -99,12 +102,17 @@ public class VulkanRenderer implements Renderer {
} }
if(Deferred) { if(Deferred) {
sceneRender = new DeferredSceneRender(RendererContext, engineInstance); sceneRender = new DeferredSceneRender(RendererContext, engineInstance);
lightRenderer = new LightRenderer(RendererContext, sceneRender.GetMRTAttachments().GetAllAttachments()); shadowRender = new ShadowRenderer(RendererContext);
List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
attachments.add(shadowRender.getShadowAttachment());
lightRenderer = new LightRenderer(RendererContext, attachments);
PostProcessor = new PostProcess(RendererContext, lightRenderer.getAttachment()); PostProcessor = new PostProcess(RendererContext, lightRenderer.getAttachment());
} else{ } else{
sceneRender = new ForwardSceneRender(RendererContext); sceneRender = new ForwardSceneRender(RendererContext);
PostProcessor = new PostProcess(RendererContext, sceneRender.GetAttachmentColour()); PostProcessor = new PostProcess(RendererContext, sceneRender.GetAttachmentColour());
lightRenderer = null; lightRenderer = null;
shadowRender = null;
} }
spriteRenderer= new SpriteRenderer(engineInstance, RendererContext, PostProcessor.GetAttachment()); spriteRenderer= new SpriteRenderer(engineInstance, RendererContext, PostProcessor.GetAttachment());
GuiRender = new GuiRenderer(engineInstance, RendererContext, GraphicsQueue, PostProcessor.GetAttachment()); GuiRender = new GuiRenderer(engineInstance, RendererContext, GraphicsQueue, PostProcessor.GetAttachment());
@ -152,6 +160,7 @@ public class VulkanRenderer implements Renderer {
Logger.debug("Loaded {} models", Models.size()); Logger.debug("Loaded {} models", Models.size());
sceneRender.LoadMaterials(RendererContext,materialsCache,textureCache); sceneRender.LoadMaterials(RendererContext,materialsCache,textureCache);
shadowRender.loadMaterials(RendererContext, materialsCache, textureCache);
spriteRenderer.CompileSprites(RendererContext,modelsCache, textureCache); spriteRenderer.CompileSprites(RendererContext,modelsCache, textureCache);
spriteRenderer.LoadMaterials(RendererContext,materialsCache,textureCache); spriteRenderer.LoadMaterials(RendererContext,materialsCache,textureCache);
GuiRender.LoadTextures(RendererContext,initData.GuiTextures(),textureCache); GuiRender.LoadTextures(RendererContext,initData.GuiTextures(),textureCache);
@ -173,6 +182,7 @@ public class VulkanRenderer implements Renderer {
RendererContext.GetDevice().waitIdle(); RendererContext.GetDevice().waitIdle();
Logger.debug("Waiting Vulkan Context"); Logger.debug("Waiting Vulkan Context");
sceneRender.cleanup(RendererContext); sceneRender.cleanup(RendererContext);
if(shadowRender != null)shadowRender.cleanup(RendererContext);
if(lightRenderer != null)lightRenderer.cleanup(RendererContext); if(lightRenderer != null)lightRenderer.cleanup(RendererContext);
PostProcessor.CleanUp(RendererContext); PostProcessor.CleanUp(RendererContext);
swapChainRender.CleanUp(RendererContext); swapChainRender.CleanUp(RendererContext);
@ -206,7 +216,9 @@ public class VulkanRenderer implements Renderer {
RecordingStart(CommandPool, CommandBuffer); RecordingStart(CommandPool, CommandBuffer);
sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame); sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame);
lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(), CurrentFrame); shadowRender.render(engineInstance, RendererContext, CommandBuffer, modelsCache, materialsCache, CurrentFrame);
lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(), shadowRender.getShadowAttachment(), CurrentFrame,
shadowRender.getCascadeShadows(CurrentFrame));
PostProcessor.Render(RendererContext,CommandBuffer,lightRenderer.getAttachment()); PostProcessor.Render(RendererContext,CommandBuffer,lightRenderer.getAttachment());
spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame); spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame);
GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment()); GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment());
@ -280,7 +292,9 @@ public class VulkanRenderer implements Renderer {
engineInstance.scene().GetProjection().Resize(extend.width(),extend.height()); engineInstance.scene().GetProjection().Resize(extend.width(),extend.height());
sceneRender.Resize(engineInstance,RendererContext); sceneRender.Resize(engineInstance,RendererContext);
if(Deferred) { if(Deferred) {
lightRenderer.resize(RendererContext, sceneRender.GetMRTAttachments().GetAllAttachments()); List<Attachment> attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments());
attachments.add(shadowRender.getShadowAttachment());
lightRenderer.resize(RendererContext, attachments);
PostProcessor.Resize(RendererContext, lightRenderer.getAttachment()); PostProcessor.Resize(RendererContext, lightRenderer.getAttachment());
} else{ } else{
PostProcessor.Resize(RendererContext, sceneRender.GetAttachmentColour()); PostProcessor.Resize(RendererContext, sceneRender.GetAttachmentColour());

View file

@ -76,7 +76,7 @@ public class EngineConfig {
public boolean AlphaToCoverage = false; public boolean AlphaToCoverage = false;
public boolean CompatibilityMode = false; public boolean CompatibilityMode = false;
public Renderer renderer = Renderer.Forward; public Renderer renderer = Renderer.Forward;
public int ShadowMapSize = 16; public int ShadowMapSize = 4096;
public float Gamma = 0.8545f; public float Gamma = 0.8545f;
public int MaxVulkanCrashesAllowed = 10; public int MaxVulkanCrashesAllowed = 10;
public boolean RenderCollisionMesh = true; public boolean RenderCollisionMesh = true;
@ -322,7 +322,7 @@ public class EngineConfig {
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())); AAValue = (Integer.parseInt(EngineConfigVar.getOrDefault("anti_alias_mode", 1).toString()));
renderer = Integer.parseInt(EngineConfigVar.getOrDefault("Renderer", 1).toString()) == 0 ? Renderer.Forward: Renderer.Deferred; renderer = Integer.parseInt(EngineConfigVar.getOrDefault("Renderer", 1).toString()) == 0 ? Renderer.Forward: Renderer.Deferred;
ShadowMapSize = Integer.parseInt(EngineConfigVar.getOrDefault("ShadowMapSize", 16).toString()); ShadowMapSize = Integer.parseInt(EngineConfigVar.getOrDefault("ShadowMapSize", 4096).toString());
MaxVulkanCrashesAllowed = Integer.parseInt(EngineConfigVar.getOrDefault("MaxAllowedVulkanCrashes", 10).toString()); MaxVulkanCrashesAllowed = Integer.parseInt(EngineConfigVar.getOrDefault("MaxAllowedVulkanCrashes", 10).toString());
ServerPort = Integer.parseInt(EngineConfigVar.getOrDefault("server_port", 25565).toString()); ServerPort = Integer.parseInt(EngineConfigVar.getOrDefault("server_port", 25565).toString());
CompatibilityMode = Boolean.parseBoolean(EngineConfigVar.getOrDefault("compatibility_mode", false).toString()); CompatibilityMode = Boolean.parseBoolean(EngineConfigVar.getOrDefault("compatibility_mode", false).toString());
@ -385,6 +385,7 @@ public class EngineConfig {
EngineConfigVar.setProperty("MaxDescriptors","1000"); EngineConfigVar.setProperty("MaxDescriptors","1000");
EngineConfigVar.setProperty("anti_alias_mode","1"); EngineConfigVar.setProperty("anti_alias_mode","1");
EngineConfigVar.setProperty("server","false"); EngineConfigVar.setProperty("server","false");
EngineConfigVar.setProperty("ShadowMapSize","4096");
EngineConfigVar.setProperty("LoadingScreenLocation",LoadingScreenLocation); EngineConfigVar.setProperty("LoadingScreenLocation",LoadingScreenLocation);
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());

View file

@ -1,6 +1,7 @@
package net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody; package net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController; import net.halbear.Terrain4J.EngineCore.Logic.Physics.IPhysicsController;
import net.halbear.Terrain4J.EngineCore.Logic.Physics.StaticSpatialHashGrid;
import org.joml.Matrix3f; import org.joml.Matrix3f;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -80,6 +81,7 @@ public class RigidBody {
InverseMassKG = 0f; InverseMassKG = 0f;
InverseInertiaLocal.zero(); InverseInertiaLocal.zero();
IsStatic = true; IsStatic = true;
StaticSpatialHashGrid.Insert(RigidBodyID, shape.GetWorldAABB());
} else { } else {
InverseMassKG = 1.0f / mass; InverseMassKG = 1.0f / mass;
IsStatic = false; IsStatic = false;

View file

@ -31,6 +31,18 @@ public class SpatialHashGrid {
} }
} }
public static Map<Long, List<String>> Cells(){
return Cells;
}
public static List<String> GetFromKey(long key){
return Cells.getOrDefault(key, Collections.emptyList());
}
public static List<String> GetAtXYZ(int x, int y, int z){
long key = HashCell(x, y, z);
return Cells.getOrDefault(key, Collections.emptyList());
}
private static long HashCell(int x, int y, int z) { private static long HashCell(int x, int y, int z) {
long xi = ((long) x) & 0x1FFFFFL; long xi = ((long) x) & 0x1FFFFFL;
long yi = ((long) y) & 0x1FFFFFL; long yi = ((long) y) & 0x1FFFFFL;

View file

@ -5,7 +5,7 @@ import org.joml.primitives.AABBf;
import java.util.*; import java.util.*;
public class StaticSpatialHashGrid { public class StaticSpatialHashGrid {
public static float CellSize = 16f; public static float CellSize = 3f;
private static final Map<Long, List<String>> Cells = new HashMap<>(); private static final Map<Long, List<String>> Cells = new HashMap<>();
@ -31,6 +31,19 @@ public class StaticSpatialHashGrid {
} }
} }
public static Map<Long, List<String>> Cells(){
return Cells;
}
public static List<String> GetFromKey(long key){
return Cells.getOrDefault(key, Collections.emptyList());
}
public static List<String> GetAtXYZ(int x, int y, int z){
long key = HashCell(x, y, z);
return Cells.getOrDefault(key, Collections.emptyList());
}
private static long HashCell(int x, int y, int z) { private static long HashCell(int x, int y, int z) {
long xi = ((long) x) & 0x1FFFFFL; long xi = ((long) x) & 0x1FFFFFL;
long yi = ((long) y) & 0x1FFFFFL; long yi = ((long) y) & 0x1FFFFFL;

View file

@ -117,6 +117,23 @@ public class WorldPhysicsManager {
Set<String> testedPairs = new HashSet<>(); Set<String> testedPairs = new HashSet<>();
// SpatialHashGrid.Cells().forEach((key, bucket)->{
// int size = bucket.size();
// for (int i = 0; i < size; i++) {
// RigidBody a = RigidBody.RigidBodyRegister.get(bucket.get(i));
// if (a == null) continue;
// for (int j = i + 1; j < size; j++) {
// RigidBody b = RigidBody.RigidBodyRegister.get(bucket.get(j));
// if (b == null || a == b) continue;
// TryResolve(a, b, worldBounds, testedPairs);
// }
// StaticSpatialHashGrid.GetFromKey(key).forEach((id)->{
// RigidBody b = RigidBody.RigidBodyRegister.get(id);
// if (b == null || a == b) return;
// TryResolve(a, b, worldBounds, testedPairs);
// });
// }
// });
for (List<String> bucket : SpatialHashGrid.Buckets()) { for (List<String> bucket : SpatialHashGrid.Buckets()) {
int size = bucket.size(); int size = bucket.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {

View file

@ -47,13 +47,12 @@ import org.tinylog.Logger;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE; import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_F3;
public class GameCore implements GameLogic { public class GameCore implements GameLogic {
private static final float MOUSE_SENSITIVITY = 0.1f; private static final float MOUSE_SENSITIVITY = 0.1f;
private static final float MOVEMENT_SPEED = 0.01f; private static final float MOVEMENT_SPEED = 0.1f;
public static boolean LoadingLevel = false; public static boolean LoadingLevel = false;
private Vector2f LastMousePos = new Vector2f(0,0); private Vector2f LastMousePos = new Vector2f(0,0);
@ -99,19 +98,31 @@ public class GameCore implements GameLogic {
public InitData Initialise(EngineInstance engineInstance) { public InitData Initialise(EngineInstance engineInstance) {
Scene scene = (Scene) engineInstance.scene(); Scene scene = (Scene) engineInstance.scene();
List<ModelData> models = new ArrayList<>(); List<ModelData> models = new ArrayList<>();
ModelData SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json"); List<MaterialData> materials = new ArrayList<>();
List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json"); // ModelData SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json");
ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json"); // List<MaterialData> SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json");
List<MaterialData> SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json"); // ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json");
scene.AddActor(new Actor3D("Sponza1", SponzaData.ID(), new Vector3f(0,0f,-5f)).SetScale(0.1f)); // List<MaterialData> SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json");
scene.AddActor(new Actor3D("Sponza2", SponzaData1.ID(), new Vector3f(0,0f,-5f)).SetScale(0.1f)); // scene.AddActor(new Actor3D("Sponza1", SponzaData.ID(), new Vector3f(0,0f,-5f)).SetScale(0.1f));
// scene.AddActor(new Actor3D("Sponza2", SponzaData1.ID(), new Vector3f(0,0f,-5f)).SetScale(0.1f));
// ModelData treeModel = ModelLoader.LoadModel("resources/models/tree/tree.json");
// models.add(treeModel);
// Actor3D treeEntity = new Actor3D("treeEntity", treeModel.ID(), new Vector3f(0.0f, 0.0f, 0.0f));
// treeEntity.SetScale(0.05f);
// scene.AddActor(treeEntity);
// materials.addAll(ModelLoader.LoadMaterials("resources/models/tree/tree_mat.json"));
// ModelData treeModel = ModelLoader.LoadModel("resources/models/Forest/forest.json");
// models.add(treeModel);
// Actor3D treeEntity = new Actor3D("treeEntity", treeModel.ID(), new Vector3f(0.0f, 0.0f, 0.0f));
// treeEntity.SetScale(10f);
// scene.AddActor(treeEntity);
// materials.addAll(ModelLoader.LoadMaterials("resources/models/Forest/forest_mat.json"));
MelonaData = ModelLoader.LoadModel("resources/models/cube/Cube.json"); MelonaData = ModelLoader.LoadModel("resources/models/cube/Cube.json");
CubeModelID = MelonaData.ID(); CubeModelID = MelonaData.ID();
List<MaterialData> MelonaMat = ModelLoader.LoadMaterials("resources/models/cube/Cube_mat.json"); List<MaterialData> MelonaMat = ModelLoader.LoadMaterials("resources/models/cube/Cube_mat.json");
var CollisionVisualisationData = ModelLoader.LoadModel("resources/models/VisualCollision/CollisionCube.json"); var CollisionVisualisationData = ModelLoader.LoadModel("resources/models/VisualCollision/CollisionCube.json");
VisualisedCollisionActor3D.CollisionCubeModelID = CollisionVisualisationData.ID(); VisualisedCollisionActor3D.CollisionCubeModelID = CollisionVisualisationData.ID();
List<MaterialData> CollisionVisualisationMat = ModelLoader.LoadMaterials("resources/models/VisualCollision/CollisionCube_mat.json"); List<MaterialData> CollisionVisualisationMat = ModelLoader.LoadMaterials("resources/models/VisualCollision/CollisionCube_mat.json");
List<MaterialData> materials = new ArrayList<>();
var Melona = ModelLoader.LoadModel("resources/models/melona/melona.json"); var Melona = ModelLoader.LoadModel("resources/models/melona/melona.json");
List<MaterialData> MelonaMaterial = ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json"); List<MaterialData> MelonaMaterial = ModelLoader.LoadMaterials("resources/models/melona/melona_mat.json");
@ -147,10 +158,10 @@ public class GameCore implements GameLogic {
} }
boolean createOfflinePlayer = !PrimaryRuntime.IsServer && !ClientSideNetworkUtils.Connected; boolean createOfflinePlayer = !PrimaryRuntime.IsServer && !ClientSideNetworkUtils.Connected;
materials.addAll(SponzaMaterial); // materials.addAll(SponzaMaterial);
materials.addAll(SponzaMaterial1); // materials.addAll(SponzaMaterial1);
models.add(SponzaData); // models.add(SponzaData);
models.add(SponzaData1); // models.add(SponzaData1);
materials.addAll(MelonaMat); materials.addAll(MelonaMat);
materials.addAll(CollisionVisualisationMat); materials.addAll(CollisionVisualisationMat);
materials.addAll(MelonaMaterial); materials.addAll(MelonaMaterial);
@ -179,47 +190,50 @@ public class GameCore implements GameLogic {
guiTextures.add(guiTexture); guiTextures.add(guiTexture);
} }
//scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f); scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f);
//scene.GetLightingManager().SetAmbientLightIntensity(0.6f); scene.GetLightingManager().SetAmbientLightIntensity(0.3f);
scene.GetLightingManager().GetAmbientLightColour().set(0.3f, 0.35f, 0.5f); // scene.GetLightingManager().GetAmbientLightColour().set(0.3f, 0.35f, 0.5f);
scene.GetLightingManager().SetAmbientLightIntensity(0.01f); // scene.GetLightingManager().SetAmbientLightIntensity(0.075f);
//
// SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.3f), true, 2.00f); SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.3f), true, 2.00f);
SkyLight = new Light(new Vector3f(0.25f, 1.0f, 1.5f),new Vector3f(0.0f, -1.0f, 0.0f), true, 1.70f); // SkyLight = new Light(new Vector3f(0.25f, 1.0f, 1.5f),new Vector3f(0.0f, -1.0f, 0.0f), true, 6.0f);
SkyLight.SetType(Light.LightType.Directional); SkyLight.SetType(Light.LightType.Directional);
List<ILight> lights = new ArrayList<>(); List<ILight> lights = new ArrayList<>();
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-433, 445f, -424f).div(10.0f),false,3000.0f+ (float)(Math.random() * 100.0))); // lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-433, 445f, -424f).div(10.0f),false,3000.0f+ (float)(Math.random() * 100.0)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-210, 445f, 460f).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-210, 445f, 460f).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-966, 445f, 204f).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-966, 445f, 204f).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-176, 445f, 1000f).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-176, 445f, 1000f).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(777, 445f, 858).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(777, 445f, 858).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(376, 445f, -2136).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(376, 445f, -2136).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,2.0f),new Vector3f(2163, 445f, 1880).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,2.0f),new Vector3f(2163, 445f, 1880).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(3334, 445f, 2405).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(3334, 445f, 2405).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(3509, 445f, 1825).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(3509, 445f, 1825).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(3877, 445f, 3378).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(3877, 445f, 3378).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(4925, 445f, 3430).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(4925, 445f, 3430).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-2083, 445f, -1826).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f))); // lights.add(new Light(new Vector3f(1.9f+ (float)Math.random(),1.5f,1.0f),new Vector3f(-2083, 445f, -1826).div(10.0f),false,700.0f + (float)(Math.random() * 150.0f)));
//
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(2076, 410, 1272).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(2446, 465, 2303).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-842, 410, -1141).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-207, 410, -1830).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(899, 460, -2015).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(1775, 460, -3448).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(1800, 460, -4154).div(10.0f),false,1000.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1727, 410, -387).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1198, 410, -964).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1778, 410, -1502).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-2692, 333, -2109).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-2849, 333, -1724).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-2019, 410, -729).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1727, 410, -389).div(10.0f),false,100.0f));
// lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1337, 410, 122).div(10.0f),false,100.0f));
//
//
// lights.add(new Light(new Vector3f(0.75f,2.0f,0.75f),new Vector3f(1086, 425, -3375).div(10.0f),false,500.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(2076, 410, 1272).div(10.0f),false,100.0f)); //lights.add(new Light(new Vector3f(3.0f,2.25f,0.0f),new Vector3f(350.0f, 1525.0f, -420.0f),false,4000.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(2446, 465, 2303).div(10.0f),false,100.0f)); //lights.add(new Light(new Vector3f(3.0f,2.25f,0.0f),new Vector3f(400.0f, 1570.0f, -350.0f),false,1000.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-842, 410, -1141).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-207, 410, -1830).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(899, 460, -2015).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(1775, 460, -3448).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(1800, 460, -4154).div(10.0f),false,1000.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1727, 410, -387).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1198, 410, -964).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1778, 410, -1502).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-2692, 333, -2109).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-2849, 333, -1724).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-2019, 410, -729).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1727, 410, -389).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(-1337, 410, 122).div(10.0f),false,100.0f));
lights.add(new Light(new Vector3f(0.75f,2.0f,0.75f),new Vector3f(1086, 425, -3375).div(10.0f),false,500.0f));
lights.add(SkyLight); lights.add(SkyLight);
ILight[] lightArr = new ILight[lights.size()]; ILight[] lightArr = new ILight[lights.size()];
@ -232,7 +246,12 @@ public class GameCore implements GameLogic {
} }
//if(PrimaryRuntime.IsServer) { //if(PrimaryRuntime.IsServer) {
permutation.GeneratePermutationArray(5783904701859L); permutation.GeneratePermutationArray(5783904701859L);
//GenerateChunk(new Vector3i(0, 0, 0), 16); for(int x = -1; x < 2; x++){
for(int y = -1; y < 2; y++){
GenerateChunk(new Vector3i(x, 0, y), 16);
}
}
for(int i = 0; i < 20; i++){ for(int i = 0; i < 20; i++){
SpawnNewActor(engineInstance, new Vector3f(-5 + (float)Math.random() * 10,10 + (float)Math.random() * 10, -5 + (float)Math.random() * 10), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); SpawnNewActor(engineInstance, new Vector3f(-5 + (float)Math.random() * 10,10 + (float)Math.random() * 10, -5 + (float)Math.random() * 10), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1));
} }
@ -241,6 +260,18 @@ public class GameCore implements GameLogic {
Settings.UsernameBuffer.set("Player"); Settings.UsernameBuffer.set("Player");
return new InitData(models,materials,guiTextures); return new InitData(models,materials,guiTextures);
} }
public static float lightAngle = 70;
private void updateDirLight() {
float zValue = (float) Math.cos(Math.toRadians(lightAngle));
float yValue = (float) Math.sin(Math.toRadians(lightAngle));
Vector3f lightDirection = SkyLight.GetPosition();
lightDirection.x = 0;
lightDirection.y = yValue;
lightDirection.z = zValue;
lightDirection.normalize();
SkyLight.GetPosition().set(lightDirection);
}
public void Reset(){ public void Reset(){
EngineInstance instance = PrimaryRuntime.GetEngineInstance(); EngineInstance instance = PrimaryRuntime.GetEngineInstance();
@ -465,6 +496,8 @@ public class GameCore implements GameLogic {
} }
if(CumulativeFrameTime >= 16_000_000) { if(CumulativeFrameTime >= 16_000_000) {
HandleGui(engineInstance, FrameDiffNanoSeconds); HandleGui(engineInstance, FrameDiffNanoSeconds);
// lightAngle = (lightAngle + 0.15f) % 360;
// updateDirLight();
CumulativeFrameTime = 0; CumulativeFrameTime = 0;
} }
} }
@ -479,6 +512,14 @@ public class GameCore implements GameLogic {
if(input.keySinglePress(GLFW_KEY_F3)){ if(input.keySinglePress(GLFW_KEY_F3)){
Scene.GUI_MODE = (Scene.GUI_MODE + 1) % 2; Scene.GUI_MODE = (Scene.GUI_MODE + 1) % 2;
} }
if(input.keyPressed(GLFW_KEY_UP)){
lightAngle = (lightAngle + 0.5f) % 360;
updateDirLight();
}
if(input.keyPressed(GLFW_KEY_DOWN)){
lightAngle = (lightAngle - 0.5f) % 360;
updateDirLight();
}
if (input.keySinglePress(GLFW_KEY_ESCAPE)) { if (input.keySinglePress(GLFW_KEY_ESCAPE)) {
StartMenuActive = !StartMenuActive; StartMenuActive = !StartMenuActive;
StartMenu.GameStarted = StartMenuActive; StartMenu.GameStarted = StartMenuActive;

View file

@ -10,6 +10,8 @@ public class Light implements ILight{
public void SetType(LightType type) { public void SetType(LightType type) {
this.type = type; this.type = type;
if(type == LightType.Directional)
Directional = true;
} }
public enum LightType{ public enum LightType{

View file

@ -156,7 +156,7 @@ public class Scene implements IScene {
if(!PrimaryRuntime.IsServer && !RenderThread.Headless) { if(!PrimaryRuntime.IsServer && !RenderThread.Headless) {
GUIReg.put("PerformanceOverlay",new PerformanceOverlay()); GUIReg.put("PerformanceOverlay",new PerformanceOverlay());
// ActiveGUIs.add("PerformanceOverlay"); ActiveGUIs.add("PerformanceOverlay");
GUIReg.put("ChatLog",new GameChat()); GUIReg.put("ChatLog",new GameChat());
ActiveGUIs.add("ChatLog"); ActiveGUIs.add("ChatLog");
} }

View file

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

View file

@ -18,8 +18,8 @@ public class Project3D {
this.FOV = FOV; this.FOV = FOV;
OriginalNear = zNear; OriginalNear = zNear;
OriginalFar = zFar; OriginalFar = zFar;
this.ZFarPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? zNear : zFar; this.ZFarPlane = zFar;
this.ZNearPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? zFar : zNear; this.ZNearPlane = zNear;
ProjectionMatrix = new Matrix4f(); ProjectionMatrix = new Matrix4f();
Resize(Width, Height); Resize(Width, Height);
LastWidth = Width; LastWidth = Width;
@ -27,8 +27,8 @@ public class Project3D {
} }
public void SetFarPlanes(){ public void SetFarPlanes(){
ZFarPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? OriginalNear : OriginalFar; ZFarPlane =OriginalFar;
ZNearPlane = EngineConfig.getInstance().GetRenderingAPI() == EngineConfig.RenderAPI.OpenGL ? OriginalFar : OriginalNear; ZNearPlane = OriginalNear;
Resize(LastWidth,LastHeight); Resize(LastWidth,LastHeight);
} }

View file

@ -13,6 +13,8 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.I
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Pipeline; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Pipeline;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PipelineBuildInfo; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.*; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.*;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shadows.CascadeData;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shadows.CascadeShadows;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Device; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
@ -31,15 +33,18 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.lwjgl.util.vma.Vma.VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK13.*; import static org.lwjgl.vulkan.VK13.*;
public class LightRenderer { public class LightRenderer {
private static final int COLOUR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT; private static final int COLOUR_FORMAT = VK_FORMAT_R32G32B32A32_SFLOAT;
private static final String DESC_ID_ATT = "LIGHT_DESC_ID_ATT"; private static final String DESC_ID_ATT = "LIGHT_DESC_ID_ATT";
private static final String DESC_ID_SHADOW_MATRICES = "LIGHT_DESC_ID_SHADOW_MATRICES";
private static final String DESC_ID_LIGHTS = "LIGHT_DESC_ID_LIGHTS"; private static final String DESC_ID_LIGHTS = "LIGHT_DESC_ID_LIGHTS";
private static final String DESC_ID_SCENE = "LIGHT_DESC_ID_SCENE "; private static final String DESC_ID_SCENE = "LIGHT_DESC_ID_SCENE ";
private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_frag.glsl"; private static final String FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_with_shadows_frag.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/EngineResources/shaders/lighting_vertex.glsl"; private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_vertex.glsl";
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
@ -53,8 +58,10 @@ public class LightRenderer {
private VkRenderingInfo RenderInfo; private VkRenderingInfo RenderInfo;
private final VulkanBuffer[] LightBuffer; private final VulkanBuffer[] LightBuffer;
private final VulkanBuffer[] SceneBuffer; private final VulkanBuffer[] SceneBuffer;
private final LightSpecConsts lightSpecConsts;
private final DescriptorSetLayout SceneDescriptorSetLayout; private final DescriptorSetLayout SceneDescriptorSetLayout;
private final DescriptorSetLayout StorageDescriptorSetLayout; private final DescriptorSetLayout StorageDescriptorSetLayout;
private final VulkanBuffer[] shadowMatrices;
public LightRenderer(VulkanContext VkCtx, List<Attachment> attachments){ public LightRenderer(VulkanContext VkCtx, List<Attachment> attachments){
ClearValueColour = VkClearValue.calloc().color( ClearValueColour = VkClearValue.calloc().color(
@ -64,18 +71,18 @@ public class LightRenderer {
AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour, ClearValueColour); AttachmentInfoColour = CreateColourAttachmentInfo(AttachmentColour, ClearValueColour);
RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour); RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour);
ShaderModule[] shaderModules = CreateShaderModules(VkCtx); lightSpecConsts = new LightSpecConsts();
ShaderModule[] shaderModules = CreateShaderModules(VkCtx, lightSpecConsts);
var textureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT, var textureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true); VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true);
textureSampler = new TextureSampler(VkCtx, textureSamplerInfo); textureSampler = new TextureSampler(VkCtx, textureSamplerInfo);
int numAttachments = attachments.size(); int numAttachments = attachments.size();
DescriptorSetLayout.LayoutInformation[] descSetLayouts = new DescriptorSetLayout.LayoutInformation[numAttachments]; DescriptorSetLayout.LayoutInformation[] descSetLayouts = new DescriptorSetLayout.LayoutInformation[numAttachments + 1];
for (int i = 0; i < numAttachments; i++) { for (int i = 0; i < numAttachments + 1; i++) {
descSetLayouts[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i, 1, VK_SHADER_STAGE_FRAGMENT_BIT); descSetLayouts[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
} }
AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, descSetLayouts); AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, descSetLayouts);
CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, attachments, textureSampler); CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, attachments, textureSampler);
StorageDescriptorSetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, StorageDescriptorSetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1,
@ -86,16 +93,32 @@ public class LightRenderer {
SceneDescriptorSetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, 1, SceneDescriptorSetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, 1,
VK_SHADER_STAGE_FRAGMENT_BIT)); VK_SHADER_STAGE_FRAGMENT_BIT));
buffSize = VulkanUtils.VEC3_SIZE * 2 + VulkanUtils.FLOAT_SIZE + VulkanUtils.INT_SIZE; buffSize = VulkanUtils.VEC3_SIZE * 2 + VulkanUtils.FLOAT_SIZE + VulkanUtils.INT_SIZE + VulkanUtils.MATRIX4X4_SIZE;
SceneBuffer = VulkanUtils.CreateHostVisibleBuffers(VkCtx, buffSize, VulkanUtils.MAX_IN_FLIGHT, SceneBuffer = VulkanUtils.CreateHostVisibleBuffers(VkCtx, buffSize, VulkanUtils.MAX_IN_FLIGHT,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESC_ID_SCENE, SceneDescriptorSetLayout); VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESC_ID_SCENE, SceneDescriptorSetLayout);
shadowMatrices = CreateShadowMatrixBuffers(VkCtx, StorageDescriptorSetLayout);
pipeline = createPipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, StorageDescriptorSetLayout, pipeline = createPipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, StorageDescriptorSetLayout,
SceneDescriptorSetLayout}); StorageDescriptorSetLayout, SceneDescriptorSetLayout});
Logger.debug("Light Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline()); Logger.debug("Light Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline());
Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VkCtx)); Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VkCtx));
} }
private static VulkanBuffer[] CreateShadowMatrixBuffers(VulkanContext vkCtx, DescriptorSetLayout layout) {
int numBuffs = VulkanUtils.MAX_IN_FLIGHT;
VulkanBuffer[] buffers = new VulkanBuffer[numBuffs];
Device device = vkCtx.GetDevice();
DescriptorSet[] descSets = vkCtx.GetDescriptorAllocator().AddDescriptorSets(device, DESC_ID_SHADOW_MATRICES, numBuffs, layout);
for (int i = 0; i < numBuffs; i++) {
long buffSize = (long) (VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.VEC4_SIZE) * SceneLightingManager.SHADOW_MAP_CASCADE_COUNT;
buffers[i] = new VulkanBuffer(vkCtx, buffSize,
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE,
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
descSets[i].SetBuffer(device, buffers[i], buffers[i].GetRequestedSize(),
layout.GetLayoutInfo().Binding(), layout.GetLayoutInfo().DescriptorType());
}
return buffers;
}
private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descSetLayout, List<Attachment> attachments, private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descSetLayout, List<Attachment> attachments,
TextureSampler sampler) { TextureSampler sampler) {
DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator(); DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator();
@ -110,7 +133,7 @@ public class LightRenderer {
SwapChain swapChain = VkCtx.GetSwapChain(); SwapChain swapChain = VkCtx.GetSwapChain();
VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent(); VkExtent2D swapChainExtent = swapChain.GetSwapChainExtent();
return new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(), return new Attachment(VkCtx, swapChainExtent.width(), swapChainExtent.height(),
COLOUR_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); COLOUR_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,1);
} }
private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue clearValue) { private static VkRenderingAttachmentInfo.Buffer CreateColourAttachmentInfo(Attachment attachment, VkClearValue clearValue) {
@ -153,19 +176,19 @@ public class LightRenderer {
return result; return result;
} }
private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx) { private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, LightSpecConsts lightSpecConsts) {
if (EngineConfig.getInstance().RecompileShaders()) { if (EngineConfig.getInstance().RecompileShaders()) {
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
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, null), 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), new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, lightSpecConsts.getSpecInfo()),
}; };
} }
public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments,int CurrentFrame) { public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments,Attachment shadowAttachment, int CurrentFrame, CascadeShadows cascadeShadows) {
try (var stack = MemoryStack.stackPush()) { try (var stack = MemoryStack.stackPush()) {
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer(); VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
@ -176,7 +199,6 @@ public class LightRenderer {
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
List<Attachment> attachments = mrtAttachments.GetColourAttachments(); List<Attachment> attachments = mrtAttachments.GetColourAttachments();
// Logger.debug("Colour Attachments -> \n1: [{}]\n 2:[{}] \n3:[{}]\n 4:[{}]",attachments.get(0),attachments.get(1),attachments.get(2),attachments.get(3));
int numAttachments = attachments.size(); int numAttachments = attachments.size();
for (int i = 0; i < numAttachments; i++) { for (int i = 0; i < numAttachments; i++) {
Attachment attachment = attachments.get(i); Attachment attachment = attachments.get(i);
@ -187,11 +209,19 @@ public class LightRenderer {
VK_IMAGE_ASPECT_COLOR_BIT); VK_IMAGE_ASPECT_COLOR_BIT);
} }
VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(), VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(),
VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_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_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_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT,
VK_IMAGE_ASPECT_DEPTH_BIT); VK_IMAGE_ASPECT_DEPTH_BIT);
VulkanUtils.ImageBarrier(stack, cmdHandle, shadowAttachment.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);
UpdateCascadeShadowMatrices(VkCtx, cascadeShadows, CurrentFrame);
vkCmdBeginRendering(cmdHandle, RenderInfo); vkCmdBeginRendering(cmdHandle, RenderInfo);
vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipeline()); vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipeline());
@ -215,10 +245,11 @@ public class LightRenderer {
vkCmdSetScissor(cmdHandle, 0, scissor); vkCmdSetScissor(cmdHandle, 0, scissor);
DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator(); DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator();
LongBuffer descriptorSets = stack.mallocLong(3) LongBuffer descriptorSets = stack.mallocLong(4)
.put(0, descAllocator.GetDescriptorSet(DESC_ID_ATT).GetVkDescriptorSet()) .put(0, descAllocator.GetDescriptorSet(DESC_ID_ATT).GetVkDescriptorSet())
.put(1, descAllocator.GetDescriptorSet(DESC_ID_LIGHTS, CurrentFrame).GetVkDescriptorSet()) .put(1, descAllocator.GetDescriptorSet(DESC_ID_LIGHTS, CurrentFrame).GetVkDescriptorSet())
.put(2, descAllocator.GetDescriptorSet(DESC_ID_SCENE, CurrentFrame).GetVkDescriptorSet()); .put(2, descAllocator.GetDescriptorSet(DESC_ID_SHADOW_MATRICES, CurrentFrame).GetVkDescriptorSet())
.put(3, descAllocator.GetDescriptorSet(DESC_ID_SCENE, CurrentFrame).GetVkDescriptorSet());
IScene scene = engineInstance.scene(); IScene scene = engineInstance.scene();
UpdateSceneInfo(VkCtx, scene, CurrentFrame); UpdateSceneInfo(VkCtx, scene, CurrentFrame);
UpdateLights(VkCtx, scene, CurrentFrame); UpdateLights(VkCtx, scene, CurrentFrame);
@ -231,6 +262,22 @@ public class LightRenderer {
} }
} }
private void UpdateCascadeShadowMatrices(VulkanContext vkCtx, CascadeShadows cascadeShadows, int currentFrame) {
VulkanBuffer buff = shadowMatrices[currentFrame];
long mappedMemory = buff.MapMemory(vkCtx);
ByteBuffer dataBuff = MemoryUtil.memByteBuffer(mappedMemory, (int) buff.GetRequestedSize());
int offset = 0;
List<CascadeData> cascadeDataList = cascadeShadows.GetCascadeData();
int numCascades = cascadeDataList.size();
for (int i = 0; i < numCascades; i++) {
CascadeData cascadeData = cascadeDataList.get(i);
cascadeData.GetProjViewMatrix().get(offset, dataBuff);
dataBuff.putFloat(offset + VulkanUtils.MATRIX4X4_SIZE, cascadeData.GetSplitDistance());
offset += VulkanUtils.MATRIX4X4_SIZE + VulkanUtils.VEC4_SIZE;
}
buff.UnMapMemory(vkCtx);
}
public void UpdateSceneInfo(VulkanContext VkCtx, IScene scene, int CurrentFrame){ public void UpdateSceneInfo(VulkanContext VkCtx, IScene scene, int CurrentFrame){
VulkanBuffer buffer = SceneBuffer[CurrentFrame]; VulkanBuffer buffer = SceneBuffer[CurrentFrame];
long MappedMemory = buffer.MapMemory(VkCtx); long MappedMemory = buffer.MapMemory(VkCtx);
@ -249,6 +296,10 @@ public class LightRenderer {
ILight[] lights = scene.GetLightingManager().GetLights(); ILight[] lights = scene.GetLightingManager().GetLights();
int LightCount = lights != null ? lights.length : 0; int LightCount = lights != null ? lights.length : 0;
dataBuffer.putInt(Offset, LightCount); dataBuffer.putInt(Offset, LightCount);
Offset += VulkanUtils.INT_SIZE;
scene.GetCamera().GetViewMatrix().get(Offset, dataBuffer);
buffer.UnMapMemory(VkCtx); buffer.UnMapMemory(VkCtx);
} }
public void UpdateLights(VulkanContext VkCtx, IScene scene, int CurrentFrame){ public void UpdateLights(VulkanContext VkCtx, IScene scene, int CurrentFrame){
@ -291,11 +342,13 @@ public class LightRenderer {
public void cleanup(VulkanContext VkCtx) { public void cleanup(VulkanContext VkCtx) {
StorageDescriptorSetLayout.CleanUp(VkCtx); StorageDescriptorSetLayout.CleanUp(VkCtx);
Arrays.asList(LightBuffer).forEach(b -> b.cleanup(VkCtx)); Arrays.asList(LightBuffer).forEach(b -> b.cleanup(VkCtx));
Arrays.asList(shadowMatrices).forEach(b -> b.cleanup(VkCtx));
SceneDescriptorSetLayout.CleanUp(VkCtx); SceneDescriptorSetLayout.CleanUp(VkCtx);
Arrays.asList(SceneBuffer).forEach(b -> b.cleanup(VkCtx)); Arrays.asList(SceneBuffer).forEach(b -> b.cleanup(VkCtx));
pipeline.CleanUp(VkCtx); pipeline.CleanUp(VkCtx);
AttachmentDescriptorSetLayout.CleanUp(VkCtx); AttachmentDescriptorSetLayout.CleanUp(VkCtx);
textureSampler.CleanUp(VkCtx); textureSampler.CleanUp(VkCtx);
lightSpecConsts.cleanup();
RenderInfo.free(); RenderInfo.free();
AttachmentColour.CleanUp(VkCtx); AttachmentColour.CleanUp(VkCtx);
AttachmentInfoColour.free(); AttachmentInfoColour.free();

View file

@ -0,0 +1,56 @@
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.DeferredRendering;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Main.Scene.SceneLightingManager;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.vulkan.VkSpecializationInfo;
import org.lwjgl.vulkan.VkSpecializationMapEntry;
import java.nio.ByteBuffer;
public class LightSpecConsts {
private final ByteBuffer data;
private final VkSpecializationMapEntry.Buffer specEntryMap;
private final VkSpecializationInfo specInfo;
public LightSpecConsts() {
var engCfg = EngineConfig.getInstance();
data = MemoryUtil.memAlloc(VulkanUtils.INT_SIZE * 2);
data.putInt(SceneLightingManager.SHADOW_MAP_CASCADE_COUNT);
data.putInt(engCfg.DebugShaders() ? 1 : 0);
data.flip();
specEntryMap = VkSpecializationMapEntry.calloc(2);
int offset = 0;
int pos = 0;
int size = VulkanUtils.INT_SIZE;
specEntryMap.get(pos)
.constantID(pos)
.size(size)
.offset(offset);
offset += size;
pos++;
size = VulkanUtils.INT_SIZE;
specEntryMap.get(pos)
.constantID(pos)
.size(size)
.offset(offset);
specInfo = VkSpecializationInfo.calloc();
specInfo.pData(data)
.pMapEntries(specEntryMap);
}
public void cleanup() {
MemoryUtil.memFree(specEntryMap);
specInfo.free();
MemoryUtil.memFree(data);
}
public VkSpecializationInfo getSpecInfo() {
return specInfo;
}
}

View file

@ -28,18 +28,18 @@ public class MultiRenderTargetAttachments {
ColourAttachments = new ArrayList<>(); ColourAttachments = new ArrayList<>();
//Position //Position
var Attachment = new Attachment(VkCtx, Width, Height, POSITION_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); var Attachment = new Attachment(VkCtx, Width, Height, POSITION_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1);
ColourAttachments.add(Attachment); ColourAttachments.add(Attachment);
//albedo //albedo
Attachment = new Attachment(VkCtx, Width, Height, ALBEDO_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); Attachment = new Attachment(VkCtx, Width, Height, ALBEDO_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1);
ColourAttachments.add(Attachment); ColourAttachments.add(Attachment);
//Normals //Normals
Attachment = new Attachment(VkCtx, Width, Height, NORMAL_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); Attachment = new Attachment(VkCtx, Width, Height, NORMAL_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1);
ColourAttachments.add(Attachment); ColourAttachments.add(Attachment);
//PBR //PBR
Attachment = new Attachment(VkCtx, Width, Height, PBR_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); Attachment = new Attachment(VkCtx, Width, Height, PBR_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1);
ColourAttachments.add(Attachment); ColourAttachments.add(Attachment);
DepthAttachment = new Attachment(VkCtx, Width, Height, DEPTH_FORMAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); DepthAttachment = new Attachment(VkCtx, Width, Height, DEPTH_FORMAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 1);
} }
public int GetWidth(){return Width;} public int GetWidth(){return Width;}

View file

@ -67,10 +67,11 @@ public class DefaultPipeline implements Pipeline {
.viewportCount(1) .viewportCount(1)
.scissorCount(1); .scissorCount(1);
var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack) var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack)
.sType(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO) .sType$Default()
.polygonMode(VK_POLYGON_MODE_FILL) .polygonMode(VK_POLYGON_MODE_FILL)
.cullMode(VK_CULL_MODE_NONE) .cullMode(VK_CULL_MODE_NONE)
.frontFace(VK_FRONT_FACE_CLOCKWISE) .frontFace(VK_FRONT_FACE_CLOCKWISE)
.depthClampEnable(BuildInfo.DepthClamp())
.lineWidth(1.0f); .lineWidth(1.0f);
int sampleCount = EngineConfig.getInstance().GetRenderSampleCount(); int sampleCount = EngineConfig.getInstance().GetRenderSampleCount();
var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack) var MultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.calloc(MemStack)
@ -88,7 +89,7 @@ public class DefaultPipeline implements Pipeline {
.sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) .sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO)
.depthTestEnable(BuildInfo.GetDepthTest()) .depthTestEnable(BuildInfo.GetDepthTest())
.depthWriteEnable(BuildInfo.performDepthWrite()) .depthWriteEnable(BuildInfo.performDepthWrite())
.depthCompareOp(VK_COMPARE_OP_GREATER_OR_EQUAL) .depthCompareOp(VK_COMPARE_OP_LESS_OR_EQUAL)
.depthBoundsTestEnable(false) .depthBoundsTestEnable(false)
.stencilTestEnable(false); .stencilTestEnable(false);
} }

View file

@ -9,24 +9,85 @@ public class Attachment {
private final Image VkImage; private final Image VkImage;
private final ImageView VkImageView; private final ImageView VkImageView;
private boolean DepthAttachment; private boolean DepthAttachment;
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage, boolean MultiSamples){
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){
var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format).SampleCount(EngineConfig.getInstance().GetRenderSampleCount()); var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format).SampleCount(EngineConfig.getInstance().GetRenderSampleCount());
int AspectMask = 0; int aspectMask = 0;
if((Usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) > 0){ if ((Usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) > 0) {
AspectMask = VK_IMAGE_ASPECT_COLOR_BIT; aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT); ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
DepthAttachment = false; DepthAttachment = false;
} }
if((Usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) > 0){ if ((Usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) > 0) {
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT); ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT);
AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
DepthAttachment = true; DepthAttachment = true;
} }
int layers = 1;
if (layers > 0) {
ImageData.ArrayLayers(layers);
}
VkImage = new Image(VkCtx, ImageData); VkImage = new Image(VkCtx, ImageData);
var ImageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(AspectMask);
VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), ImageViewData,DepthAttachment); var imageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(aspectMask);
if (layers > 1) {
imageViewData.ViewType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
imageViewData.LayerCount(layers);
}
VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), imageViewData, DepthAttachment);
}
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage){
var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format).SampleCount(VK_SAMPLE_COUNT_1_BIT);
int aspectMask = 0;
if ((Usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) > 0) {
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
DepthAttachment = false;
}
if ((Usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) > 0) {
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT);
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
DepthAttachment = true;
}
int layers = 1;
if (layers > 0) {
ImageData.ArrayLayers(layers);
}
VkImage = new Image(VkCtx, ImageData);
var imageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(aspectMask);
if (layers > 1) {
imageViewData.ViewType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
imageViewData.LayerCount(layers);
}
VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), imageViewData, DepthAttachment);
}
public Attachment(VulkanContext VkCtx, int Width, int Height, int Format, int Usage,int layers){
var ImageData = new Image.ImageData().Width(Width).Height(Height).Format(Format).SampleCount(VK_SAMPLE_COUNT_1_BIT);
int aspectMask = 0;
if ((Usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) > 0) {
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
DepthAttachment = false;
}
if ((Usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) > 0) {
ImageData.Usage(Usage | VK_IMAGE_USAGE_SAMPLED_BIT);
aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
DepthAttachment = true;
}
if (layers > 0) {
ImageData.ArrayLayers(layers);
}
VkImage = new Image(VkCtx, ImageData);
var imageViewData = new ImageView.ImageViewData().Format(VkImage.GetFormat()).AspectMask(aspectMask);
if (layers > 1) {
imageViewData.ViewType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
imageViewData.LayerCount(layers);
}
VkImageView = new ImageView(VkCtx.GetDevice(), VkImage.getVulkanImage(), imageViewData, DepthAttachment);
} }
public Image GetVkImage(){return VkImage;} public Image GetVkImage(){return VkImage;}

View file

@ -14,6 +14,7 @@ public class PipelineBuildInfo {
private DescriptorSetLayout[] DescriptorSetLayouts; private DescriptorSetLayout[] DescriptorSetLayouts;
private boolean useBlend; private boolean useBlend;
private boolean DepthWrite = true; private boolean DepthWrite = true;
private boolean DepthClamp = false;
private boolean DepthTest = true; private boolean DepthTest = true;
private boolean DualPass = false; private boolean DualPass = false;
private boolean alphaToCoverage = false; private boolean alphaToCoverage = false;
@ -27,6 +28,13 @@ public class PipelineBuildInfo {
DepthFormat = VK_FORMAT_UNDEFINED; DepthFormat = VK_FORMAT_UNDEFINED;
useBlend = true; useBlend = true;
} }
public boolean DepthClamp() {
return DepthClamp;
}
public PipelineBuildInfo SetDepthClamp(boolean depthClamp) {
this.DepthClamp = depthClamp;
return this;
}
public PipelineBuildInfo SetBlendingMethod(int in){ public PipelineBuildInfo SetBlendingMethod(int in){
BlendingMethod = in; BlendingMethod = in;

View file

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

View file

@ -1,9 +1,70 @@
package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shadows; package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shadows;
import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig;
import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance;
import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext;
import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3D;
import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene;
import net.halbear.Terrain4J.EngineCore.Main.Scene.SceneLightingManager;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.DefaultPipeline;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Attachment;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ITexture;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.Texture;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.TextureCache;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Pipeline;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PipelineBuildInfo;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.PushConstantsRange;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.*;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VertexBufferStructure;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel.*;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.CommandBuffer;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Device;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ImageView;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer;
import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils;
import org.joml.Matrix4f;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.shaderc.Shaderc;
import org.lwjgl.vulkan.*;
import org.tinylog.Logger;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_D32_SFLOAT; import java.nio.ByteBuffer;
import static org.lwjgl.vulkan.VK10.VK_FORMAT_R32G32_SFLOAT; import java.nio.LongBuffer;
import java.util.Arrays;
import java.util.List;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK10.VK_ATTACHMENT_LOAD_OP_CLEAR;
import static org.lwjgl.vulkan.VK10.VK_ATTACHMENT_STORE_OP_DONT_CARE;
import static org.lwjgl.vulkan.VK10.VK_ATTACHMENT_STORE_OP_STORE;
import static org.lwjgl.vulkan.VK10.VK_BORDER_COLOR_INT_OPAQUE_BLACK;
import static org.lwjgl.vulkan.VK10.VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
import static org.lwjgl.vulkan.VK10.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
import static org.lwjgl.vulkan.VK10.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
import static org.lwjgl.vulkan.VK10.VK_IMAGE_ASPECT_COLOR_BIT;
import static org.lwjgl.vulkan.VK10.VK_IMAGE_ASPECT_DEPTH_BIT;
import static org.lwjgl.vulkan.VK10.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
import static org.lwjgl.vulkan.VK10.VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
import static org.lwjgl.vulkan.VK10.VK_IMAGE_LAYOUT_UNDEFINED;
import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
import static org.lwjgl.vulkan.VK10.VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
import static org.lwjgl.vulkan.VK10.VK_INDEX_TYPE_UINT32;
import static org.lwjgl.vulkan.VK10.VK_PIPELINE_BIND_POINT_GRAPHICS;
import static org.lwjgl.vulkan.VK10.VK_SAMPLER_ADDRESS_MODE_REPEAT;
import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_FRAGMENT_BIT;
import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_GEOMETRY_BIT;
import static org.lwjgl.vulkan.VK10.VK_SHADER_STAGE_VERTEX_BIT;
import static org.lwjgl.vulkan.VK10.vkCmdBindDescriptorSets;
import static org.lwjgl.vulkan.VK10.vkCmdBindIndexBuffer;
import static org.lwjgl.vulkan.VK10.vkCmdBindPipeline;
import static org.lwjgl.vulkan.VK10.vkCmdBindVertexBuffers;
import static org.lwjgl.vulkan.VK10.vkCmdDrawIndexed;
import static org.lwjgl.vulkan.VK10.vkCmdPushConstants;
import static org.lwjgl.vulkan.VK10.vkCmdSetScissor;
import static org.lwjgl.vulkan.VK10.vkCmdSetViewport;
import static org.lwjgl.vulkan.VK12.VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL;
import static org.lwjgl.vulkan.VK13.*;
public class ShadowRenderer { public class ShadowRenderer {
public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT; public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT;
@ -19,4 +80,281 @@ public class ShadowRenderer {
private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/shadow_vertex.glsl"; private static final String VERTEX_SHADER_FILE_GLSL = "resources/EngineResources/shaders/shadow_vertex.glsl";
private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; private static final String VERTEX_SHADER_FILE_SPV = VERTEX_SHADER_FILE_GLSL + ".spv";
private final CascadeShadows[] cascadeShadows;
private final VkClearValue ClearValueColour;
private final VkClearValue ClearValueDepth;
private final Attachment colorAttachment;
private final VkRenderingAttachmentInfo.Buffer colorAttachmentInfo;
private final Attachment depthAttachment;
private final VkRenderingAttachmentInfo depthAttachmentInfo;
private final DescriptorSetLayout descLayoutFrgStorage;
private final Pipeline pipeline;
private final VulkanBuffer[] prjBuffers;
private final ByteBuffer pushConstBuff;
private final VkRenderingInfo renderingInfo;
private final DescriptorSetLayout textDescriptorSetLayout;
private final TextureSampler textureSampler;
private final DescriptorSetLayout uniformGeomDescriptorSetLayout;
public ShadowRenderer(VulkanContext VulkanContext) {
ClearValueColour = VkClearValue.calloc().color(
c -> c.float32(0, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f));
ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 1.0f));
depthAttachment = createDepthAttachment(VulkanContext);
depthAttachmentInfo = createDepthAttachmentInfo(depthAttachment, ClearValueDepth);
colorAttachment = createColorAttachment(VulkanContext);
colorAttachmentInfo = createColorAttachmentInfo(colorAttachment, ClearValueColour);
pushConstBuff = MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE);
renderingInfo = createRenderInfo(colorAttachmentInfo, depthAttachmentInfo);
ShaderModule[] shaderModules = createShaderModules(VulkanContext);
uniformGeomDescriptorSetLayout = new DescriptorSetLayout(VulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
0, 1, VK_SHADER_STAGE_GEOMETRY_BIT));
long buffSize = (long) VulkanUtils.MATRIX4X4_SIZE * SceneLightingManager.SHADOW_MAP_CASCADE_COUNT;
prjBuffers = VulkanUtils.CreateHostVisibleBuffers(VulkanContext, buffSize, VulkanUtils.MAX_IN_FLIGHT,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, DESCRIPTOR_ID_PRJ, uniformGeomDescriptorSetLayout);
descLayoutFrgStorage = new DescriptorSetLayout(VulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
0, 1, VK_SHADER_STAGE_FRAGMENT_BIT));
var textureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT,
VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true);
textureSampler = new TextureSampler(VulkanContext, textureSamplerInfo);
textDescriptorSetLayout = new DescriptorSetLayout(VulkanContext, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
0, TextureCache.MAX_TEXTURES, VK_SHADER_STAGE_FRAGMENT_BIT));
pipeline = createPipeline(VulkanContext, shaderModules, new DescriptorSetLayout[]{uniformGeomDescriptorSetLayout, textDescriptorSetLayout,
descLayoutFrgStorage});
Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VulkanContext));
cascadeShadows = new CascadeShadows[VulkanUtils.MAX_IN_FLIGHT];
for (int i = 0; i < VulkanUtils.MAX_IN_FLIGHT; i++) {
cascadeShadows[i] = new CascadeShadows();
}
}
private static Attachment createColorAttachment(VulkanContext VulkanContext) {
int shadowMapSize = EngineConfig.getInstance().GetShadowMapSize();
return new Attachment(VulkanContext, shadowMapSize, shadowMapSize,
ATTACHMENT_FORMATT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, SceneLightingManager.SHADOW_MAP_CASCADE_COUNT);
}
private static VkRenderingAttachmentInfo.Buffer createColorAttachmentInfo(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 Attachment createDepthAttachment(VulkanContext VulkanContext) {
int shadowMapSize = EngineConfig.getInstance().GetShadowMapSize();
return new Attachment(VulkanContext, shadowMapSize, shadowMapSize,
DEPTH_FORMAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, SceneLightingManager.SHADOW_MAP_CASCADE_COUNT);
}
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 Pipeline createPipeline(VulkanContext VulkanContext, ShaderModule[] shaderModules, DescriptorSetLayout[] DescriptorSetLayouts) {
var vtxBuffStruct = new VertexBufferStructure();
var buildInfo = new PipelineBuildInfo(shaderModules, vtxBuffStruct.getVertexInput(), new int[]{ATTACHMENT_FORMATT})
.SetDepthFormat(DEPTH_FORMAT)
.SetPushConstantRanges(
new PushConstantsRange[]{
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT, 0, PUSH_CONSTANTS_SIZE)
})
.SetDescriptorSetLayouts(DescriptorSetLayouts)
.SetDescriptorSetLayouts(DescriptorSetLayouts)
.SetDepthClamp(VulkanContext.GetDevice().getDepthClamp());
var pipeline = new DefaultPipeline(VulkanContext, buildInfo);
vtxBuffStruct.cleanup();
return pipeline;
}
private static VkRenderingInfo createRenderInfo(VkRenderingAttachmentInfo.Buffer colorAttachmentInfo,
VkRenderingAttachmentInfo depthAttachments) {
var result = VkRenderingInfo.calloc().sType$Default();
try (var stack = MemoryStack.stackPush()) {
int shadowMapSize = EngineConfig.getInstance().GetShadowMapSize();
VkExtent2D extent = VkExtent2D.calloc(stack);
extent.width(shadowMapSize);
extent.height(shadowMapSize);
var renderArea = VkRect2D.calloc(stack).extent(extent);
result.renderArea(renderArea)
.layerCount(SceneLightingManager.SHADOW_MAP_CASCADE_COUNT)
.pColorAttachments(colorAttachmentInfo)
.pDepthAttachment(depthAttachments);
}
return result;
}
private static ShaderModule[] createShaderModules(VulkanContext VulkanContext) {
if (EngineConfig.getInstance().RecompileShaders()) {
ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader);
ShaderCompiler.CompileGLSLShaderOnChange(SHADOW_GEOMETRY_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_geometry_shader);
ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader);
}
return new ShaderModule[]{
new ShaderModule(VulkanContext, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV, null),
new ShaderModule(VulkanContext, VK_SHADER_STAGE_GEOMETRY_BIT, SHADOW_GEOMETRY_SHADER_FILE_SPV, null),
new ShaderModule(VulkanContext, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, null),
};
}
public void cleanup(VulkanContext VulkanContext) {
pipeline.CleanUp(VulkanContext);
uniformGeomDescriptorSetLayout.CleanUp(VulkanContext);
descLayoutFrgStorage.CleanUp(VulkanContext);
textDescriptorSetLayout.CleanUp(VulkanContext);
textureSampler.CleanUp(VulkanContext);
Arrays.asList(prjBuffers).forEach(b -> b.cleanup(VulkanContext));
renderingInfo.free();
depthAttachmentInfo.free();
depthAttachment.CleanUp(VulkanContext);
colorAttachmentInfo.free();
colorAttachment.CleanUp(VulkanContext);
MemoryUtil.memFree(pushConstBuff);
ClearValueColour.free();
ClearValueDepth.free();
}
public CascadeShadows getCascadeShadows(int currentFrame) {
return cascadeShadows[currentFrame];
}
public Attachment getShadowAttachment() {
return colorAttachment;
}
public void loadMaterials(VulkanContext VulkanContext, MaterialsCache materialsCache, TextureCache textureCache) {
DescriptorAllocator descAllocator = VulkanContext.GetDescriptorAllocator();
Device device = VulkanContext.GetDevice();
DescriptorSet descSet = descAllocator.AddDescriptorSet(device, DESCRIPTOR_ID_MAT, descLayoutFrgStorage);
DescriptorSetLayout.LayoutInformation layoutInfo = descLayoutFrgStorage.GetLayoutInfo();
var buffer = materialsCache.GetMaterialsBuffer();
descSet.SetBuffer(device, buffer, buffer.GetRequestedSize(), layoutInfo.Binding(), layoutInfo.DescriptorType());
List<ImageView> imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList();
descSet = VulkanContext.GetDescriptorAllocator().AddDescriptorSet(device, DESCRIPTOR_ID_TEXT, textDescriptorSetLayout);
descSet.SetImageArray(device, imageViews, textureSampler, 0);
}
public void render(EngineInstance engCtx, VulkanContext VulkanContext, CommandBuffer cmdBuffer, ModelsCache modelsCache,
MaterialsCache materialsCache, int currentFrame) {
try (var stack = MemoryStack.stackPush()) {
IScene scene = engCtx.scene();
ShadowUtils.updateCascadeShadows(cascadeShadows[currentFrame], scene);
VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer();
VulkanUtils.ImageBarrier(stack, cmdHandle, colorAttachment.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);
VulkanUtils.ImageBarrier(stack, cmdHandle, depthAttachment.GetVkImage().getVulkanImage(),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL,
VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT,
VK_ACCESS_2_NONE,
VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_IMAGE_ASPECT_DEPTH_BIT);
vkCmdBeginRendering(cmdHandle, renderingInfo);
vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipeline());
int shadowMapSize = EngineConfig.getInstance().GetShadowMapSize();
int width = shadowMapSize;
int height = shadowMapSize;
var viewport = VkViewport.calloc(1, stack)
.x(0)
.y(height)
.height(-height)
.width(width)
.minDepth(0.0f)
.maxDepth(1.0f);
vkCmdSetViewport(cmdHandle, 0, viewport);
var scissor = VkRect2D.calloc(1, stack)
.extent(it -> it.width(width).height(height))
.offset(it -> it.x(0).y(0));
vkCmdSetScissor(cmdHandle, 0, scissor);
updateProjBuffer(VulkanContext, currentFrame);
DescriptorAllocator descAllocator = VulkanContext.GetDescriptorAllocator();
LongBuffer descriptorSets = stack.mallocLong(3)
.put(0, descAllocator.GetDescriptorSet(DESCRIPTOR_ID_PRJ, currentFrame).GetVkDescriptorSet())
.put(1, descAllocator.GetDescriptorSet(DESCRIPTOR_ID_TEXT).GetVkDescriptorSet())
.put(2, descAllocator.GetDescriptorSet(DESCRIPTOR_ID_MAT).GetVkDescriptorSet());
vkCmdBindDescriptorSets(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.GetVulkanPipelineLayout(),
0, descriptorSets, null);
LongBuffer vertexBuffer = stack.mallocLong(1);
LongBuffer offsets = stack.mallocLong(1).put(0, 0L);
List<Actor3D> entities = scene.GetActors();
int numEntities = entities.size();
for (int i = 0; i < numEntities; i++) {
var entity = entities.get(i);
VulkanModel model = modelsCache.GetModel(entity.GetModelID());
List<VulkanMesh> vulkanMeshList = model.GetVkMeshList();
int numMeshes = vulkanMeshList.size();
for (int j = 0; j < numMeshes; j++) {
var vulkanMesh = vulkanMeshList.get(j);
String materialId = vulkanMesh.MaterialID();
int materialIdx = materialsCache.GetPosition(materialId);
VulkanMaterial vulkanMaterial = materialsCache.GetMaterial(materialId);
if (vulkanMaterial == null) {
Logger.warn("Mesh [{}] in model [{}] does not have material", j, model.GetID());
continue;
}
setPushConstants(cmdHandle, entity.GetModelMatrix(), materialIdx);
vertexBuffer.put(0, vulkanMesh.VerticesBuffer().GetBuffer());
vkCmdBindVertexBuffers(cmdHandle, 0, vertexBuffer, offsets);
vkCmdBindIndexBuffer(cmdHandle, vulkanMesh.IndicesBuffer().GetBuffer(), 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(cmdHandle, vulkanMesh.IndicesCount(), 1, 0, 0, 0);
}
}
vkCmdEndRendering(cmdHandle);
}
}
private void setPushConstants(VkCommandBuffer cmdHandle, Matrix4f modelMatrix, int materialIdx) {
modelMatrix.get(0, pushConstBuff);
pushConstBuff.putInt(VulkanUtils.MATRIX4X4_SIZE, materialIdx);
vkCmdPushConstants(cmdHandle, pipeline.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, pushConstBuff);
}
private void updateProjBuffer(VulkanContext VulkanContext, int currentFrame) {
int offset = 0;
List<CascadeData> cascadeDataList = cascadeShadows[currentFrame].GetCascadeData();
int numCascades = cascadeDataList.size();
VulkanBuffer vkBuffer = prjBuffers[currentFrame];
long mappedMemory = vkBuffer.MapMemory(VulkanContext);
ByteBuffer buff = MemoryUtil.memByteBuffer(mappedMemory, (int) vkBuffer.GetRequestedSize());
for (int i = 0; i < numCascades; i++) {
CascadeData cascadeData = cascadeDataList.get(i);
cascadeData.GetProjViewMatrix().get(offset, buff);
offset += VulkanUtils.MATRIX4X4_SIZE;
}
vkBuffer.UnMapMemory(VulkanContext);
}
} }

View file

@ -15,58 +15,65 @@ import java.util.List;
public class ShadowUtils { public class ShadowUtils {
private static final float LAMBDA = 0.95f; private static final float LAMBDA = 0.95f;
private static final Vector3f Up = new Vector3f(0.0f,1.0f,0.0f); private static final Vector3f UP = new Vector3f(0.0f, 1.0f, 0.0f);
private static final Vector3f UpAlt = new Vector3f(0.0f,0.0f,1.0f); private static final Vector3f UP_ALT = new Vector3f(0.0f, 0.0f, 1.0f);
private ShadowUtils(){
private ShadowUtils() {
} }
public static void UpdateCascadeShadows(CascadeShadows shadows, IScene scene){ public static void updateCascadeShadows(CascadeShadows cascadeShadows, IScene scene) {
Camera camera = scene.GetCamera(); Camera camera = scene.GetCamera();
Matrix4f ViewMatrix = camera.GetViewMatrix(); Matrix4f viewMatrix = camera.GetViewMatrix();
Project3D projection = scene.GetProjection(); Project3D projection = scene.GetProjection();
Matrix4f ProjectionMatrix = projection.GetProjectionMatrix(); Matrix4f projMatrix = projection.GetProjectionMatrix();
ILight[] lights = scene.GetLightingManager().GetLights(); ILight[] lights = scene.GetLightingManager().GetLights();
int LightCount = lights.length; int numLights = lights.length;
ILight SkyLight = null; ILight dirLight = null;
for(int i = 0; i < LightCount; i++){ for (int i = 0; i < numLights; i++) {
if(lights[i].IsDirectional()){ if (lights[i].IsDirectional()) {
SkyLight = lights[i]; dirLight = lights[i];
break; break;
} }
} }
if(SkyLight == null){ if (dirLight == null) {
throw new RuntimeException("No SkyLight on scene"); throw new RuntimeException("Could not find directional light");
} }
Vector4f LightPosition = new Vector4f(SkyLight.GetPosition(),0.0f); Vector3f lightPos = dirLight.GetPosition();
float[] CascadeSplits = new float[SceneLightingManager.SHADOW_MAP_CASCADE_COUNT];
float NearClip = Math.min(projection.GetNearZ(), projection.GetFarZ());
float FarClip = Math.max(projection.GetNearZ(), projection.GetFarZ());
float ClipRange = FarClip - NearClip;
float MinZ = NearClip; float[] cascadeSplits = new float[SceneLightingManager.SHADOW_MAP_CASCADE_COUNT];
float MaxZ = NearClip + ClipRange;
float Range = MaxZ - MinZ; float nearClip = projection.GetNearZ();
float Ratio = MaxZ/MinZ; float farClip = projection.GetFarZ();
float clipRange = farClip - nearClip;
List<CascadeData> cascadeDataList = shadows.GetCascadeData(); if (nearClip <= 0.0f || farClip <= nearClip) {
int CascadeCount = cascadeDataList.size(); //throw new IllegalStateException("Invalid projection near/far planes for shadow cascades: near=" + nearClip + ", far=" + farClip);
}
for(int i = 0; i < CascadeCount; i++){ float minZ = nearClip;
float maxZ = nearClip + clipRange;
float range = maxZ - minZ;
float ratio = maxZ / minZ;
List<CascadeData> cascadeDataList = cascadeShadows.GetCascadeData();
int numCascades = cascadeDataList.size();
// Calculate split depths based on view camera frustum
// Based on method presented in https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch10.html
for (int i = 0; i < numCascades; i++) {
float p = (i + 1) / (float) (SceneLightingManager.SHADOW_MAP_CASCADE_COUNT); float p = (i + 1) / (float) (SceneLightingManager.SHADOW_MAP_CASCADE_COUNT);
float Log = (float) (MinZ * Math.pow(Ratio, p)); float log = (float) (minZ * java.lang.Math.pow(ratio, p));
float Uniform = MinZ + Range * p; float uniform = minZ + range * p;
float d = LAMBDA * (Log - Uniform) + Uniform; float d = LAMBDA * (log - uniform) + uniform;
CascadeSplits[i] = (d - NearClip) / ClipRange; cascadeSplits[i] = (d - nearClip) / clipRange;
} }
float LastSplitDist = 0.0f; float lastSplitDist = 0.0f;
for(int i = 0; i < CascadeCount; i++){ for (int i = 0; i < numCascades; i++) {
float SplitDist = CascadeSplits[i]; float splitDist = cascadeSplits[i];
Vector3f[] FustrumCorners = new Vector3f[]{ Vector3f[] frustumCorners = new Vector3f[]{
new Vector3f(-1.0f, 1.0f, 0.0f), new Vector3f(-1.0f, 1.0f, 0.0f),
new Vector3f(1.0f, 1.0f, 0.0f), new Vector3f(1.0f, 1.0f, 0.0f),
new Vector3f(1.0f, -1.0f, 0.0f), new Vector3f(1.0f, -1.0f, 0.0f),
@ -74,70 +81,73 @@ public class ShadowUtils {
new Vector3f(-1.0f, 1.0f, 1.0f), new Vector3f(-1.0f, 1.0f, 1.0f),
new Vector3f(1.0f, 1.0f, 1.0f), new Vector3f(1.0f, 1.0f, 1.0f),
new Vector3f(1.0f, -1.0f, 1.0f), new Vector3f(1.0f, -1.0f, 1.0f),
new Vector3f(-1.0f, -1.0f, 1.0f) new Vector3f(-1.0f, -1.0f, 1.0f),
}; };
var InvertedCam = (new Matrix4f(ProjectionMatrix).mul(ViewMatrix)).invert(); // Project frustum corners into world space
for(int j = 0; j < 8; j++){ var invCam = (new Matrix4f(projMatrix).mul(viewMatrix)).invert();
Vector4f InvertedCorner = new Vector4f(FustrumCorners[j],1.0f).mul(InvertedCam); for (int j = 0; j < 8; j++) {
FustrumCorners[j] = new Vector3f(InvertedCorner.x,InvertedCorner.y,InvertedCorner.z).div(InvertedCorner.w); Vector4f invCorner = new Vector4f(frustumCorners[j], 1.0f).mul(invCam);
frustumCorners[j] = new Vector3f(invCorner.x, invCorner.y, invCorner.z).div(invCorner.w);
} }
for(int j = 0; j < 4; j++){ for (int j = 0; j < 4; j++) {
var Distance = new Vector3f(FustrumCorners[j + 4]).sub(FustrumCorners[j]); var dist = new Vector3f(frustumCorners[j + 4]).sub(frustumCorners[j]);
FustrumCorners[j + 4] = new Vector3f(FustrumCorners[j]).add(new Vector3f(Distance).mul(SplitDist)); frustumCorners[j + 4] = new Vector3f(frustumCorners[j]).add(new Vector3f(dist).mul(splitDist));
FustrumCorners[j] = new Vector3f(FustrumCorners[j]).add(new Vector3f(Distance).mul(LastSplitDist)); frustumCorners[j] = new Vector3f(frustumCorners[j]).add(new Vector3f(dist).mul(lastSplitDist));
} }
var FustrumCenter = new Vector3f(0.0f); var frustumCenter = new Vector3f(0.0f);
for(int j = 0; j < 8; j++){ for (int j = 0; j < 8; j++) {
FustrumCenter.add(FustrumCorners[j]); frustumCenter.add(frustumCorners[j]);
} }
FustrumCenter.div(8); frustumCenter.div(8.0f);
var up = Up; var up = UP;
float SphereRadius = 0.0f; float sphereRadius = 0.0f;
for(int j = 0; j < 8; j++){ for (int j = 0; j < 8; j++) {
float Distance = new Vector3f(FustrumCorners[j]).sub(FustrumCenter).length(); float dist = new Vector3f(frustumCorners[j]).sub(frustumCenter).length();
SphereRadius = Math.max(SphereRadius,Distance); sphereRadius = java.lang.Math.max(sphereRadius, dist);
} }
SphereRadius = (float)Math.ceil(SphereRadius * 16.0f) / 16.0f; sphereRadius = (float) java.lang.Math.ceil(sphereRadius * 16.0f) / 16.0f;
var MaxExtents = new Vector3f(SphereRadius); var maxExtents = new Vector3f(sphereRadius, sphereRadius, sphereRadius);
var MinExtents = new Vector3f(-SphereRadius); var minExtents = new Vector3f(maxExtents).mul(-1.0f);
var LightDirection = new Vector3f(LightPosition.x, LightPosition.y, LightPosition.z); var lightDir = new Vector3f(lightPos.x, lightPos.y, lightPos.z);
var ShadowCamPosition = new Vector3f(FustrumCenter).add(LightDirection.mul(MinExtents.z)); var shadowCameraPos = new Vector3f(frustumCenter).add(lightDir.mul(minExtents.z));
float Dot = Math.abs(new Vector3f(LightPosition.x, LightPosition.y, LightPosition.z).dot(up)); float dot = java.lang.Math.abs(new Vector3f(lightPos.x, lightPos.y, lightPos.z).dot(up));
if(Dot == 1.0f){ if (dot == 1.0f) {
up = UpAlt; up = UP_ALT;
} }
var LightViewMatrix = new Matrix4f().lookAt(ShadowCamPosition,FustrumCenter,up); var lightViewMatrix = new Matrix4f().lookAt(shadowCameraPos, frustumCenter, up);
var LightOrthoMatrix = new Matrix4f().ortho(MinExtents.x,MaxExtents.x,MinExtents.y,MaxExtents.y,0.0f,MaxExtents.z - MinExtents.z,true); var lightOrthoMatrix = new Matrix4f().ortho
(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - minExtents.z, true);
int ShadowMapSize = EngineConfig.getInstance().GetShadowMapSize(); int shadowMapSize = EngineConfig.getInstance().GetShadowMapSize();
Vector4f ShadowOrigin = new Vector4f(0f,0f,0f,1f); Vector4f shadowOrigin = new Vector4f(0.0f, 0.0f, 0.0f, 1.0f);
LightViewMatrix.transform(ShadowOrigin); lightViewMatrix.transform(shadowOrigin);
ShadowOrigin.mul(ShadowMapSize/2.0f); shadowOrigin.mul(shadowMapSize / 2.0f);
Vector4f RoundedOrigin = new Vector4f(ShadowOrigin).round(); Vector4f roundedOrigin = new Vector4f(shadowOrigin).round();
Vector4f RoundOffset = RoundedOrigin.sub(ShadowOrigin); Vector4f roundOffset = roundedOrigin.sub(shadowOrigin);
RoundOffset.mul(2.0f/ShadowMapSize); roundOffset.mul(2.0f / shadowMapSize);
RoundOffset.z = 0.0f; roundOffset.z = 0.0f;
RoundOffset.w = 0.0f; roundOffset.w = 0.0f;
LightOrthoMatrix.m30(LightOrthoMatrix.m30() + RoundOffset.x); lightOrthoMatrix.m30(lightOrthoMatrix.m30() + roundOffset.x);
LightOrthoMatrix.m31(LightOrthoMatrix.m31() + RoundOffset.y); lightOrthoMatrix.m31(lightOrthoMatrix.m31() + roundOffset.y);
LightOrthoMatrix.m32(LightOrthoMatrix.m32() + RoundOffset.z); lightOrthoMatrix.m32(lightOrthoMatrix.m32() + roundOffset.z);
LightOrthoMatrix.m33(LightOrthoMatrix.m33() + RoundOffset.w); lightOrthoMatrix.m33(lightOrthoMatrix.m33() + roundOffset.w);
// Store split distance and matrix in cascade
CascadeData cascadeData = cascadeDataList.get(i); CascadeData cascadeData = cascadeDataList.get(i);
cascadeData.SetSplitDistance((NearClip + SplitDist * ClipRange) * -1.0f); cascadeData.SetSplitDistance((nearClip + splitDist * clipRange) * -1.0f);
cascadeData.SetProjectionViewMatrix(LightOrthoMatrix.mul(LightViewMatrix)); cascadeData.SetProjectionViewMatrix(lightOrthoMatrix.mul(lightViewMatrix));
LastSplitDist = CascadeSplits[i]; lastSplitDist = cascadeSplits[i];
} }
} }
} }

View file

@ -157,10 +157,7 @@ public class SpriteRenderer {
.SetDepthWrite(DepthWrite) .SetDepthWrite(DepthWrite)
.SetPushConstantRanges( .SetPushConstantRanges(
new PushConstantsRange[]{ new PushConstantsRange[]{
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,0,VulkanUtils.VEC2_SIZE), new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,0,VulkanUtils.VEC2_SIZE * 3 + VulkanUtils.FLOAT_SIZE),
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,VulkanUtils.VEC2_SIZE,VulkanUtils.VEC2_SIZE),
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,VulkanUtils.VEC2_SIZE * 2,VulkanUtils.VEC2_SIZE),
new PushConstantsRange(VK_SHADER_STAGE_VERTEX_BIT,VulkanUtils.VEC2_SIZE * 3,VulkanUtils.FLOAT_SIZE),
new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT,VulkanUtils.VEC2_SIZE * 3 + VulkanUtils.FLOAT_SIZE,VulkanUtils.INT_SIZE) new PushConstantsRange(VK_SHADER_STAGE_FRAGMENT_BIT,VulkanUtils.VEC2_SIZE * 3 + VulkanUtils.FLOAT_SIZE,VulkanUtils.INT_SIZE)
}) })
.SetDescriptorSetLayouts(DescriptorSetLayouts) .SetDescriptorSetLayouts(DescriptorSetLayouts)

View file

@ -20,6 +20,7 @@ import static org.lwjgl.vulkan.KHRPortabilitySubset.VK_KHR_PORTABILITY_SUBSET_EX
import static org.lwjgl.vulkan.VK13.*; import static org.lwjgl.vulkan.VK13.*;
public class Device { public class Device {
private final boolean depthClamp;
private final VkDevice VulkanDevice; private final VkDevice VulkanDevice;
private final boolean SamplesAnisotropy; private final boolean SamplesAnisotropy;
@ -37,14 +38,15 @@ public class Device {
.queueFamilyIndex(i) .queueFamilyIndex(i)
.pQueuePriorities(Priorities); .pQueuePriorities(Priorities);
} }
var features12 = VkPhysicalDeviceVulkan12Features.calloc(MemStack)
.sType$Default()
.scalarBlockLayout(true);
var features13 = VkPhysicalDeviceVulkan13Features.calloc(MemStack) var features13 = VkPhysicalDeviceVulkan13Features.calloc(MemStack)
.sType$Default() .sType$Default()
.dynamicRendering(true) .dynamicRendering(true)
.synchronization2(true); .synchronization2(true);
var features12 = VkPhysicalDeviceVulkan12Features.calloc(MemStack)
.sType$Default()
.scalarBlockLayout(true);
var features2 = VkPhysicalDeviceFeatures2.calloc(MemStack).sType$Default(); var features2 = VkPhysicalDeviceFeatures2.calloc(MemStack).sType$Default();
var features = features2.features(); var features = features2.features();
@ -53,8 +55,11 @@ public class Device {
if(SamplesAnisotropy){ if(SamplesAnisotropy){
features.samplerAnisotropy(true); features.samplerAnisotropy(true);
} }
features2.pNext(features13.address()); features.geometryShader(true);
features13.pNext(features12.address()); depthClamp = SupportedFeatures.depthClamp();
features.depthClamp(depthClamp);
features2.pNext(features12.address());
features12.pNext(features13.address());
var DeviceCreateInfo = VkDeviceCreateInfo.calloc(MemStack) var DeviceCreateInfo = VkDeviceCreateInfo.calloc(MemStack)
.sType$Default() .sType$Default()
@ -75,6 +80,10 @@ public class Device {
} }
} }
public boolean getDepthClamp() {
return depthClamp;
}
private static PointerBuffer CreateRequiredExtensions(PhysicalDevice PhysDevice, MemoryStack MemStack){ private static PointerBuffer CreateRequiredExtensions(PhysicalDevice PhysDevice, MemoryStack MemStack){
Set<String> DeviceExtensions = GetDeviceExtensions(PhysDevice); Set<String> DeviceExtensions = GetDeviceExtensions(PhysDevice);
//cross platform support for that fuckass Metal API mac uses //cross platform support for that fuckass Metal API mac uses

View file

@ -108,7 +108,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
public DeferredSceneRender(VulkanContext vulkanContext, EngineInstance engineInstance){ public DeferredSceneRender(VulkanContext vulkanContext, EngineInstance engineInstance){
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, 0.0f).float32(1, 0.0f).float32(2, 0.0f).float32(3, 0.0f));
ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f)); ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 1.0f));
MRTAttachments = new MultiRenderTargetAttachments(vulkanContext); MRTAttachments = new MultiRenderTargetAttachments(vulkanContext);
AttachmentInfoColour = CreateColourAttachmentInfo(MRTAttachments, ClearValueColour); AttachmentInfoColour = CreateColourAttachmentInfo(MRTAttachments, ClearValueColour);
AttachmentInfoDepth = CreateDepthAttachmentInfo(MRTAttachments, ClearValueDepth); AttachmentInfoDepth = CreateDepthAttachmentInfo(MRTAttachments, ClearValueDepth);
@ -267,7 +267,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering
.SetDepthTest(true) .SetDepthTest(true)
.SetPushConstantRanges(new PushConstantsRange[0]) .SetPushConstantRanges(new PushConstantsRange[0])
.SetDescriptorSetLayouts(DescriptorSetLayouts) .SetDescriptorSetLayouts(DescriptorSetLayouts)
.BlendingIsUsed(true) .BlendingIsUsed(false)
.SetDualPass(false) .SetDualPass(false)
.SetAlphaToCoverage(false); .SetAlphaToCoverage(false);
var pipeline = new DefaultPipeline(VkCtx, BuildInfo); var pipeline = new DefaultPipeline(VkCtx, BuildInfo);

View file

@ -117,7 +117,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering
public ForwardSceneRender(VulkanContext vulkanContext){ public ForwardSceneRender(VulkanContext vulkanContext){
ClearValueColour = VkClearValue.calloc().color( ClearValueColour = VkClearValue.calloc().color(
c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f)); c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f));
ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f)); ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 1.0f));
CreateRenderAttachments(vulkanContext); CreateRenderAttachments(vulkanContext);
PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE)); PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE));

View file

@ -17,12 +17,14 @@ public class ImageView {
private final long VulkanImage; private final long VulkanImage;
private final long VulkanImageView; private final long VulkanImageView;
private final boolean DepthImage; private final boolean DepthImage;
private final int layerCount;
public ImageView(Device device, long vulkanImage, ImageViewData imageViewData, boolean DepthImage){ public ImageView(Device device, long vulkanImage, ImageViewData imageViewData, boolean DepthImage){
this.AspectMask = imageViewData.AspectMask; this.AspectMask = imageViewData.AspectMask;
this.MipLevels = imageViewData.MipLevels; this.MipLevels = imageViewData.MipLevels;
this.VulkanImage = vulkanImage; this.VulkanImage = vulkanImage;
this.DepthImage = DepthImage; this.DepthImage = DepthImage;
this.layerCount = imageViewData.LayerCount;
try(var MemStack = MemoryStack.stackPush()){ try(var MemStack = MemoryStack.stackPush()){
LongBuffer LongPointer = MemStack.mallocLong(1); LongBuffer LongPointer = MemStack.mallocLong(1);
var ViewCreateInfo = VkImageViewCreateInfo.calloc(MemStack) var ViewCreateInfo = VkImageViewCreateInfo.calloc(MemStack)
@ -46,6 +48,10 @@ public class ImageView {
vkDestroyImageView(device.FetchVulkanDevice(), VulkanImageView, null); vkDestroyImageView(device.FetchVulkanDevice(), VulkanImageView, null);
} }
public int GetLayerCount() {
return layerCount;
}
public int GetAspectMask(){ public int GetAspectMask(){
return AspectMask; return AspectMask;
} }

View file

@ -37,15 +37,16 @@ public class RenderThread extends EngineThread {
public InitData GetInitData(){return initData;} public InitData GetInitData(){return initData;}
public void RestartCrashedRenderer(){ public void RestartCrashedRenderer(){
if(Headless) return; throw new IllegalStateException("Vulkan device lost; terminating renderer instead of hot-restarting");
if(VulkanCrashCount < EngineConfig.getInstance().GetMaxVulkanCrashes()){ // if(Headless) return;
RefreshRenderer(); // if(VulkanCrashCount < EngineConfig.getInstance().GetMaxVulkanCrashes()){
VulkanCrashCount++; // RefreshRenderer();
}else{ // VulkanCrashCount++;
Logger.error("MAX API CRASHES REACHED, CLOSING SOFTWARE"); // }else{
PrimaryRuntime.GetEngineInstance().window().setShouldClose(); // Logger.error("MAX API CRASHES REACHED, CLOSING SOFTWARE");
PrimaryRuntime.CloseRuntime(); // PrimaryRuntime.GetEngineInstance().window().setShouldClose();
} // PrimaryRuntime.CloseRuntime();
// }
} }
public Renderer GetRenderer(){return render;} public Renderer GetRenderer(){return render;}

View file

@ -11,7 +11,7 @@ Renderer=1
RenderingAPI=Vulkan RenderingAPI=Vulkan
RequestedImages=3 RequestedImages=3
ShaderRecompiling=true ShaderRecompiling=true
ShadowMapSize=2048 ShadowMapSize=4096
Software_Icon=ProgramIcon.png Software_Icon=ProgramIcon.png
Software_Icon_Path=/WindowResources/Icon/ Software_Icon_Path=/WindowResources/Icon/
Software_Title=Terrain4J Game Engine Software_Title=Terrain4J Game Engine
@ -35,5 +35,5 @@ throttle_on_unfocus=false
user_display_name=TheSigma user_display_name=TheSigma
vkValidated=true vkValidated=true
vsync=false vsync=false
z_far_plane=0.1f z_near_plane=0.1f
z_near_plane=10000.0f z_far_plane=10000.0f