diff --git a/build.gradle b/build.gradle index a154d98..d043272 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,17 @@ buildscript { plugins { id 'application' id 'java' + id 'com.gradleup.shadow' version '9.2.0' } + +jar { + manifest { + attributes( + 'Main-Class': 'net.halbear.Executable.Launcher' + ) + } +} + project.ext.lwjglVersion = "3.4.1" project.ext.jomlVersion = "1.10.8" project.ext.jomlprimitivesVersion = "1.10.0" diff --git a/resources/EngineResources/shaders/lighting_frag.glsl b/resources/EngineResources/shaders/lighting_frag.glsl index a7fada2..8108408 100644 --- a/resources/EngineResources/shaders/lighting_frag.glsl +++ b/resources/EngineResources/shaders/lighting_frag.glsl @@ -23,6 +23,9 @@ 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 sampler2D emissiveSampler; +layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler; +layout(set = 0, binding = 6) uniform sampler2D OpacitySampler; layout(scalar, set = 1, binding = 0) readonly buffer Lights { Light lights[]; @@ -32,6 +35,7 @@ layout(scalar, set = 2, binding = 0) uniform SceneInfo { float ambientLightIntensity; vec3 ambientLightColor; uint numLights; + mat4 viewMatrix; } sceneInfo; float distributionGGX(vec3 N, vec3 H, float roughness) { @@ -126,6 +130,10 @@ void main() { vec3 normal = texture(normalsSampler, inTextCoord).rgb; vec3 worldPos = texture(posSampler, inTextCoord).rgb; vec3 pbr = texture(pbrSampler, inTextCoord).rgb; + vec3 emissive = texture(emissiveSampler, inTextCoord).rgb; + vec3 translucency = texture(TranslucencySampler, inTextCoord).rgb; + float emissiveness = emissive.r; + float roughness = pbr.g; float metallic = pbr.b; @@ -146,9 +154,9 @@ void main() { } } vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity; - vec3 color = ambient + Lo; + outFragColor = vec4(Lo + ambient + vec3(emissiveness), 1.0f); - outFragColor = vec4(color, 1.0f); + // outFragColor = vec4(color, 1.0f); if (length(normal) < 0.001) { outFragColor = vec4(albedo,1.0f); return; diff --git a/resources/EngineResources/shaders/lighting_frag.glsl.spv b/resources/EngineResources/shaders/lighting_frag.glsl.spv index 8cd6ee9..067478a 100644 Binary files a/resources/EngineResources/shaders/lighting_frag.glsl.spv and b/resources/EngineResources/shaders/lighting_frag.glsl.spv differ diff --git a/resources/EngineResources/shaders/lighting_with_shadows_frag.glsl b/resources/EngineResources/shaders/lighting_with_shadows_frag.glsl index 7e3f672..81c739c 100644 --- a/resources/EngineResources/shaders/lighting_with_shadows_frag.glsl +++ b/resources/EngineResources/shaders/lighting_with_shadows_frag.glsl @@ -27,7 +27,11 @@ 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(set = 0, binding = 4) uniform sampler2D emissiveSampler; +layout(set = 0, binding = 5) uniform sampler2D TranslucencySampler; +layout(set = 0, binding = 6) uniform sampler2D OpacitySampler; +layout(set = 0, binding = 7) uniform sampler2DArray shadowSampler; + layout(scalar, set = 1, binding = 0) readonly buffer Lights { Light lights[]; @@ -62,7 +66,7 @@ float chebyshevUpperBound(vec2 moments, float t) { return p_max; } -float calcVisibility(vec4 worldPosition, uint cascadeIndex) { +float calcVisibility(vec4 worldPosition, uint cascadeIndex, float ShadowBias) { vec4 shadowMapPosition = shadows.cascadeshadows[cascadeIndex].projViewMatrix * worldPosition; shadowMapPosition.xyz /= shadowMapPosition.w; @@ -76,14 +80,25 @@ float calcVisibility(vec4 worldPosition, uint cascadeIndex) { if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0 || - depth < 0.0 || depth > 1.0) { + depth < ShadowBias || depth > 1.0) { return 1.0; } - vec2 moments = texture(shadowSampler, vec3(uv, cascadeIndex)).rg; + float shadow = 0.0; - float visibility = chebyshevUpperBound(moments, depth); - return visibility; + vec2 texelSize = 1.0 / textureSize(shadowSampler, 0).rg; + for(int x = -1; x <= 1; ++x) + { + for(int y = -1; y <= 1; ++y) + { + vec2 moments = texture(shadowSampler, vec3((uv + vec2(x, y) * texelSize), cascadeIndex)).rg; + float visibility = chebyshevUpperBound(moments, depth); + shadow += depth - ShadowBias > visibility ? 1.0 : 0.0; + } + } + shadow /= 9.0; + + return 1 - shadow; } float distributionGGX(vec3 N, vec3 H, float roughness) { @@ -150,7 +165,7 @@ vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, ve return (kD * albedo / PI + specular) * radiance * NdotL; } -vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) { +vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness, float translucency) { vec3 L = normalize(-light.position); vec3 H = normalize(V + L); @@ -170,7 +185,9 @@ vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo kD *= 1.0 - metallic; float NdotL = max(dot(N, L), 0.0); - return (kD * albedo / PI + specular) * radiance * NdotL; + vec3 shadowValue = (kD * albedo / PI + specular) * radiance * NdotL; + vec3 lightValue = (kD * albedo / PI + specular) * radiance; + return (shadowValue * (1 - translucency)) + (lightValue * translucency); } void main() { @@ -179,6 +196,20 @@ void main() { vec4 worldPosW = texture(posSampler, inTextCoord); vec3 worldPos = worldPosW.xyz; vec3 pbr = texture(pbrSampler, inTextCoord).rgb; + vec3 emissive = texture(emissiveSampler, inTextCoord).rgb; + vec3 Opacity = texture(OpacitySampler, inTextCoord).rgb; + vec3 translucency = texture(TranslucencySampler, inTextCoord).rgb; + + float emissiveness = emissive.r; + float translucencyf = translucency.r; + +// outFragColor = vec4(emissive,1); +// return; + + float ShadowBias = 0.05f; + + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf/3.0; float roughness = pbr.g; float metallic = pbr.b; @@ -186,6 +217,8 @@ void main() { vec3 N = normalize(normal); vec3 V = normalize(sceneInfo.camPos - worldPos); + + vec3 F0 = vec3(0.04); F0 = mix(F0, albedo, metallic); @@ -196,18 +229,19 @@ void main() { cascadeIndex = i + 1; } } - float shadow = calcVisibility(vec4(worldPos, 1), cascadeIndex); + float shadow = calcVisibility(vec4(worldPos, 1), cascadeIndex,ShadowBias); 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; + Lo += calculateDirectionalLight(light, V, N, F0, albedo, metallic, roughness,translucencyf) * shadow; } else { Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness); } } vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity; + if(emissive.x > 0 || emissive.y > 0 || emissive.z > 0) ambient = emissive; outFragColor = vec4(Lo + ambient, 1.0f); if (DEBUG_SHADOWS == 1) { diff --git a/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl.spv b/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl.spv index 1cce2dd..2cf3d79 100644 Binary files a/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl.spv and b/resources/EngineResources/shaders/multi-sampled_post_process_frag.glsl.spv differ diff --git a/resources/EngineResources/shaders/post_process_frag.glsl b/resources/EngineResources/shaders/post_process_frag.glsl index e4c4353..b15b7d0 100644 --- a/resources/EngineResources/shaders/post_process_frag.glsl +++ b/resources/EngineResources/shaders/post_process_frag.glsl @@ -2,7 +2,7 @@ layout(constant_id = 0) const int USE_AA = 0; -const float GAMMA_CONST = 0.4545; +const float GAMMA_CONST = 0.8545; const float SPAN_MAX = 8.0; const float REDUCE_MIN = 1.0/128.0; const float REDUCE_MUL = 1.0/32.0; diff --git a/resources/EngineResources/shaders/post_process_frag.glsl.spv b/resources/EngineResources/shaders/post_process_frag.glsl.spv index a4a924f..055aba0 100644 Binary files a/resources/EngineResources/shaders/post_process_frag.glsl.spv and b/resources/EngineResources/shaders/post_process_frag.glsl.spv differ diff --git a/resources/EngineResources/shaders/scene_fragment.glsl b/resources/EngineResources/shaders/scene_fragment.glsl index 759800e..87eb92c 100644 --- a/resources/EngineResources/shaders/scene_fragment.glsl +++ b/resources/EngineResources/shaders/scene_fragment.glsl @@ -10,17 +10,25 @@ layout(location = 4) in vec2 inTextCoords; layout(location = 0) out vec4 outAlbedo; - struct Material { - vec4 diffuseColor; - uint hasTexture; - uint textureIdx; - uint hasNormalMap; - uint normalMapIdx; - uint hasRoughMap; - uint roughMapIdx; - float roughnessFactor; - float metallicFactor; + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 }; layout(set = 2, binding = 0) readonly buffer MaterialUniform{ @@ -36,13 +44,23 @@ layout(push_constant) uniform pc{ void main() { + Material material = matUniform.materials[push_constants.materialIdx]; if(material.hasTexture == 1){ vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords); - if(texColor.a < 0.4){discard;} outAlbedo = texColor; } else{ outAlbedo = material.diffuseColor; } + vec4 Opacity = vec4(outAlbedo.a,outAlbedo.a,outAlbedo.a,1); + if(material.OpacityFactor != 1) Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1); + if(material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES){ + Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords); + } + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf/3; + if(opacityf < 0.4){discard;} + + outAlbedo = vec4(outAlbedo.rgb, opacityf); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_fragment.glsl.spv b/resources/EngineResources/shaders/scene_fragment.glsl.spv index 0cf93b5..9776783 100644 Binary files a/resources/EngineResources/shaders/scene_fragment.glsl.spv and b/resources/EngineResources/shaders/scene_fragment.glsl.spv differ diff --git a/resources/EngineResources/shaders/scene_fragment_deferred.glsl b/resources/EngineResources/shaders/scene_fragment_deferred.glsl index fc873e0..2392663 100644 --- a/resources/EngineResources/shaders/scene_fragment_deferred.glsl +++ b/resources/EngineResources/shaders/scene_fragment_deferred.glsl @@ -12,17 +12,29 @@ layout(location = 1) out vec4 outAlbedo ; layout(location = 0) out vec4 outPos; layout(location = 2) out vec4 outNormal; layout(location = 3) out vec4 outPBR; +layout(location = 4) out vec4 outEmissive; +layout(location = 5) out vec4 outTranslucency; +layout(location = 6) out vec4 outOpacity; struct Material { - vec4 diffuseColor; - uint hasTexture; - uint textureIdx; - uint hasNormalMap; - uint normalMapIdx; - uint hasRoughMap; - uint roughMapIdx; - float roughnessFactor; - float metallicFactor; + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 }; layout(set = 2, binding = 0) readonly buffer MaterialUniform { Material materials[]; @@ -56,6 +68,17 @@ void main() outAlbedo = material.diffuseColor; } + vec4 Opacity = vec4(outAlbedo.a,outAlbedo.a,outAlbedo.a,1); + if(material.OpacityFactor != 1) Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1); + if(material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES){ + Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords); + } + outOpacity = Opacity; + + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf/3; + + outAlbedo = vec4(outAlbedo.rgb, opacityf); if(outAlbedo.a < 0.5) discard; @@ -75,6 +98,18 @@ void main() metallicFactor = material.metallicFactor; } + vec4 emissive = material.emissiveColour; + if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) { + emissive = texture(textSampler[material.emissiveMapIdx], inTextCoords); + } + outEmissive = emissive; + + vec4 Translucency = vec4(material.translucencyFactor,material.translucencyFactor,material.translucencyFactor,1); + if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){ + Translucency = texture(textSampler[material.translucencyMapIdx], inTextCoords); + } + outTranslucency = Translucency; + outPBR = vec4(ao, roughnessFactor, metallicFactor, 1.0f); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_fragment_deferred.glsl.spv b/resources/EngineResources/shaders/scene_fragment_deferred.glsl.spv index 16cea28..2e37b81 100644 Binary files a/resources/EngineResources/shaders/scene_fragment_deferred.glsl.spv and b/resources/EngineResources/shaders/scene_fragment_deferred.glsl.spv differ diff --git a/resources/EngineResources/shaders/scene_opaque_fragment.glsl b/resources/EngineResources/shaders/scene_opaque_fragment.glsl index dea4039..f8290eb 100644 --- a/resources/EngineResources/shaders/scene_opaque_fragment.glsl +++ b/resources/EngineResources/shaders/scene_opaque_fragment.glsl @@ -11,15 +11,24 @@ layout(location = 4) in vec2 inTextCoords; layout(location = 0) out vec4 outAlbedo; struct Material { - vec4 diffuseColor; - uint hasTexture; - uint textureIdx; - uint hasNormalMap; - uint normalMapIdx; - uint hasRoughMap; - uint roughMapIdx; - float roughnessFactor; - float metallicFactor; + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 }; layout(set = 2, binding = 0) readonly buffer MaterialUniform{ @@ -37,9 +46,18 @@ void main() Material material = matUniform.materials[push_constants.materialIdx]; if(material.hasTexture == 1){ vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords); - if(texColor.a < 0.9){discard;} outAlbedo = texColor; } else{ outAlbedo = material.diffuseColor; } + vec4 Opacity = vec4(outAlbedo.a,outAlbedo.a,outAlbedo.a,1); + if(material.OpacityFactor != 1) Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1); + if(material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES){ + Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords); + } + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf/3; + if(opacityf < 0.9){discard;} + + outAlbedo = vec4(outAlbedo.rgb, opacityf); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_opaque_fragment.glsl.spv b/resources/EngineResources/shaders/scene_opaque_fragment.glsl.spv index 5a5dfb1..251492d 100644 Binary files a/resources/EngineResources/shaders/scene_opaque_fragment.glsl.spv and b/resources/EngineResources/shaders/scene_opaque_fragment.glsl.spv differ diff --git a/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl b/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl index b230395..d91d780 100644 --- a/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl +++ b/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl @@ -12,6 +12,9 @@ layout(location = 1) out vec4 outAlbedo ; layout(location = 0) out vec4 outPos; layout(location = 2) out vec4 outNormal; layout(location = 3) out vec4 outPBR; +layout(location = 4) out vec4 outEmissive; +layout(location = 5) out vec4 outTranslucency; +layout(location = 6) out vec4 outOpacity; const float bayerMatrix[16] = float[]( 0.0 / 16.0, 8.0 / 16.0, 2.0 / 16.0, 10.0 / 16.0, @@ -21,15 +24,24 @@ const float bayerMatrix[16] = float[]( ); struct Material { - vec4 diffuseColor; - uint hasTexture; - uint textureIdx; - uint hasNormalMap; - uint normalMapIdx; - uint hasRoughMap; - uint roughMapIdx; - float roughnessFactor; - float metallicFactor; + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 }; layout(set = 2, binding = 0) readonly buffer MaterialUniform { Material materials[]; @@ -67,6 +79,19 @@ void main() int y = int(gl_FragCoord.y) % Intensity; float threshold = bayerMatrix[y * Intensity + x]; if(outAlbedo.a < threshold || outAlbedo.a < 0.05f) discard;*/ + + vec4 Opacity = vec4(outAlbedo.a,outAlbedo.a,outAlbedo.a,1); + if(material.OpacityFactor != 1) Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1); + if(material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES){ + Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords); + } + outOpacity = Opacity; + + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf/3; + + outAlbedo = vec4(outAlbedo.rgb, opacityf); + if(outAlbedo.a < 0.75) discard; @@ -86,6 +111,18 @@ void main() metallicFactor = material.metallicFactor; } + vec4 emissive = material.emissiveColour; + if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) { + emissive = texture(textSampler[material.emissiveMapIdx], inTextCoords); + } + outEmissive = emissive; + + vec4 Translucency = vec4(material.translucencyFactor,material.translucencyFactor,material.translucencyFactor,1); + if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){ + Translucency = texture(textSampler[material.translucencyMapIdx], inTextCoords); + } + outTranslucency = Translucency; + outPBR = vec4(ao, roughnessFactor, metallicFactor, outAlbedo.a); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl.spv b/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl.spv index c06da7b..a4f90f2 100644 Binary files a/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl.spv and b/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl.spv differ diff --git a/resources/EngineResources/shaders/scene_translucent_fragment.glsl b/resources/EngineResources/shaders/scene_translucent_fragment.glsl index f909b2e..847195f 100644 --- a/resources/EngineResources/shaders/scene_translucent_fragment.glsl +++ b/resources/EngineResources/shaders/scene_translucent_fragment.glsl @@ -10,18 +10,26 @@ layout(location = 4) in vec2 inTextCoords; layout(location = 0) out vec4 outAlbedo; -struct Material{ - vec4 diffuseColor; - uint hasTexture; - uint textureIdx; - uint hasNormalMap; - uint normalMapIdx; - uint hasRoughMap; - uint roughMapIdx; - float roughnessFactor; - float metallicFactor; +struct Material { + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 }; - layout(set = 2, binding = 0) readonly buffer MaterialUniform{ Material materials[]; } matUniform; @@ -37,9 +45,19 @@ void main() Material material = matUniform.materials[push_constants.materialIdx]; if(material.hasTexture == 1){ vec4 texColor = texture(textSampler[material.textureIdx],inTextCoords); - if(texColor.a >= 0.9){discard;} outAlbedo = texColor; } else{ outAlbedo = material.diffuseColor; } + vec4 Opacity = vec4(outAlbedo.a,outAlbedo.a,outAlbedo.a,1); + if(material.OpacityFactor != 1) Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1); + if(material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES){ + Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords); + } + + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf/3; + if(opacityf >= 0.9){discard;} + + outAlbedo = vec4(outAlbedo.rgb, opacityf); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_translucent_fragment.glsl.spv b/resources/EngineResources/shaders/scene_translucent_fragment.glsl.spv index 382a9ad..53ea5ee 100644 Binary files a/resources/EngineResources/shaders/scene_translucent_fragment.glsl.spv and b/resources/EngineResources/shaders/scene_translucent_fragment.glsl.spv differ diff --git a/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl b/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl index 1bdcf4a..58d8529 100644 --- a/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl +++ b/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl @@ -12,6 +12,9 @@ layout(location = 1) out vec4 outAlbedo ; layout(location = 0) out vec4 outPos; layout(location = 2) out vec4 outNormal; layout(location = 3) out vec4 outPBR; +layout(location = 4) out vec4 outEmissive; +layout(location = 5) out vec4 outTranslucency; +layout(location = 6) out vec4 outOpacity; const float bayerMatrix[16] = float[]( 0.0 / 16.0, 8.0 / 16.0, 2.0 / 16.0, 10.0 / 16.0, @@ -22,16 +25,26 @@ const float bayerMatrix[16] = float[]( struct Material { - vec4 diffuseColor; - uint hasTexture; - uint textureIdx; - uint hasNormalMap; - uint normalMapIdx; - uint hasRoughMap; - uint roughMapIdx; - float roughnessFactor; - float metallicFactor; + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 }; + layout(set = 2, binding = 0) readonly buffer MaterialUniform { Material materials[]; } matUniform; @@ -64,6 +77,17 @@ void main() outAlbedo = material.diffuseColor; } + vec4 Opacity = vec4(outAlbedo.a,outAlbedo.a,outAlbedo.a,1); + if(material.OpacityFactor != 1) Opacity = vec4(material.OpacityFactor, material.OpacityFactor, material.OpacityFactor, 1); + if(material.hasOpacityMap > 0 && material.OpacityMapIdx < MAX_TEXTURES){ + Opacity = texture(textSampler[material.OpacityMapIdx], inTextCoords); + } + outOpacity = Opacity; + + float opacityf = Opacity.x + Opacity.y + Opacity.z; + opacityf = opacityf/3; + + outAlbedo = vec4(outAlbedo.rgb, opacityf); if(outAlbedo.a >= 0.75 || outAlbedo.a < 0.05f) discard; @@ -83,6 +107,18 @@ void main() metallicFactor = material.metallicFactor; } + vec4 emissive = material.emissiveColour; + if (material.hasEmissiveMap > 0 && material.emissiveMapIdx < MAX_TEXTURES) { + emissive = texture(textSampler[material.emissiveMapIdx], inTextCoords); + } + outEmissive = emissive; + + vec4 Translucency = vec4(material.translucencyFactor,material.translucencyFactor,material.translucencyFactor,1); + if(material.hasTranslucencyMap > 0 && material.translucencyMapIdx < MAX_TEXTURES){ + Translucency = texture(textSampler[material.translucencyMapIdx], inTextCoords); + } + outTranslucency = Translucency; + outPBR = vec4(ao, roughnessFactor, metallicFactor, outAlbedo.a); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl.spv b/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl.spv index e6305d2..960f751 100644 Binary files a/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl.spv and b/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl.spv differ diff --git a/resources/EngineResources/shaders/shadow_frag.glsl b/resources/EngineResources/shaders/shadow_frag.glsl index b0619e1..0ba66bb 100644 --- a/resources/EngineResources/shaders/shadow_frag.glsl +++ b/resources/EngineResources/shaders/shadow_frag.glsl @@ -9,17 +9,25 @@ 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; + vec4 diffuseColor; //16 + uint hasTexture; //20 + uint textureIdx; //24 + uint hasNormalMap; //28 + uint normalMapIdx; //32 + uint hasRoughMap; //36 + uint roughMapIdx; //40 + float roughnessFactor; //44 + float metallicFactor; //48 + vec4 emissiveColour; //64 + uint hasEmissiveMap; //68 + uint emissiveMapIdx; //72 + uint hasTranslucencyMap; //76 + uint translucencyMapIdx; //80 + float translucencyFactor; //84 + uint hasOpacityMap; //88 + uint OpacityMapIdx; //92 + float OpacityFactor; //96 }; - layout(set = 1, binding = 0) uniform sampler2D textSampler[MAX_TEXTURES]; layout(set = 2, binding = 0) readonly buffer MaterialUniform { Material materials[]; diff --git a/resources/EngineResources/shaders/shadow_geometry.glsl b/resources/EngineResources/shaders/shadow_geometry.glsl index f96fc9e..2649a50 100644 --- a/resources/EngineResources/shaders/shadow_geometry.glsl +++ b/resources/EngineResources/shaders/shadow_geometry.glsl @@ -12,18 +12,18 @@ 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]; + 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(); + 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(); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/skybox_fragment.glsl b/resources/EngineResources/shaders/skybox_fragment.glsl index 4086d0e..056c61d 100644 --- a/resources/EngineResources/shaders/skybox_fragment.glsl +++ b/resources/EngineResources/shaders/skybox_fragment.glsl @@ -7,5 +7,5 @@ layout(location = 1) out vec4 outColor; layout(set = 2, binding = 0) uniform samplerCube skyboxSampler; void main() { - outColor = texture(skyboxSampler, outTexCoords);// * vec4(0.0,0.05,0.1,1); + outColor = texture(skyboxSampler, outTexCoords) * vec4(0.0,0.05,0.1,1); } \ No newline at end of file diff --git a/resources/EngineResources/shaders/skybox_fragment.glsl.spv b/resources/EngineResources/shaders/skybox_fragment.glsl.spv index 3f18f85..6842753 100644 Binary files a/resources/EngineResources/shaders/skybox_fragment.glsl.spv and b/resources/EngineResources/shaders/skybox_fragment.glsl.spv differ diff --git a/resources/EngineResources/shaders/skybox_vertex.glsl b/resources/EngineResources/shaders/skybox_vertex.glsl index 1a980ef..e5f4f14 100644 --- a/resources/EngineResources/shaders/skybox_vertex.glsl +++ b/resources/EngineResources/shaders/skybox_vertex.glsl @@ -14,5 +14,5 @@ void main() { outTexCoords = inPosition; mat4 skyView = mat4(mat3(uboView.view)); vec4 pos = uboProj.proj * skyView * vec4(inPosition, 1.0); - gl_Position = vec4(pos.xy, pos.w, pos.w); + gl_Position = vec4(pos.xy, 0.0, pos.w); } diff --git a/resources/EngineResources/shaders/skybox_vertex.glsl.spv b/resources/EngineResources/shaders/skybox_vertex.glsl.spv index ad6646e..bf0a2ce 100644 Binary files a/resources/EngineResources/shaders/skybox_vertex.glsl.spv and b/resources/EngineResources/shaders/skybox_vertex.glsl.spv differ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java index 777fd24..934b806 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java @@ -45,6 +45,12 @@ public class OpenGLRenderer implements Renderer{ private GLCapabilities glCapabilities = null; private SceneRender sceneRenderer = null; private OpenGLGuiRenderer GuiRenderer; + private volatile boolean RebuildShadowsRequested = false; + + @Override + public void RequestRebuildShadows() { + RebuildShadowsRequested = true; + } public OpenGLGuiRenderer GetGuiRenderer(){return GuiRenderer;} @@ -108,6 +114,11 @@ public class OpenGLRenderer implements Renderer{ frameTimeNS = newFrameTimeNS; } + @Override + public void RebuildShadows() { + + } + public void Resize(int width, int height) { GuiRenderer.Resize(width, height); //sceneRenderer.Resize(width, height); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java index 35230bc..26f4da1 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/Renderer.java @@ -61,4 +61,8 @@ public interface Renderer { public void ForwardRender(EngineInstance engineInstance); public void render(EngineInstance engineInstance); + + public void RebuildShadows(); + + public void RequestRebuildShadows(); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java index bef8d2b..a1a9ebc 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/VulkanRenderer.java @@ -55,7 +55,7 @@ public class VulkanRenderer implements Renderer { private final LightRenderer lightRenderer; private final PostProcess PostProcessor; private final SwapChainRender swapChainRender; - private final ShadowRenderer shadowRender; + private ShadowRenderer shadowRender; private final GuiRenderer GuiRender; private int CurrentFrame; private final VulkanContext RendererContext; @@ -68,6 +68,13 @@ public class VulkanRenderer implements Renderer { private final boolean Deferred; private float LastGamma = 0.8545f; + private volatile boolean RebuildShadowsRequested = false; + + @Override + public void RequestRebuildShadows() { + RebuildShadowsRequested = true; + } + public TextureCache GetTextureCache(){return textureCache;} public MaterialsCache GetMaterialsCache(){return materialsCache;} @@ -160,7 +167,7 @@ public class VulkanRenderer implements Renderer { Logger.debug("Loaded {} models", Models.size()); sceneRender.LoadMaterials(RendererContext,materialsCache,textureCache); - shadowRender.loadMaterials(RendererContext, materialsCache, textureCache); + if(shadowRender != null) shadowRender.loadMaterials(RendererContext, materialsCache, textureCache); spriteRenderer.CompileSprites(RendererContext,modelsCache, textureCache); spriteRenderer.LoadMaterials(RendererContext,materialsCache,textureCache); GuiRender.LoadTextures(RendererContext,initData.GuiTextures(),textureCache); @@ -213,15 +220,6 @@ public class VulkanRenderer implements Renderer { var CommandPool = CommandPools[CurrentFrame]; var CommandBuffer = CommandBuffers[CurrentFrame]; - RecordingStart(CommandPool, CommandBuffer); - - sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,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()); - spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame); - GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment()); int ImageIndex; if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[imageAcquisitionIndex])) < 0){ @@ -229,6 +227,20 @@ public class VulkanRenderer implements Renderer { return; } + RecordingStart(CommandPool, CommandBuffer); + + sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame); + boolean RenderShadows = ShadowRenderer.AllowShadowRendering() && EngineConfig.getInstance().RenderShadows(); + //lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(), shadowRender.getShadowAttachment(), CurrentFrame, shadowRender.getCascadeShadows(CurrentFrame)); + if(RenderShadows) { + shadowRender.render(engineInstance, RendererContext, CommandBuffer, modelsCache, materialsCache, CurrentFrame); + lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(), shadowRender.getShadowAttachment(), CurrentFrame, shadowRender.getCascadeShadows(CurrentFrame)); + } else lightRenderer.render(engineInstance, RendererContext, CommandBuffer, sceneRender.GetMRTAttachments(),CurrentFrame); + PostProcessor.Render(RendererContext,CommandBuffer,lightRenderer.getAttachment()); + spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame); + GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment()); + + swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex); RecordingStop(CommandBuffer); @@ -243,12 +255,6 @@ public class VulkanRenderer implements Renderer { WaitForFence(CurrentFrame); //problem child found var CommandPool = CommandPools[CurrentFrame]; var CommandBuffer = CommandBuffers[CurrentFrame]; - RecordingStart(CommandPool, CommandBuffer); - - sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame); - PostProcessor.Render(RendererContext,CommandBuffer,sceneRender.GetAttachmentColour()); - spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame); - GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment()); int ImageIndex; if (Resize || (ImageIndex = swapChain.FetchNextImage(RendererContext.GetDevice(), PresentCompleteSemaphores[CurrentFrame])) < 0){ @@ -256,6 +262,13 @@ public class VulkanRenderer implements Renderer { return; } + RecordingStart(CommandPool, CommandBuffer); + + sceneRender.Render(engineInstance,RendererContext,CommandBuffer, modelsCache,materialsCache,CurrentFrame); + PostProcessor.Render(RendererContext,CommandBuffer,sceneRender.GetAttachmentColour()); + spriteRenderer.Render(engineInstance,RendererContext,CommandBuffer,PostProcessor.GetAttachment(),modelsCache,CurrentFrame); + GuiRender.Render(RendererContext,CommandBuffer,CurrentFrame,PostProcessor.GetAttachment()); + swapChainRender.Render(RendererContext,CommandBuffer,PostProcessor.GetAttachment(),ImageIndex); RecordingStop(CommandBuffer); @@ -267,9 +280,35 @@ public class VulkanRenderer implements Renderer { public void render(EngineInstance engineInstance){ if(! RenderThread.AllowRender()) return; + + if (RebuildShadowsRequested) { + RebuildShadowsRequested = false; + RebuildShadows(); + } + if(Deferred) DeferredRender(engineInstance); else ForwardRender(engineInstance); } + + @Override + public void RebuildShadows() { + if (!Deferred || shadowRender == null || lightRenderer == null) { + return; + } + + ShadowRenderer.AllowShadowRendering(false); + RendererContext.GetDevice().waitIdle(); + + shadowRender.RebuildPipelineAndRenderingAttachments(RendererContext); + + List attachments = new ArrayList<>(sceneRender.GetMRTAttachments().GetColourAttachments()); + attachments.add(shadowRender.getShadowAttachment()); + lightRenderer.updateAttachmentDescriptors(RendererContext, attachments); + + RendererContext.GetDevice().waitIdle(); + ShadowRenderer.AllowShadowRendering(true); + } + private void resize(EngineInstance engineInstance){ Window window = engineInstance.window(); if(window.getWidth() == 0 && window.getHeight() == 0){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java index f0dd0ff..19c2a68 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/EngineConfig.java @@ -1,6 +1,7 @@ package net.halbear.Terrain4J.EngineCore.Logic; +import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.DeferredSceneRender; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DisplayToScreen.ForwardSceneRender; import net.halbear.Terrain4J.EngineCore.ServerNetworking.ClientSideNetworkUtils; @@ -92,6 +93,16 @@ public class EngineConfig { public float SoundVolume = 0.0f; public float WeaponVolume = 0.0f; public float AmbientVolume = 0.0f; + public float MaxShadowDistance = 16384.0f; + + + public float MaxShadowDistance(){return MaxShadowDistance;} + public void MaxShadowDistance(float newDistance){ MaxShadowDistance = newDistance;} + + public boolean RenderShadows = true; + + public boolean RenderShadows() {return RenderShadows;} + public void RenderShadows(boolean renderShadows) {RenderShadows = renderShadows;} public float PlayerOnline = 1.0f; @@ -158,7 +169,12 @@ public class EngineConfig { public String GetLoadingScreenImageLocation(){return LoadingScreenLocation;} public void SetLoadingScreenImageLocation(String location){this.LoadingScreenLocation = location;} public int GetMaxVulkanCrashes(){return MaxVulkanCrashesAllowed;} - public void SetShadowMapSize(int ShadowSize){this.ShadowMapSize = ShadowSize;} + public void SetShadowMapSize(int ShadowSize){ + this.ShadowMapSize = ShadowSize; + if (PrimaryRuntime.GetRenderThread() != null && PrimaryRuntime.GetRenderThread().GetRenderer() != null) { + PrimaryRuntime.GetRenderThread().GetRenderer().RequestRebuildShadows(); + } + } public int GetShadowMapSize(){return ShadowMapSize;} public void SetRenderer(Renderer renderer){this.renderer = renderer;} public boolean DeferredRendering(){return renderer == Renderer.Deferred;} @@ -320,9 +336,11 @@ public class EngineConfig { FOV = (float)(DegToRad * Float.parseFloat(EngineConfigVar.getOrDefault("field_of_view", 60.0f).toString())); zNearPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_near_plane", 1.0f).toString())); zFarPlane = (Float.parseFloat(EngineConfigVar.getOrDefault("z_far_plane", 100.0f).toString())); + MaxShadowDistance = (Float.parseFloat(EngineConfigVar.getOrDefault("max_shadow_distance", 16384.0f).toString())); AAValue = (Integer.parseInt(EngineConfigVar.getOrDefault("anti_alias_mode", 1).toString())); renderer = Integer.parseInt(EngineConfigVar.getOrDefault("Renderer", 1).toString()) == 0 ? Renderer.Forward: Renderer.Deferred; - ShadowMapSize = Integer.parseInt(EngineConfigVar.getOrDefault("ShadowMapSize", 4096).toString()); + ShadowMapSize = Integer.parseInt(EngineConfigVar.getOrDefault("ShadowMapSize", 2048).toString()); + RenderShadows = Boolean.parseBoolean(EngineConfigVar.getOrDefault("RenderShadows", true).toString()); MaxVulkanCrashesAllowed = Integer.parseInt(EngineConfigVar.getOrDefault("MaxAllowedVulkanCrashes", 10).toString()); ServerPort = Integer.parseInt(EngineConfigVar.getOrDefault("server_port", 25565).toString()); CompatibilityMode = Boolean.parseBoolean(EngineConfigVar.getOrDefault("compatibility_mode", false).toString()); @@ -377,6 +395,7 @@ public class EngineConfig { EngineConfigVar.setProperty("ShaderRecompiling","true"); EngineConfigVar.setProperty("throttle_accuracy","100000"); EngineConfigVar.setProperty("throttle_on_unfocus","true"); + EngineConfigVar.setProperty("RenderShadows","true"); EngineConfigVar.setProperty("field_of_view","60"); EngineConfigVar.setProperty("z_near_plane","1"); EngineConfigVar.setProperty("z_far_plane","100"); @@ -384,6 +403,7 @@ public class EngineConfig { EngineConfigVar.setProperty("DefaultTexturePath",DefaultTexturePath); EngineConfigVar.setProperty("MaxDescriptors","1000"); EngineConfigVar.setProperty("anti_alias_mode","1"); + EngineConfigVar.setProperty("max_shadow_distance","16384"); EngineConfigVar.setProperty("server","false"); EngineConfigVar.setProperty("ShadowMapSize","4096"); EngineConfigVar.setProperty("LoadingScreenLocation",LoadingScreenLocation); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/SeparatingAxisTheoremTester.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/SeparatingAxisTheoremTester.java index 8df545d..539fdc3 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/SeparatingAxisTheoremTester.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/SeparatingAxisTheoremTester.java @@ -15,7 +15,6 @@ overlap (least "penetration" or intersection amount) is the collision normal, face contacts are "resolved into a full contact manifold"(whatever that means) by clipping the incident face against the side planes of the reference face, this is what gives stable multipoint contact (e.g. a box resting flat on a floor gets 4 contact points, not 1) -I'm not gonna lie, I asked Google AI Overview for help on this one, and it did NOT help, but it *did* provide some pretty useful information on how to do it For a good explanation, visit this https://dyn4j.org/2010/01/sat/*/ public class SeparatingAxisTheoremTester { diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java index ef247a4..816cf20 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/WorldPhysicsManager.java @@ -82,6 +82,7 @@ public class WorldPhysicsManager { SweepForTunneling(); ResetGroundedFlags(); ResolveAllCollisions(); + SyncRigidBodiesToActors(); Accumulator -= FixedTimeStep; stepsRun++; } @@ -117,23 +118,6 @@ public class WorldPhysicsManager { Set 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 bucket : SpatialHashGrid.Buckets()) { int size = bucket.size(); for (int i = 0; i < size; i++) { @@ -152,6 +136,7 @@ public class WorldPhysicsManager { TryResolve(dyn, stat, worldBounds, testedPairs); } } + } private static boolean IsClientRemoteNetworkBody(RigidBody body) { diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java index 4573150..4053f10 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Rendering/ModelCompiler.java @@ -32,8 +32,7 @@ import static org.lwjgl.assimp.Assimp.*; public class ModelCompiler { private static final Pattern EMBED_TEXT_ID = Pattern.compile("\\*([0-9)]+)"); private static final int FLAGS = aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices - | aiProcess_Triangulate | aiProcess_FixInfacingNormals | aiProcess_CalcTangentSpace - | aiProcess_PreTransformVertices; + | aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_PreTransformVertices; @Parameter(names = "-model", description = "Model Path", required = true) private String ModelPath; @@ -108,14 +107,23 @@ public class ModelCompiler { public static MaterialData ProcessMaterial(AIScene aiScene, AIMaterial aiMaterial, String ModelName, String BaseDirectory, int Position) throws IOException{ Vector4f diffuse = new Vector4f(); AIColor4D colour = AIColor4D.create(); + AIColor4D emissive_colour = AIColor4D.create(); int Result = aiGetMaterialColor(aiMaterial, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_NONE, 0, colour); if(Result == aiReturn_SUCCESS){ diffuse.set(colour.r(), colour.g(), colour.b(), colour.a()); } + Vector4f emissiveColour = new Vector4f(1,1,1,0); + Result = aiGetMaterialColor(aiMaterial, AI_MATKEY_COLOR_EMISSIVE, aiTextureType_NONE, 0, emissive_colour); + if(Result == aiReturn_SUCCESS){ + emissiveColour.set(emissive_colour.r(), emissive_colour.g(), emissive_colour.b(), emissive_colour.a()); + } String DiffuseTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_DIFFUSE); String NormalTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_NORMALS); + String EmissiveTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_EMISSIVE); + String TranslucencyTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_TRANSMISSION); String MetallicRoughTexture = ProcessTexture(aiScene, aiMaterial, BaseDirectory, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); + String OpacityTexture = ProcessTexture(aiScene,aiMaterial,BaseDirectory,aiTextureType_OPACITY); float[] MetallicArray = new float[]{0.0f}; int[] MaxPointer = new int[]{1}; @@ -130,8 +138,26 @@ public class ModelCompiler { RoughnessArray = new float[]{0.0f}; } + float[] EmissiveArray = new float[]{0.0f}; + Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_EMISSIVE_INTENSITY,aiTextureType_NONE,0,EmissiveArray,MaxPointer); + if(Result == aiReturn_SUCCESS){ + emissiveColour.set(emissiveColour.x,emissiveColour.y,emissiveColour.z,EmissiveArray[0]); + } - return new MaterialData(ModelName + "-mat-" + Position,DiffuseTexture,NormalTexture, MetallicRoughTexture,diffuse,RoughnessArray[0],MetallicArray[0]); + float[] TranslucencyArray = new float[]{0.0f}; + Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_TRANSMISSION_FACTOR,aiTextureType_NONE,0,TranslucencyArray,MaxPointer); + if(Result != aiReturn_SUCCESS){ + TranslucencyArray = new float[]{0.0f}; + } + + float[] OpacityArray = new float[]{0.0f}; + + Result = aiGetMaterialFloatArray(aiMaterial,AI_MATKEY_OPACITY,aiTextureType_NONE,0,OpacityArray,MaxPointer); + if(Result != aiReturn_SUCCESS){ + OpacityArray = new float[]{0.0f}; + } + + return new MaterialData(ModelName + "-mat-" + Position,DiffuseTexture,NormalTexture, MetallicRoughTexture,diffuse,RoughnessArray[0],MetallicArray[0], EmissiveTexture,emissiveColour, TranslucencyTexture, TranslucencyArray[0], OpacityTexture, OpacityArray[0]); } public static MeshData ProcessMesh(AIMesh aiMesh, List MaterialList, int MeshPosition, ModelBinaryData BinaryData) throws IOException { diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java index ed6ca3a..012c25d 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -99,12 +99,12 @@ public class GameCore implements GameLogic { Scene scene = (Scene) engineInstance.scene(); List models = new ArrayList<>(); List materials = new ArrayList<>(); -// ModelData SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json"); -// List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json"); -// ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json"); -// List SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json"); -// 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 SponzaData = ModelLoader.LoadModel("resources/models/Cafe/exterior.json"); + List SponzaMaterial = ModelLoader.LoadMaterials("resources/models/Cafe/exterior_mat.json"); + ModelData SponzaData1 = ModelLoader.LoadModel("resources/models/Cafe/interior.json"); + List SponzaMaterial1= ModelLoader.LoadMaterials("resources/models/Cafe/interior_mat.json"); + 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)); @@ -113,7 +113,7 @@ public class GameCore implements GameLogic { // 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)); +// Actor3D treeEntity = new Actor3D("treeEntity", treeModel.ID(), new Vector3f(0.0f, -100.0f, 0.0f)); // treeEntity.SetScale(10f); // scene.AddActor(treeEntity); // materials.addAll(ModelLoader.LoadMaterials("resources/models/Forest/forest_mat.json")); @@ -158,10 +158,10 @@ public class GameCore implements GameLogic { } boolean createOfflinePlayer = !PrimaryRuntime.IsServer && !ClientSideNetworkUtils.Connected; -// materials.addAll(SponzaMaterial); -// materials.addAll(SponzaMaterial1); -// models.add(SponzaData); -// models.add(SponzaData1); + materials.addAll(SponzaMaterial); + materials.addAll(SponzaMaterial1); + models.add(SponzaData); + models.add(SponzaData1); materials.addAll(MelonaMat); materials.addAll(CollisionVisualisationMat); materials.addAll(MelonaMaterial); @@ -191,49 +191,68 @@ public class GameCore implements GameLogic { } scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f); - scene.GetLightingManager().SetAmbientLightIntensity(0.3f); -// scene.GetLightingManager().GetAmbientLightColour().set(0.3f, 0.35f, 0.5f); -// 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(0.25f, 1.0f, 1.5f),new Vector3f(0.0f, -1.0f, 0.0f), true, 6.0f); + scene.GetLightingManager().SetAmbientLightIntensity(0.15f); + scene.GetLightingManager().GetAmbientLightColour().set(0.3f, 0.35f, 0.5f); + scene.GetLightingManager().SetAmbientLightIntensity(0.05f); + + SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.3f), true, 4.00f); + SkyLight = new Light(new Vector3f(0.25f, 0.75f, 1.3f),new Vector3f(0.0f, -1.0f, 0.0f), true, 4.0f); SkyLight.SetType(Light.LightType.Directional); List 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(-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(-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(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,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(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(-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(-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(-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(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,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(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(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(3.0f,2.25f,0.0f),new Vector3f(350.0f, 1525.0f, -420.0f),false,4000.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(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(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(615.8f, 305.5f, -904.1f).div(10.0f),false,200.0f)); + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(425.4f, 305.5f, -541.0f).div(10.0f),false,200.0f)); + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(501.4f, 305.5f, -102.7f).div(10.0f),false,200.0f)); + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(803.0f, 305.5f, 50.2f).div(10.0f),false,200.0f)); + + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(720.4f, 261.6f, -329.2f).div(10.0f),false,75.0f)); + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(879.4f,261.6f,-246.3f).div(10.0f),false,75.0f)); + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(1037.7f,261.6f,-155.0f).div(10.0f),false,75.0f)); + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(663.4f,261.6f,-468.9f).div(10.0f),false,75.0f)); + + lights.add(new Light(new Vector3f(1.9f + (float)Math.random(),1.5f,1.0f),new Vector3f(772.3f,243.7f,-513.7f).div(10.0f),false,50.0f)); + + lights.add(new Light(new Vector3f(1.2f + (float)Math.random(),1.1f,1.0f),new Vector3f(193.1f,260.7f,-859.3f).div(10.0f),false,50.0f)); + lights.add(new Light(new Vector3f(1.2f + (float)Math.random(),1.1f,1.0f),new Vector3f(51.0f,260.7f,-603.0f).div(10.0f),false,50.0f)); + lights.add(new Light(new Vector3f(1.2f + (float)Math.random(),1.1f,1.0f),new Vector3f(-95.0f,260.7f,-334.2f).div(10.0f),false,50.0f)); + lights.add(new Light(new Vector3f(1.2f + (float)Math.random(),1.1f,1.0f),new Vector3f(41.5f,260.7f,5.7f).div(10.0f),false,50.0f)); + lights.add(new Light(new Vector3f(1.2f + (float)Math.random(),1.1f,1.0f),new Vector3f(335.8f,260.7f,144.6f).div(10.0f),false,50.0f)); + lights.add(new Light(new Vector3f(1.2f + (float)Math.random(),1.1f,1.0f),new Vector3f(616.9f,260.7f,255.4f).div(10.0f),false,50.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(3.0f,2.25f,0.0f),new Vector3f(350.0f, 1500.0f, -420.0f),false,10000.0f)); +// lights.add(new Light(new Vector3f(3.0f,2.25f,0.0f),new Vector3f(400.0f, 1550.0f, -350.0f),false,10000.0f)); lights.add(SkyLight); ILight[] lightArr = new ILight[lights.size()]; @@ -246,27 +265,29 @@ public class GameCore implements GameLogic { } //if(PrimaryRuntime.IsServer) { permutation.GeneratePermutationArray(5783904701859L); - 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++){ - 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)); - } +// 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++){ +// SpawnNewActor(engineInstance, new Vector3f(-5 + (float)Math.random() * 10,10 + (float)Math.random() * 10, -5 + (float)Math.random() * 10), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); +// } //} Settings.textBuffer.set(ClientSideNetworkUtils.ServerIP); Settings.UsernameBuffer.set("Player"); return new InitData(models,materials,guiTextures); } public static float lightAngle = 70; + public static float lightAnglex = 0; private void updateDirLight() { - float zValue = (float) Math.cos(Math.toRadians(lightAngle)); + float zValue = (float) Math.cos(Math.toRadians(lightAngle)) + (float) Math.cos(Math.toRadians(lightAnglex)); float yValue = (float) Math.sin(Math.toRadians(lightAngle)); + float xValue = (float) Math.sin(Math.toRadians(lightAnglex)); Vector3f lightDirection = SkyLight.GetPosition(); - lightDirection.x = 0; + lightDirection.x = xValue; lightDirection.y = yValue; lightDirection.z = zValue; lightDirection.normalize(); @@ -502,6 +523,8 @@ public class GameCore implements GameLogic { } } + int GUI_MODE = 1; + @Override public void Input(EngineInstance engineInstance, long FrameDiffNanoSeconds) { if(PrimaryRuntime.IsServer || RenderThread.Headless) return; @@ -510,7 +533,7 @@ public class GameCore implements GameLogic { scene.GlobalInput(engineInstance,FrameDiffNanoSeconds, null, MOVEMENT_SPEED,this); KeyboardInput input = engineInstance.window().getKeyboardInput(); if(input.keySinglePress(GLFW_KEY_F3)){ - Scene.GUI_MODE = (Scene.GUI_MODE + 1) % 2; + GUI_MODE = (GUI_MODE + 1) % 3; } if(input.keyPressed(GLFW_KEY_UP)){ lightAngle = (lightAngle + 0.5f) % 360; @@ -520,6 +543,14 @@ public class GameCore implements GameLogic { lightAngle = (lightAngle - 0.5f) % 360; updateDirLight(); } + if(input.keyPressed(GLFW_KEY_RIGHT)){ + lightAnglex = (lightAnglex + 0.5f) % 360; + updateDirLight(); + } + if(input.keyPressed(GLFW_KEY_LEFT)){ + lightAnglex = (lightAnglex - 0.5f) % 360; + updateDirLight(); + } if (input.keySinglePress(GLFW_KEY_ESCAPE)) { StartMenuActive = !StartMenuActive; StartMenu.GameStarted = StartMenuActive; @@ -587,7 +618,7 @@ public class GameCore implements GameLogic { StartMenuActive = false; } } else { - engineInstance.scene().RenderGUIs(engineInstance, frameTimeNS, this); + if(GUI_MODE == 1)engineInstance.scene().RenderGUIs(engineInstance, frameTimeNS, this); if (ChangeGraphicsSettings) { ImGuiViewport viewport = ImGui.getMainViewport(); float CenterX = viewport.getWorkPosX() + viewport.getWorkSizeX() / 2.0f; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java index 17cf2f0..c71afb8 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/PerformanceOverlay.java @@ -6,6 +6,7 @@ import imgui.flag.ImGuiWindowFlags; import imgui.type.ImFloat; import net.halbear.Terrain4J.EngineCore.Logic.EngineConfig; import net.halbear.Terrain4J.EngineCore.Logic.EngineInstance; +import net.halbear.Terrain4J.EngineCore.Main.AudioInstance; import net.halbear.Terrain4J.EngineCore.Main.GameCore; import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Scene.GUIOverlay; @@ -15,6 +16,14 @@ import org.tinylog.Logger; public class PerformanceOverlay implements GUIOverlay { private final ImFloat GammaValue = new ImFloat(0.8545f); + public int[] ShadowSize = new int[]{4096}; + public int[] ShadowDistance = new int[]{1000}; + + public PerformanceOverlay(){ + ShadowSize[0] = EngineConfig.getInstance().GetShadowMapSize(); + ShadowDistance[0] = (int)EngineConfig.getInstance().MaxShadowDistance(); + } + @Override public void RenderGUI(EngineInstance engineInstance, long frameTimeNS, GameCore parent) { int windowFlags = ImGuiWindowFlags.NoDecoration @@ -48,35 +57,111 @@ public class PerformanceOverlay implements GUIOverlay { EngineConfig.getInstance().SetRenderingAPI(EngineConfig.RenderAPI.OpenGL); } ImGui.text("Presets:"); + float ZFarPlane = Math.max(EngineConfig.getInstance().GetZFarPlane(), EngineConfig.getInstance().GetZNearPlane()); if(ImGui.button("Lowest")){ parent.ChangeGraphicsSettings = true; parent.CoolDown = 2000; parent.NextAAMode = (0); ForwardSceneRender.SetDualPassRendering(false); DeferredSceneRender.SetDualPassRendering(false); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Forward); + EngineConfig.getInstance().RenderShadows(false); EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().SetShadowMapSize(1); + EngineConfig.getInstance().MaxShadowDistance(64); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); + if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.sameLine(); + if(ImGui.button("Low")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (0); + ForwardSceneRender.SetDualPassRendering(false); + DeferredSceneRender.SetDualPassRendering(false); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); + EngineConfig.getInstance().RenderShadows(true); + EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().SetShadowMapSize(256); + EngineConfig.getInstance().MaxShadowDistance((int)(ZFarPlane/4)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); } ImGui.sameLine(); if(ImGui.button("Medium")){ parent.ChangeGraphicsSettings = true; parent.CoolDown = 2000; - parent.NextAAMode = (1); + parent.NextAAMode = (0); ForwardSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); DeferredSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().RenderShadows(true); EngineConfig.getInstance().SetAlphaToCoverage(true); + EngineConfig.getInstance().SetShadowMapSize(1024); + EngineConfig.getInstance().MaxShadowDistance((int)(ZFarPlane/2)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); } ImGui.sameLine(); - if(ImGui.button("Highest")){ + if(ImGui.button("High")){ parent.ChangeGraphicsSettings = true; parent.CoolDown = 2000; - parent.NextAAMode = (4); + parent.NextAAMode = (0); ForwardSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); DeferredSceneRender.SetDualPassRendering(true); EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().RenderShadows(true); + EngineConfig.getInstance().SetShadowMapSize(4096); + EngineConfig.getInstance().MaxShadowDistance((int)(ZFarPlane)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); } + ImGui.sameLine(); + if(ImGui.button("Ultra")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (0); + ForwardSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); + DeferredSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().RenderShadows(true); + EngineConfig.getInstance().SetShadowMapSize(8192); + EngineConfig.getInstance().MaxShadowDistance( (int)(ZFarPlane * 1.5)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); + if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.text(" "); + ImGui.text("Shadows:"); + if(ImGui.button("No Shadows")){ + // parent.ChangeGraphicsSettings = true; + // parent.CoolDown = 2000; + EngineConfig.getInstance().RenderShadows(false); + } + ImGui.sameLine(); + if(ImGui.button("Cascading")){ + // parent.ChangeGraphicsSettings = true; + // parent.CoolDown = 2000; + EngineConfig.getInstance().RenderShadows(true); + } + if (ImGui.sliderInt("Shadow Map Size", ShadowSize, 16, 8192)) { + ShadowSize[0] = Math.clamp((ShadowSize[0] / 16) * 16, 16, 8192); + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + EngineConfig.getInstance().SetShadowMapSize(ShadowSize[0]); + } + if (ImGui.sliderInt("Shadow Distance", ShadowDistance, 64, (int)(ZFarPlane * 1.5))) { + ShadowDistance[0] = Math.clamp((ShadowDistance[0] / 64) * 64, 64, (int)(ZFarPlane * 1.5)); + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + EngineConfig.getInstance().MaxShadowDistance(ShadowDistance[0]); + } ImGui.text(" "); ImGui.text("anti aliasing:"); if(ImGui.button("No AA")){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/SettingsMenu.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/SettingsMenu.java index 0de0775..7edca8e 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/SettingsMenu.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/GUIs/SettingsMenu.java @@ -22,6 +22,8 @@ public class SettingsMenu implements GUIOverlay { public int[] SFX = new int[]{100}; public int[] Weapons = new int[]{100}; public int[] Ambient = new int[]{100}; + public int[] ShadowSize = new int[]{4096}; + public int[] ShadowDistance = new int[]{1000}; public ImInt ServerPort = new ImInt(25565); public final ImString textBuffer = new ImString(100); public final ImString UsernameBuffer = new ImString(24); @@ -34,6 +36,8 @@ public class SettingsMenu implements GUIOverlay { SFX[0] = (int)(EngineConfig.getInstance().SoundVolume * 100); Weapons[0] = (int)(EngineConfig.getInstance().WeaponVolume * 100); Ambient[0] = (int)(EngineConfig.getInstance().AmbientVolume * 100); + ShadowSize[0] = EngineConfig.getInstance().GetShadowMapSize(); + ShadowDistance[0] = (int)EngineConfig.getInstance().MaxShadowDistance(); AudioInstance.ApplyUniversalVolume(); @@ -191,13 +195,36 @@ public class SettingsMenu implements GUIOverlay { EngineConfig.getInstance().SetRenderingAPI(EngineConfig.RenderAPI.OpenGL); } ImGui.text("Presets:"); + float ZFarPlane = Math.max(EngineConfig.getInstance().GetZFarPlane(), EngineConfig.getInstance().GetZNearPlane()); if(ImGui.button("Lowest")){ parent.ChangeGraphicsSettings = true; parent.CoolDown = 2000; parent.NextAAMode = (0); ForwardSceneRender.SetDualPassRendering(false); DeferredSceneRender.SetDualPassRendering(false); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Forward); + EngineConfig.getInstance().RenderShadows(false); EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().SetShadowMapSize(1); + EngineConfig.getInstance().MaxShadowDistance(64); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); + if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.sameLine(); + if(ImGui.button("Low")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (0); + ForwardSceneRender.SetDualPassRendering(false); + DeferredSceneRender.SetDualPassRendering(false); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); + EngineConfig.getInstance().RenderShadows(true); + EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().SetShadowMapSize(256); + EngineConfig.getInstance().MaxShadowDistance((int)(ZFarPlane/4)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); } ImGui.sameLine(); @@ -206,20 +233,74 @@ public class SettingsMenu implements GUIOverlay { parent.CoolDown = 2000; parent.NextAAMode = (1); ForwardSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); DeferredSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().RenderShadows(true); EngineConfig.getInstance().SetAlphaToCoverage(true); + EngineConfig.getInstance().SetShadowMapSize(1024); + EngineConfig.getInstance().MaxShadowDistance((int)(ZFarPlane/2)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); } ImGui.sameLine(); - if(ImGui.button("Highest")){ + if(ImGui.button("High")){ parent.ChangeGraphicsSettings = true; parent.CoolDown = 2000; - parent.NextAAMode = (4); + parent.NextAAMode = (0); ForwardSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); DeferredSceneRender.SetDualPassRendering(true); EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().RenderShadows(true); + EngineConfig.getInstance().SetShadowMapSize(4096); + EngineConfig.getInstance().MaxShadowDistance((int)(ZFarPlane)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); } + ImGui.sameLine(); + if(ImGui.button("Ultra")){ + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + parent.NextAAMode = (0); + ForwardSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetRenderer(EngineConfig.Renderer.Deferred); + DeferredSceneRender.SetDualPassRendering(true); + EngineConfig.getInstance().SetAlphaToCoverage(false); + EngineConfig.getInstance().RenderShadows(true); + EngineConfig.getInstance().SetShadowMapSize(8192); + EngineConfig.getInstance().MaxShadowDistance( (int)(ZFarPlane * 1.5)); + ShadowDistance[0] = (int)Math.clamp(EngineConfig.getInstance().MaxShadowDistance(), 64, (int)(ZFarPlane * 1.5)); + ShadowSize[0] = (int)Math.clamp((EngineConfig.getInstance().GetShadowMapSize() / 16) * 16, 16, 8192); + if(engineInstance.window().GetLinkedApi() == EngineConfig.RenderAPI.Vulkan)PrimaryRuntime.GetRenderThread().GetRenderer().GetSceneRender().RebuildPipelines(PrimaryRuntime.GetRenderThread().GetRenderer().GetVulkanContext()); + } + ImGui.text(" "); + ImGui.text("Shadows:"); + if(ImGui.button("No Shadows")){ + // parent.ChangeGraphicsSettings = true; + // parent.CoolDown = 2000; + EngineConfig.getInstance().RenderShadows(false); + } + ImGui.sameLine(); + if(ImGui.button("Cascading")){ + // parent.ChangeGraphicsSettings = true; + // parent.CoolDown = 2000; + EngineConfig.getInstance().RenderShadows(true); + } + if (ImGui.sliderInt("Shadow Map Size", ShadowSize, 16, 8192)) { + ShadowSize[0] = Math.clamp((ShadowSize[0] / 16) * 16, 16, 8192); + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + EngineConfig.getInstance().SetShadowMapSize(ShadowSize[0]); + } + if (ImGui.sliderInt("Shadow Distance", ShadowDistance, 64, (int)(ZFarPlane * 1.5))) { + ShadowDistance[0] = Math.clamp((ShadowDistance[0] / 64) * 64, 64, (int)(ZFarPlane * 1.5)); + parent.ChangeGraphicsSettings = true; + parent.CoolDown = 2000; + EngineConfig.getInstance().MaxShadowDistance(ShadowDistance[0]); + } + ImGui.text(" "); ImGui.text("anti aliasing:"); ImGui.text("Selected AA: " + EngineConfig.getInstance().RenderAAType().name()); if(ImGui.button("No AA")){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java index 470790e..885267d 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Scene.java @@ -156,9 +156,9 @@ public class Scene implements IScene { if(!PrimaryRuntime.IsServer && !RenderThread.Headless) { GUIReg.put("PerformanceOverlay",new PerformanceOverlay()); - ActiveGUIs.add("PerformanceOverlay"); + ActiveGUIs.add("PerformanceOverlay"); GUIReg.put("ChatLog",new GameChat()); - ActiveGUIs.add("ChatLog"); + //ActiveGUIs.add("ChatLog"); } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Projection/Project3D.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Projection/Project3D.java index be94eeb..0dd11ed 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Projection/Project3D.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Universal/Projection/Project3D.java @@ -32,6 +32,22 @@ public class Project3D { Resize(LastWidth,LastHeight); } + public Project3D GetReversedFarPlanes(){ + Project3D newProjection; + float zNear = Math.max(ZFarPlane, ZNearPlane); + float zFar = Math.min(ZFarPlane, ZNearPlane); + newProjection = new Project3D(FOV, zNear, zFar, LastWidth, LastHeight); + return newProjection; + } + + public Project3D GetNormalFarPlanes(){ + Project3D newProjection; + float zNear = Math.min(ZFarPlane, ZNearPlane); + float zFar = Math.max(ZFarPlane, ZNearPlane); + newProjection = new Project3D(FOV, zNear, zFar, LastWidth, LastHeight); + return newProjection; + } + public void ChangeFOV(float newFOV){ FOV = newFOV; Resize(LastWidth,LastHeight); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/LightRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/LightRenderer.java index 5b102d6..0423e96 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/LightRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/LightRenderer.java @@ -15,6 +15,7 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.P 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.Rendering.Shadows.ShadowRenderer; 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; @@ -41,17 +42,22 @@ import static org.lwjgl.vulkan.VK13.*; public class LightRenderer { 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_NOSHADOW_ATT = "LIGHT_DESC_ID_NOSHADOW_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_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_with_shadows_frag.glsl"; private static final String FRAGMENT_SHADER_FILE_SPV = FRAGMENT_SHADER_FILE_GLSL + ".spv"; + private static final String NO_SHADOWS_FRAGMENT_SHADER_FILE_GLSL = "resources/EngineResources/shaders/lighting_frag.glsl"; + private static final String NO_SHADOWS_FRAGMENT_SHADER_FILE_SPV = NO_SHADOWS_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_SPV = VERTEX_SHADER_FILE_GLSL + ".spv"; private final DescriptorSetLayout AttachmentDescriptorSetLayout; + private final DescriptorSetLayout NoShadowsAttachmentDescriptorSetLayout; private final VkClearValue ClearValueColour; private final Pipeline pipeline; + private final Pipeline NoShadowsPipeline; private final TextureSampler textureSampler; private Attachment AttachmentColour; private VkRenderingAttachmentInfo.Buffer AttachmentInfoColour; @@ -72,7 +78,7 @@ public class LightRenderer { RenderInfo = CreateRenderInfo(AttachmentColour, AttachmentInfoColour); lightSpecConsts = new LightSpecConsts(); - ShaderModule[] shaderModules = CreateShaderModules(VkCtx, lightSpecConsts); + ShaderModule[] shaderModules = CreateShaderModules(VkCtx, lightSpecConsts,true); var textureSamplerInfo = new TextureSamplerInfo(VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_BORDER_COLOR_INT_OPAQUE_BLACK, 1, true); @@ -83,7 +89,7 @@ public class LightRenderer { descSetLayouts[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i, 1, VK_SHADER_STAGE_FRAGMENT_BIT); } AttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, descSetLayouts); - CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, attachments, textureSampler); + CreateAttachmentDescriptorSet(VkCtx, AttachmentDescriptorSetLayout, attachments, textureSampler, true); StorageDescriptorSetLayout = new DescriptorSetLayout(VkCtx, new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 0, 1, VK_SHADER_STAGE_FRAGMENT_BIT)); @@ -99,6 +105,19 @@ public class LightRenderer { shadowMatrices = CreateShadowMatrixBuffers(VkCtx, StorageDescriptorSetLayout); pipeline = createPipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{AttachmentDescriptorSetLayout, StorageDescriptorSetLayout, StorageDescriptorSetLayout, SceneDescriptorSetLayout}); + Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VkCtx)); + + numAttachments = attachments.size(); + DescriptorSetLayout.LayoutInformation[] OldDescSetLayouds = new DescriptorSetLayout.LayoutInformation[numAttachments]; + for (int i = 0; i < numAttachments; i++) { + OldDescSetLayouds[i] = new DescriptorSetLayout.LayoutInformation(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, i, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + } + NoShadowsAttachmentDescriptorSetLayout = new DescriptorSetLayout(VkCtx, OldDescSetLayouds); + CreateAttachmentDescriptorSet(VkCtx, NoShadowsAttachmentDescriptorSetLayout, attachments, textureSampler, false); + + shaderModules = CreateShaderModules(VkCtx, lightSpecConsts,false); + NoShadowsPipeline = createPipeline(VkCtx, shaderModules, new DescriptorSetLayout[]{NoShadowsAttachmentDescriptorSetLayout, + StorageDescriptorSetLayout, SceneDescriptorSetLayout}); Logger.debug("Light Renderer Pipeline -> [{}]",pipeline.GetVulkanPipeline()); Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VkCtx)); } @@ -120,10 +139,10 @@ public class LightRenderer { } private static void CreateAttachmentDescriptorSet(VulkanContext VkCtx, DescriptorSetLayout descSetLayout, List attachments, - TextureSampler sampler) { + TextureSampler sampler, boolean Shadows) { DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator(); Device device = VkCtx.GetDevice(); - DescriptorSet descSet = descAllocator.AddDescriptorSet(device, DESC_ID_ATT, descSetLayout); + DescriptorSet descSet = descAllocator.AddDescriptorSet(device, Shadows ? DESC_ID_ATT : DESC_ID_NOSHADOW_ATT, descSetLayout); List imageViews = new ArrayList<>(); attachments.forEach(a -> imageViews.add(a.GetVkImageView())); descSet.SetImages(device, imageViews, sampler, 0); @@ -176,14 +195,16 @@ public class LightRenderer { return result; } - private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, LightSpecConsts lightSpecConsts) { + private static ShaderModule[] CreateShaderModules(VulkanContext VkCtx, LightSpecConsts lightSpecConsts, boolean shadowPipeline) { if (EngineConfig.getInstance().RecompileShaders()) { ShaderCompiler.CompileGLSLShaderOnChange(VERTEX_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_vertex_shader); - ShaderCompiler.CompileGLSLShaderOnChange(FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); + //ShaderCompiler.CompileGLSLShaderOnChange( FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); + ShaderCompiler.CompileGLSLShaderOnChange(shadowPipeline ? FRAGMENT_SHADER_FILE_GLSL : NO_SHADOWS_FRAGMENT_SHADER_FILE_GLSL, Shaderc.shaderc_glsl_fragment_shader); } return new ShaderModule[]{ new ShaderModule(VkCtx, VK_SHADER_STAGE_VERTEX_BIT, VERTEX_SHADER_FILE_SPV, null), - new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, lightSpecConsts.getSpecInfo()), + //new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, FRAGMENT_SHADER_FILE_SPV, lightSpecConsts.getSpecInfo()), + new ShaderModule(VkCtx, VK_SHADER_STAGE_FRAGMENT_BIT, shadowPipeline ? FRAGMENT_SHADER_FILE_SPV : NO_SHADOWS_FRAGMENT_SHADER_FILE_SPV, shadowPipeline ? lightSpecConsts.getSpecInfo() : null), }; } @@ -210,8 +231,10 @@ public class LightRenderer { } VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(), 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_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT, + VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_ACCESS_2_SHADER_READ_BIT, VK_IMAGE_ASPECT_DEPTH_BIT); VulkanUtils.ImageBarrier(stack, cmdHandle, shadowAttachment.GetVkImage().getVulkanImage(), @@ -262,6 +285,73 @@ public class LightRenderer { } } + public void render(EngineInstance engineInstance, VulkanContext VkCtx, CommandBuffer cmdBuffer, MultiRenderTargetAttachments mrtAttachments, int CurrentFrame) { + try (var stack = MemoryStack.stackPush()) { + VkCommandBuffer cmdHandle = cmdBuffer.GetVulkanCommandBuffer(); + + VulkanUtils.ImageBarrier(stack, cmdHandle, AttachmentColour.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); + + List attachments = mrtAttachments.GetColourAttachments(); + int numAttachments = attachments.size(); + for (int i = 0; i < numAttachments; i++) { + Attachment attachment = attachments.get(i); + VulkanUtils.ImageBarrier(stack, cmdHandle, attachment.GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_SHADER_READ_BIT, + VK_IMAGE_ASPECT_COLOR_BIT); + } + VulkanUtils.ImageBarrier(stack, cmdHandle, mrtAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(), + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, + VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, + VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_ACCESS_2_SHADER_READ_BIT, + VK_IMAGE_ASPECT_DEPTH_BIT); + + vkCmdBeginRendering(cmdHandle, RenderInfo); + + vkCmdBindPipeline(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, NoShadowsPipeline.GetVulkanPipeline()); + + + Image ColourImage = AttachmentColour.GetVkImage(); + int width = ColourImage.GetWidth(); + int height = ColourImage.GetHeight(); + 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); + + DescriptorAllocator descAllocator = VkCtx.GetDescriptorAllocator(); + LongBuffer descriptorSets = stack.mallocLong(3) + .put(0, descAllocator.GetDescriptorSet(DESC_ID_NOSHADOW_ATT).GetVkDescriptorSet()) + .put(1, descAllocator.GetDescriptorSet(DESC_ID_LIGHTS, CurrentFrame).GetVkDescriptorSet()) + .put(2, descAllocator.GetDescriptorSet(DESC_ID_SCENE, CurrentFrame).GetVkDescriptorSet()); + IScene scene = engineInstance.scene(); + UpdateSceneInfo(VkCtx, scene, CurrentFrame); + UpdateLights(VkCtx, scene, CurrentFrame); + vkCmdBindDescriptorSets(cmdHandle, VK_PIPELINE_BIND_POINT_GRAPHICS, + NoShadowsPipeline.GetVulkanPipelineLayout(), 0, descriptorSets, null); + + vkCmdDraw(cmdHandle, 3, 1, 0, 0); + + vkCmdEndRendering(cmdHandle); + } + } + private void UpdateCascadeShadowMatrices(VulkanContext vkCtx, CascadeShadows cascadeShadows, int currentFrame) { VulkanBuffer buff = shadowMatrices[currentFrame]; long mappedMemory = buff.MapMemory(vkCtx); @@ -324,6 +414,20 @@ public class LightRenderer { buffer.UnMapMemory(VkCtx); } + public void updateAttachmentDescriptors(VulkanContext VkCtx, List attachments) { + DescriptorSet descSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESC_ID_ATT); + var imageViews = new ArrayList(); + attachments.forEach(a -> imageViews.add(a.GetVkImageView())); + descSet.SetImages(VkCtx.GetDevice(), imageViews, textureSampler, 0); + + DescriptorSet noShadowDescSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESC_ID_NOSHADOW_ATT); + var noShadowImageViews = new ArrayList(); + for (int i = 0; i < attachments.size() - 1; i++) { + noShadowImageViews.add(attachments.get(i).GetVkImageView()); + } + noShadowDescSet.SetImages(VkCtx.GetDevice(), noShadowImageViews, textureSampler, 0); + } + public void resize(VulkanContext VkCtx, List attachments) { RenderInfo.free(); AttachmentInfoColour.free(); @@ -337,6 +441,13 @@ public class LightRenderer { var imageViews = new ArrayList(); attachments.forEach(a -> imageViews.add(a.GetVkImageView())); descSet.SetImages(VkCtx.GetDevice(), imageViews, textureSampler, 0); + + DescriptorSet noShadowDescSet = VkCtx.GetDescriptorAllocator().GetDescriptorSet(DESC_ID_NOSHADOW_ATT); + var noShadowImageViews = new ArrayList(); + for (int i = 0; i < attachments.size() - 1; i++) { + noShadowImageViews.add(attachments.get(i).GetVkImageView()); + } + noShadowDescSet.SetImages(VkCtx.GetDevice(), noShadowImageViews, textureSampler, 0); } public void cleanup(VulkanContext VkCtx) { @@ -346,7 +457,9 @@ public class LightRenderer { SceneDescriptorSetLayout.CleanUp(VkCtx); Arrays.asList(SceneBuffer).forEach(b -> b.cleanup(VkCtx)); pipeline.CleanUp(VkCtx); + NoShadowsPipeline.CleanUp(VkCtx); AttachmentDescriptorSetLayout.CleanUp(VkCtx); + NoShadowsAttachmentDescriptorSetLayout.CleanUp(VkCtx); textureSampler.CleanUp(VkCtx); lightSpecConsts.cleanup(); RenderInfo.free(); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/MultiRenderTargetAttachments.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/MultiRenderTargetAttachments.java index 8931415..f542079 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/MultiRenderTargetAttachments.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/DeferredRendering/MultiRenderTargetAttachments.java @@ -15,6 +15,9 @@ public class MultiRenderTargetAttachments { public static final int DEPTH_FORMAT = VK_FORMAT_D32_SFLOAT; public static final int NORMAL_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; public static final int PBR_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; + public static final int EMISSIVE_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; + public static final int TRANSLUCECNY_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; + public static final int OPACITY_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; public static final int POSITION_FORMAT = VK_FORMAT_R16G16B16A16_SFLOAT; private final List ColourAttachments; private final Attachment DepthAttachment; @@ -39,6 +42,15 @@ public class MultiRenderTargetAttachments { //PBR Attachment = new Attachment(VkCtx, Width, Height, PBR_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1); ColourAttachments.add(Attachment); + //Emissive + Attachment = new Attachment(VkCtx, Width, Height, EMISSIVE_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1); + ColourAttachments.add(Attachment); + //Translucency + Attachment = new Attachment(VkCtx, Width, Height, TRANSLUCECNY_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1); + ColourAttachments.add(Attachment); + //Opacity + Attachment = new Attachment(VkCtx, Width, Height, OPACITY_FORMAT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 1); + ColourAttachments.add(Attachment); DepthAttachment = new Attachment(VkCtx, Width, Height, DEPTH_FORMAT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 1); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/DefaultPipeline.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/DefaultPipeline.java index fb57993..916876b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/DefaultPipeline.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/DefaultPipeline.java @@ -69,7 +69,7 @@ public class DefaultPipeline implements Pipeline { var RasterizationStateCreateInfo = VkPipelineRasterizationStateCreateInfo.calloc(MemStack) .sType$Default() .polygonMode(VK_POLYGON_MODE_FILL) - .cullMode(VK_CULL_MODE_NONE) + .cullMode(BuildInfo.CullMode()) .frontFace(VK_FRONT_FACE_CLOCKWISE) .depthClampEnable(BuildInfo.DepthClamp()) .lineWidth(1.0f); @@ -89,7 +89,7 @@ public class DefaultPipeline implements Pipeline { .sType(VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) .depthTestEnable(BuildInfo.GetDepthTest()) .depthWriteEnable(BuildInfo.performDepthWrite()) - .depthCompareOp(VK_COMPARE_OP_LESS_OR_EQUAL) + .depthCompareOp(BuildInfo.DepthBuffer()) .depthBoundsTestEnable(false) .stencilTestEnable(false); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java index d5a5122..552777f 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/Images/TextureCache.java @@ -20,11 +20,15 @@ import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; public class TextureCache implements ITextureCache { public static final int MAX_TEXTURES = 256; private final IndexedLinkedHashMap TextureMap; + private final IndexedLinkedHashMap CubemapTextures; private final List ActualTextures; + private final List ActualCubemapTextures; public TextureCache(){ TextureMap = new IndexedLinkedHashMap<>(); + CubemapTextures = new IndexedLinkedHashMap<>(); ActualTextures = new ArrayList<>(); + ActualCubemapTextures = new ArrayList<>(); } public ITexture AddCubeMapTexture(VulkanContext VkCtx, String ID, String[] FacePaths, int Format) { @@ -109,8 +113,17 @@ public class TextureCache implements ITextureCache { } public IndexedLinkedHashMap GetTextureCache(){return TextureMap;} public List GetTextureList(){return new ArrayList<>(TextureMap.values());} + public List GetAll2DTextures(){ + List result = new ArrayList<>(); + TextureMap.forEach((key,value)->{ + if(!(value instanceof CubeMapTexture)){ + result.add(value); + } + }); + return result; + } public int GetPosition(String ID){ - int result = -1; + int result = 0; if(ID != null){ result = TextureMap.GetIndexOf(ID); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java index aae2347..483c55c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Pipeline/PipelineBuildInfo.java @@ -4,7 +4,7 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.Des import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Shader.ShaderModule; import org.lwjgl.vulkan.VkPipelineVertexInputStateCreateInfo; -import static org.lwjgl.vulkan.VK10.VK_FORMAT_UNDEFINED; +import static org.lwjgl.vulkan.VK10.*; public class PipelineBuildInfo { private final ShaderModule[] ShaderModules; @@ -20,6 +20,14 @@ public class PipelineBuildInfo { private boolean alphaToCoverage = false; private final int[] ColourFormats; private int BlendingMethod = 0; + private int CullMode = VK_CULL_MODE_NONE; + private int DepthBuffer = VK_COMPARE_OP_GREATER_OR_EQUAL; + + public int DepthBuffer(){return DepthBuffer;} + public PipelineBuildInfo DepthBuffer(int DepthBuffer){this.DepthBuffer = DepthBuffer;return this;} + + public int CullMode(){return CullMode;} + public PipelineBuildInfo CullMode(int CullMode){this.CullMode = CullMode; return this;} public PipelineBuildInfo(ShaderModule[] shaderModules, VkPipelineVertexInputStateCreateInfo VertexInput, int[] ColourFormat){ this.ColourFormats = ColourFormat; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowRenderer.java index 889b9bc..baf61b3 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowRenderer.java @@ -31,6 +31,7 @@ import org.tinylog.Logger; import java.nio.ByteBuffer; import java.nio.LongBuffer; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -83,19 +84,68 @@ public class ShadowRenderer { 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 Attachment colorAttachment; + private VkRenderingAttachmentInfo.Buffer colorAttachmentInfo; + private Attachment depthAttachment; + private VkRenderingAttachmentInfo depthAttachmentInfo; private final DescriptorSetLayout descLayoutFrgStorage; - private final Pipeline pipeline; + private Pipeline pipeline; private final VulkanBuffer[] prjBuffers; private final ByteBuffer pushConstBuff; - private final VkRenderingInfo renderingInfo; + private VkRenderingInfo renderingInfo; private final DescriptorSetLayout textDescriptorSetLayout; private final TextureSampler textureSampler; private final DescriptorSetLayout uniformGeomDescriptorSetLayout; + public static volatile boolean AllowShadowRendering = false; + public static synchronized boolean AllowShadowRendering(){ return AllowShadowRendering;} + public static synchronized void AllowShadowRendering(boolean AllowShadowRendering){ ShadowRenderer.AllowShadowRendering = AllowShadowRendering;} + + public void RebuildPipelineAndRenderingAttachments(VulkanContext VulkanContext){ + + VkRenderingInfo NewRenderInfo; + Attachment newColourAttachment; + Attachment newDepthAttachment; + VkRenderingAttachmentInfo newDepthAttachmentInfo; + VkRenderingAttachmentInfo.Buffer newColourAttachmentInfo; + Pipeline newPipeline; + + newDepthAttachment = createDepthAttachment(VulkanContext); + newDepthAttachmentInfo = createDepthAttachmentInfo(newDepthAttachment, ClearValueDepth); + + newColourAttachment = createColorAttachment(VulkanContext); + newColourAttachmentInfo = createColorAttachmentInfo(newColourAttachment, ClearValueColour); + + NewRenderInfo = createRenderInfo(newColourAttachmentInfo, newDepthAttachmentInfo); + + ShaderModule[] shaderModules = createShaderModules(VulkanContext); + newPipeline = createPipeline(VulkanContext, shaderModules, new DescriptorSetLayout[]{uniformGeomDescriptorSetLayout, textDescriptorSetLayout, + descLayoutFrgStorage}); + Arrays.asList(shaderModules).forEach(s -> s.CleanUp(VulkanContext)); + + VkRenderingInfo OldRenderInfo = renderingInfo; + Attachment OldColourAttachment = colorAttachment; + Attachment OldDepthAttachment = depthAttachment; + VkRenderingAttachmentInfo OldDepthAttachmentInfo = depthAttachmentInfo; + VkRenderingAttachmentInfo.Buffer OldColourAttachmentInfo = colorAttachmentInfo; + Pipeline OldPipeline = pipeline; + + renderingInfo = NewRenderInfo; + colorAttachment = newColourAttachment; + depthAttachment = newDepthAttachment; + depthAttachmentInfo = newDepthAttachmentInfo; + colorAttachmentInfo = newColourAttachmentInfo; + pipeline = newPipeline; + + OldRenderInfo.free(); + OldDepthAttachmentInfo.free(); + OldDepthAttachment.CleanUp(VulkanContext); + OldColourAttachmentInfo.free(); + OldColourAttachment.CleanUp(VulkanContext); + OldPipeline.CleanUp(VulkanContext); + + } + 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)); @@ -135,6 +185,7 @@ public class ShadowRenderer { for (int i = 0; i < VulkanUtils.MAX_IN_FLIGHT; i++) { cascadeShadows[i] = new CascadeShadows(); } + AllowShadowRendering(true); } private static Attachment createColorAttachment(VulkanContext VulkanContext) { @@ -179,7 +230,9 @@ public class ShadowRenderer { }) .SetDescriptorSetLayouts(DescriptorSetLayouts) .SetDescriptorSetLayouts(DescriptorSetLayouts) - .SetDepthClamp(VulkanContext.GetDevice().getDepthClamp()); + .SetDepthClamp(VulkanContext.GetDevice().getDepthClamp()) + .CullMode(VK_CULL_MODE_FRONT_BIT) + .DepthBuffer(VK_COMPARE_OP_LESS_OR_EQUAL); var pipeline = new DefaultPipeline(VulkanContext, buildInfo); vtxBuffStruct.cleanup(); return pipeline; @@ -216,6 +269,7 @@ public class ShadowRenderer { } public void cleanup(VulkanContext VulkanContext) { + AllowShadowRendering(false); pipeline.CleanUp(VulkanContext); uniformGeomDescriptorSetLayout.CleanUp(VulkanContext); descLayoutFrgStorage.CleanUp(VulkanContext); @@ -248,7 +302,12 @@ public class ShadowRenderer { var buffer = materialsCache.GetMaterialsBuffer(); descSet.SetBuffer(device, buffer, buffer.GetRequestedSize(), layoutInfo.Binding(), layoutInfo.DescriptorType()); - List imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList(); + List imageViews = new ArrayList<>(textureCache.GetAll2DTextures().stream().map(ITexture::GetImageView).toList()); + + ImageView fallback = textureCache.GetTexture("resources/EngineResources/Texture/NoTexture.png").GetImageView(); + while (imageViews.size() < TextureCache.MAX_TEXTURES) { + imageViews.add(fallback); + } descSet = VulkanContext.GetDescriptorAllocator().AddDescriptorSet(device, DESCRIPTOR_ID_TEXT, textDescriptorSetLayout); descSet.SetImageArray(device, imageViews, textureSampler, 0); } @@ -319,6 +378,9 @@ public class ShadowRenderer { var vulkanMesh = vulkanMeshList.get(j); String materialId = vulkanMesh.MaterialID(); int materialIdx = materialsCache.GetPosition(materialId); + if(materialIdx == -1) { + continue; + } VulkanMaterial vulkanMaterial = materialsCache.GetMaterial(materialId); if (vulkanMaterial == null) { Logger.warn("Mesh [{}] in model [{}] does not have material", j, model.GetID()); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java index ec83742..ef50d53 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/Shadows/ShadowUtils.java @@ -24,7 +24,7 @@ public class ShadowUtils { public static void updateCascadeShadows(CascadeShadows cascadeShadows, IScene scene) { Camera camera = scene.GetCamera(); Matrix4f viewMatrix = camera.GetViewMatrix(); - Project3D projection = scene.GetProjection(); + Project3D projection = scene.GetProjection().GetNormalFarPlanes(); Matrix4f projMatrix = projection.GetProjectionMatrix(); ILight[] lights = scene.GetLightingManager().GetLights(); int numLights = lights.length; @@ -42,14 +42,10 @@ public class ShadowUtils { float[] cascadeSplits = new float[SceneLightingManager.SHADOW_MAP_CASCADE_COUNT]; - float nearClip = projection.GetNearZ(); - float farClip = projection.GetFarZ(); + float nearClip = projection.GetNearZ();//projection.GetNearZ(); + float farClip = EngineConfig.getInstance().MaxShadowDistance();//Math.min(projection.GetFarZ(), EngineConfig.getInstance().MaxShadowDistance()); float clipRange = farClip - nearClip; - if (nearClip <= 0.0f || farClip <= nearClip) { - //throw new IllegalStateException("Invalid projection near/far planes for shadow cascades: near=" + nearClip + ", far=" + farClip); - } - float minZ = nearClip; float maxZ = nearClip + clipRange; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialData.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialData.java index 5e2f2f7..b9407bc 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialData.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialData.java @@ -2,5 +2,5 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.VkModel; import org.joml.Vector4f; -public record MaterialData(String ID, String TexturePath,String NormalTexturePath,String MetalRoughnessMap, Vector4f DiffuseColour,float Roughness, float Metallic) { +public record MaterialData(String ID, String TexturePath,String NormalTexturePath,String MetalRoughnessMap, Vector4f DiffuseColour,float Roughness, float Metallic, String EmissiveTexture,Vector4f EmissiveColour, String TranslucencyTexture, float Translucency, String OpacityTexture, float Opacity) { } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialsCache.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialsCache.java index 82e0597..83ea1df 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialsCache.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Rendering/VkModel/MaterialsCache.java @@ -10,6 +10,7 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLaye import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Structure.DeviceLayers.Queues.Queue; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils; +import org.joml.Vector4f; import org.lwjgl.system.MemoryUtil; import org.tinylog.Logger; @@ -21,7 +22,8 @@ import static org.lwjgl.util.vma.Vma.VMA_MEMORY_USAGE_AUTO; import static org.lwjgl.vulkan.VK10.*; public class MaterialsCache { - private static final int MATERIAL_SIZE = VulkanUtils.VEC4_SIZE * 3; + private static final int MATERIAL_RAW_SIZE = VulkanUtils.VEC4_SIZE * 4 + (VulkanUtils.INT_SIZE * 2 + VulkanUtils.FLOAT_SIZE) * 2 + (VulkanUtils.INT_SIZE * 2); + private static final int MATERIAL_SIZE = 16 * (int)(Math.ceil(MATERIAL_RAW_SIZE/16.0)); private final IndexedLinkedHashMap MaterialsMap; private VulkanBuffer MaterialsBuffer; @@ -31,6 +33,7 @@ public class MaterialsCache { //create staging buffer and GPU only accessibly buffer, add any located textures public void LoadMaterials(VulkanContext VkCtx, List Materials, TextureCache textureCache, CommandPool commandPool, Queue queue){ + Logger.debug("MATERIAL SIZE: [{}], Expected Size: 96, raw size [{}]", MATERIAL_SIZE,MATERIAL_RAW_SIZE); int MaterialCount = Materials.size(); int BufferSize = MATERIAL_SIZE * MaterialCount; var SrcBuffer = new VulkanBuffer(VkCtx, BufferSize, @@ -48,20 +51,28 @@ public class MaterialsCache { int Offset = 0; for(int i = 0; i < MaterialCount; i++){ + int materialBaseOffset = i * MATERIAL_SIZE; + Offset = materialBaseOffset; var Material = Materials.get(i); String TexturePath = Material.TexturePath(); - boolean ValidTexture = TexturePath != null && !TexturePath.isEmpty(); + boolean hasDiffuseTexture = TexturePath != null && !TexturePath.isEmpty(); boolean TransparentTexture; Logger.debug("Material Texture Path -> [{}]",Material.TexturePath()); - if(ValidTexture){ + + if(hasDiffuseTexture){ ITexture newTexture = textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB); if(newTexture == null) { - TransparentTexture = false; TexturePath = "resources/EngineResources/Texture/NoTexture.png"; + textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB); + hasDiffuseTexture = false; + TransparentTexture = false; + } + else { + TransparentTexture = newTexture.HasTransparency(); } - else TransparentTexture = newTexture.HasTransparency(); } else{ TexturePath = "resources/EngineResources/Texture/NoTexture.png"; + textureCache.AddTexture(VkCtx, TexturePath, TexturePath, VK_FORMAT_R8G8B8A8_SRGB); TransparentTexture = Material.DiffuseColour().w < 1.0f; } VulkanMaterial newMaterial = new VulkanMaterial(Material.ID(),TransparentTexture); @@ -70,7 +81,7 @@ public class MaterialsCache { Material.DiffuseColour().get(Offset,data); Offset += VulkanUtils.VEC4_SIZE; - data.putInt(Offset, ValidTexture ? 1 : 0); + data.putInt(Offset, hasDiffuseTexture ? 1 : 0); Offset += VulkanUtils.INT_SIZE; data.putInt(Offset, textureCache.GetPosition(TexturePath)); Offset += VulkanUtils.INT_SIZE; @@ -79,17 +90,17 @@ public class MaterialsCache { boolean hasNormalMap = NormalMap != null && !NormalMap.isEmpty(); if(hasNormalMap){ textureCache.AddTexture(VkCtx,NormalMap,NormalMap,VK_FORMAT_R8G8B8A8_UNORM); - } + }else NormalMap = "resources/EngineResources/Texture/NoTexture.png"; data.putInt(Offset, hasNormalMap ? 1 : 0); Offset += VulkanUtils.INT_SIZE; data.putInt(Offset, textureCache.GetPosition(NormalMap)); Offset += VulkanUtils.INT_SIZE; String RoughnessMap = Material.MetalRoughnessMap(); - boolean hasRoughness = RoughnessMap != null && !RoughnessMap.isEmpty(); + boolean hasRoughness = RoughnessMap != null && !RoughnessMap.equals("null") && !RoughnessMap.isEmpty(); if(hasRoughness){ textureCache.AddTexture(VkCtx,RoughnessMap,RoughnessMap,VK_FORMAT_R8G8B8A8_UNORM); - } + }else RoughnessMap = "resources/EngineResources/Texture/NoTexture.png"; data.putInt(Offset, hasRoughness ? 1 : 0); Offset += VulkanUtils.INT_SIZE; data.putInt(Offset, textureCache.GetPosition(RoughnessMap)); @@ -99,6 +110,48 @@ public class MaterialsCache { Offset += VulkanUtils.FLOAT_SIZE; data.putFloat(Offset, Material.Metallic()); Offset += VulkanUtils.FLOAT_SIZE; + + if(Material.EmissiveColour() != null) { + Material.EmissiveColour().get(Offset, data); + } + else new Vector4f(0,0,0,0).get(Offset,data); + Offset += VulkanUtils.VEC4_SIZE; + String EmissiveMap = Material.EmissiveTexture(); + boolean hasEmissiveMap = EmissiveMap != null && !EmissiveMap.equals("null") && !EmissiveMap.isEmpty(); + if(hasEmissiveMap){ + textureCache.AddTexture(VkCtx,EmissiveMap,EmissiveMap,VK_FORMAT_R8G8B8A8_UNORM); + } else EmissiveMap = "resources/EngineResources/Texture/NoTexture.png"; + data.putInt(Offset, hasEmissiveMap ? 1 : 0); + Offset += VulkanUtils.INT_SIZE; + data.putInt(Offset, textureCache.GetPosition(EmissiveMap)); + Offset += VulkanUtils.INT_SIZE; + + String TranslucencyMap = Material.TranslucencyTexture(); + boolean hasTranslucency = TranslucencyMap != null && !TranslucencyMap.equals("null") && !TranslucencyMap.isEmpty(); + if(hasTranslucency){ + textureCache.AddTexture(VkCtx,TranslucencyMap,TranslucencyMap,VK_FORMAT_R8G8B8A8_UNORM); + }else TranslucencyMap = "resources/EngineResources/Texture/NoTexture.png"; + data.putInt(Offset, hasTranslucency ? 1 : 0); + Offset += VulkanUtils.INT_SIZE; + data.putInt(Offset, textureCache.GetPosition(TranslucencyMap)); + Offset += VulkanUtils.INT_SIZE; + + data.putFloat(Offset, Material.Translucency()); + Offset += VulkanUtils.FLOAT_SIZE; + + String OpacityMap = Material.OpacityTexture(); + boolean hasOpacity = OpacityMap != null && !OpacityMap.equals("null") && !OpacityMap.isEmpty(); + if(hasOpacity){ + textureCache.AddTexture(VkCtx,OpacityMap,OpacityMap,VK_FORMAT_R8G8B8A8_UNORM); + }else OpacityMap = "resources/EngineResources/Texture/NoTexture.png"; + data.putInt(Offset, hasOpacity ? 1 : 0); + Offset += VulkanUtils.INT_SIZE; + data.putInt(Offset, textureCache.GetPosition(OpacityMap)); + Offset += VulkanUtils.INT_SIZE; + + data.putFloat(Offset, Material.Opacity()); + Offset += VulkanUtils.FLOAT_SIZE; + Offset = materialBaseOffset + MATERIAL_SIZE; } // data.position(0); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/SpriteRendering/SpriteRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/SpriteRendering/SpriteRenderer.java index 8b39f45..2ffc790 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/SpriteRendering/SpriteRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/SpriteRendering/SpriteRenderer.java @@ -205,7 +205,12 @@ public class SpriteRenderer { public void LoadMaterials(VulkanContext VkCtx, MaterialsCache materialsCache, TextureCache textureCache){ DescriptorAllocator descriptorAllocator = VkCtx.GetDescriptorAllocator(); Device device = VkCtx.GetDevice(); - List imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList(); + List imageViews = new ArrayList<>(textureCache.GetAll2DTextures().stream().map(ITexture::GetImageView).toList()); + + ImageView fallback = textureCache.GetTexture("resources/EngineResources/Texture/NoTexture.png").GetImageView(); + while (imageViews.size() < TextureCache.MAX_TEXTURES) { + imageViews.add(fallback); + } DescriptorSet descriptorSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device,DESCRIPTOR_ID_TEXTURE,TextDescriptorSetLayout); descriptorSet.SetImageArray(device,imageViews,TextureSampler,0); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java index 08261b5..20ee739 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/DeferredSceneRender.java @@ -108,7 +108,7 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering public DeferredSceneRender(VulkanContext vulkanContext, EngineInstance engineInstance){ 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)); + ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f)); MRTAttachments = new MultiRenderTargetAttachments(vulkanContext); AttachmentInfoColour = CreateColourAttachmentInfo(MRTAttachments, ClearValueColour); AttachmentInfoDepth = CreateDepthAttachmentInfo(MRTAttachments, ClearValueDepth); @@ -241,7 +241,10 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, MultiRenderTargetAttachments.NORMAL_FORMAT, - MultiRenderTargetAttachments.PBR_FORMAT + MultiRenderTargetAttachments.PBR_FORMAT, + MultiRenderTargetAttachments.EMISSIVE_FORMAT, + MultiRenderTargetAttachments.TRANSLUCECNY_FORMAT, + MultiRenderTargetAttachments.OPACITY_FORMAT }; try (MemoryStack MemStack = MemoryStack.stackPush()) { @@ -279,7 +282,10 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage, int BlendingMethod){ var vertexBufferStructure = new VertexBufferStructure(); var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{ - MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT}) + MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, + MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT, + MultiRenderTargetAttachments.EMISSIVE_FORMAT, MultiRenderTargetAttachments.TRANSLUCECNY_FORMAT, + MultiRenderTargetAttachments.OPACITY_FORMAT}) .SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT) .SetDepthWrite(DepthWrite) .SetPushConstantRanges( @@ -318,10 +324,11 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering VK_IMAGE_ASPECT_COLOR_BIT); } VulkanUtils.ImageBarrier(MemStack, CommandHandle, MRTAttachments.GetDepthAttachment().GetVkImage().getVulkanImage(), - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_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_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT, - VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, + VK_ACCESS_2_NONE, + VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_ASPECT_DEPTH_BIT); long InitialTime = System.nanoTime(); @@ -427,13 +434,17 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering var VkMesh = VkMeshList.get(j); String MaterialID = VkMesh.MaterialID(); int MaterialIndex = materialsCache.GetPosition(MaterialID); + if(MaterialIndex == -1) { + continue; + } VulkanMaterial vulkanMaterial = materialsCache.GetMaterial(MaterialID); if (vulkanMaterial == null) { Logger.warn("Mesh [{}] in model [{}] does not have material", j, model.GetID()); continue; } if (DualPassRendering || vulkanMaterial.HasTransparency() == Transparent) { - SetPushConstants(CommandHandle, Actor.GetModelMatrix(), MaterialIndex); + if(DualPassRendering) SetDualPassPushConstants(CommandHandle, Actor.GetModelMatrix(), MaterialIndex, Transparent); + else SetPushConstants(CommandHandle, Actor.GetModelMatrix(), MaterialIndex); vertexBuffer.put(0, VkMesh.VerticesBuffer().GetBuffer()); vkCmdBindVertexBuffers(CommandHandle, 0, vertexBuffer, offsets); vkCmdBindIndexBuffer(CommandHandle, VkMesh.IndicesBuffer().GetBuffer(), 0, VK_INDEX_TYPE_UINT32); @@ -447,6 +458,15 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering } } + private void SetDualPassPushConstants(VkCommandBuffer CmdHandle, Matrix4f ModelMatrix, int MaterialIndex, boolean Transparent){ + ModelMatrix.get(0,PushConstBuffer); + PushConstBuffer.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex); + vkCmdPushConstants(CmdHandle, Transparent? VkPipelineTranslucent.GetVulkanPipelineLayout() : VkPipelineOpaque.GetVulkanPipelineLayout(), VK_SHADER_STAGE_VERTEX_BIT, 0, + PushConstBuffer.slice(0,VulkanUtils.MATRIX4X4_SIZE)); + vkCmdPushConstants(CmdHandle, Transparent? VkPipelineTranslucent.GetVulkanPipelineLayout() : VkPipelineOpaque.GetVulkanPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, VulkanUtils.MATRIX4X4_SIZE, + PushConstBuffer.slice(VulkanUtils.MATRIX4X4_SIZE, VulkanUtils.INT_SIZE)); + } + private void SetPushConstants(VkCommandBuffer CmdHandle, Matrix4f ModelMatrix, int MaterialIndex){ ModelMatrix.get(0,PushConstBuffer); PushConstBuffer.putInt(VulkanUtils.MATRIX4X4_SIZE, MaterialIndex); @@ -477,7 +497,12 @@ public class DeferredSceneRender implements SceneRenderer {//dynamic rendering var buffer = materialsCache.GetMaterialsBuffer(); descSet.SetBuffer(device, buffer, buffer.GetRequestedSize(), layoutInfo.Binding(), layoutInfo.DescriptorType()); - List imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList(); + List imageViews = new ArrayList<>(textureCache.GetAll2DTextures().stream().map(ITexture::GetImageView).toList()); + + ImageView fallback = textureCache.GetTexture("resources/EngineResources/Texture/NoTexture.png").GetImageView(); + while (imageViews.size() < TextureCache.MAX_TEXTURES) { + imageViews.add(fallback); + } descSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device, DESCRIPTOR_ID_TEXT, descriptorLayoutTexture); descSet.SetImageArray(device, imageViews, textureSampler, 0); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/ForwardSceneRender.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/ForwardSceneRender.java index 82d7664..1460682 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/ForwardSceneRender.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/DisplayToScreen/ForwardSceneRender.java @@ -32,6 +32,7 @@ import org.tinylog.Logger; import java.nio.ByteBuffer; import java.nio.LongBuffer; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -117,7 +118,7 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering public ForwardSceneRender(VulkanContext vulkanContext){ ClearValueColour = VkClearValue.calloc().color( c -> c.float32(0, R).float32(1, G).float32(2, B).float32(3, 1.0f)); - ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 1.0f)); + ClearValueDepth = VkClearValue.calloc().color(c -> c.float32(0, 0.0f)); CreateRenderAttachments(vulkanContext); PushConstBuffer = (MemoryUtil.memAlloc(PUSH_CONSTANTS_SIZE)); @@ -250,10 +251,10 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering private static Pipeline CreateSkyboxPipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage){ int[] skyboxFormats = new int[] { - MultiRenderTargetAttachments.POSITION_FORMAT, - MultiRenderTargetAttachments.ALBEDO_FORMAT, - MultiRenderTargetAttachments.NORMAL_FORMAT, - MultiRenderTargetAttachments.PBR_FORMAT + MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, + MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT, + MultiRenderTargetAttachments.EMISSIVE_FORMAT, MultiRenderTargetAttachments.TRANSLUCECNY_FORMAT, + MultiRenderTargetAttachments.OPACITY_FORMAT }; try (MemoryStack MemStack = MemoryStack.stackPush()) { @@ -292,7 +293,10 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering private static Pipeline CreatePipeline(VulkanContext VkCtx, ShaderModule[] ShaderModules, DescriptorSetLayout[] DescriptorSetLayouts, boolean DepthWrite, boolean DualRender, boolean Blending, boolean AlphaToCoverage, int BlendingMethod){ var vertexBufferStructure = new VertexBufferStructure(); var BuildInfo = new PipelineBuildInfo(ShaderModules,vertexBufferStructure.getVertexInput(),new int[]{ - MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT}) + MultiRenderTargetAttachments.POSITION_FORMAT, MultiRenderTargetAttachments.ALBEDO_FORMAT, + MultiRenderTargetAttachments.NORMAL_FORMAT, MultiRenderTargetAttachments.PBR_FORMAT, + MultiRenderTargetAttachments.EMISSIVE_FORMAT, MultiRenderTargetAttachments.TRANSLUCECNY_FORMAT, + MultiRenderTargetAttachments.OPACITY_FORMAT}) .SetDepthFormat(MultiRenderTargetAttachments.DEPTH_FORMAT) .SetDepthWrite(DepthWrite) .SetPushConstantRanges( @@ -415,6 +419,9 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering var VkMesh = VkMeshList.get(j); String MaterialID = VkMesh.MaterialID(); int MaterialIndex = materialsCache.GetPosition(MaterialID); + if(MaterialIndex == -1) { + continue; + } VulkanMaterial vulkanMaterial = materialsCache.GetMaterial(MaterialID); if (vulkanMaterial == null) { Logger.warn("Mesh [{}] in model [{}] does not have material", j, model.GetID()); @@ -461,7 +468,12 @@ public class ForwardSceneRender implements SceneRenderer {//dynamic rendering DescriptorSetLayout.LayoutInformation LayoutInfo = descriptorLayoutFragStorage.GetLayoutInfo(); var Buffer = materialsCache.GetMaterialsBuffer(); descriptorSet.SetBuffer(device,Buffer,Buffer.GetRequestedSize(),LayoutInfo.Binding(),LayoutInfo.DescriptorType()); - List imageViews = textureCache.GetTextureList().stream().map(ITexture::GetImageView).toList(); + List imageViews = new ArrayList<>(textureCache.GetAll2DTextures().stream().map(ITexture::GetImageView).toList()); + + ImageView fallback = textureCache.GetTexture("resources/EngineResources/Texture/NoTexture.png").GetImageView(); + while (imageViews.size() < TextureCache.MAX_TEXTURES) { + imageViews.add(fallback); + } descriptorSet = VkCtx.GetDescriptorAllocator().AddDescriptorSet(device,DESCRIPTOR_ID_TEXT,descriptorLayoutTexture); descriptorSet.SetImageArray(device,imageViews,textureSampler,0); DescriptorSet descSetSkyBox = descriptorAllocator.AddDescriptorSet(device, DESCRIPTOR_ID_SKYBOX_CUBEMAP, descriptorLayoutSkyboxTexture); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/SwapChain/SwapChain.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/SwapChain/SwapChain.java index 6e57047..561b8cb 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/SwapChain/SwapChain.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/Vulkan/Structure/SwapChain/SwapChain.java @@ -18,6 +18,7 @@ import java.util.Arrays; import static net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils.vkCheck; import static org.lwjgl.vulkan.KHRSurface.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; +import static org.lwjgl.vulkan.KHRSurface.VK_ERROR_SURFACE_LOST_KHR; import static org.lwjgl.vulkan.VK13.*; public class SwapChain { @@ -102,6 +103,19 @@ public class SwapChain { return ReturnResult; } + private static String VkResultName(int result) { + return switch (result) { + case VK_SUCCESS -> "VK_SUCCESS"; + case KHRSwapchain.VK_SUBOPTIMAL_KHR -> "VK_SUBOPTIMAL_KHR"; + case KHRSwapchain.VK_ERROR_OUT_OF_DATE_KHR -> "VK_ERROR_OUT_OF_DATE_KHR"; + case VK_ERROR_DEVICE_LOST -> "VK_ERROR_DEVICE_LOST"; + case VK_ERROR_OUT_OF_HOST_MEMORY -> "VK_ERROR_OUT_OF_HOST_MEMORY"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY -> "VK_ERROR_OUT_OF_DEVICE_MEMORY"; + case VK_ERROR_SURFACE_LOST_KHR -> "VK_ERROR_SURFACE_LOST_KHR"; + default -> "Unknown Vulkan error"; + }; + } + public int FetchNextImage(Device device, Semaphore ImageFetchSemaphore){ int ImageIndex; try(var MemStack = MemoryStack.stackPush()){ @@ -112,8 +126,10 @@ public class SwapChain { } else if (Error == KHRSwapchain.VK_SUBOPTIMAL_KHR){ //Logger.warn("Suboptimal surface properties match, not fatal"); + } else if (Error == VK_ERROR_DEVICE_LOST) { + throw new RuntimeException("Vulkan device was lost while acquiring the next swapchain image. This usually means an earlier GPU operation was invalid. Result: " + VkResultName(Error) + " (" + Error + ")"); } else if (Error != VK_SUCCESS){ - throw new RuntimeException("Failed to fetch next image in the swapchain: " + Error); + throw new RuntimeException("Failed to fetch next image in the swapchain: " + VkResultName(Error) + " (" + Error + ")"); } ImageIndex = IntPointer.get(0); } @@ -136,8 +152,8 @@ public class SwapChain { } else if (Error == KHRSwapchain.VK_SUBOPTIMAL_KHR){ //Logger.warn("Suboptimal surface properties match, not fatal"); } else if (Error != VK_SUCCESS){ - Logger.debug("Failure in Present Image"); - throw new RuntimeException("failed to present KHR: " + Error); + Logger.debug("Failure in Present Image: " + VkResultName(Error) + " (" + Error + ")"); + throw new RuntimeException("failed to present KHR: " + VkResultName(Error) + " (" + Error + ")"); } } return resize; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java index 1a5ad07..28eba78 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/EngineThread.java @@ -80,7 +80,7 @@ public class EngineThread implements IEngineThread{ Logger.debug("{} Thread Started",ThreadName); EngineAccuracy = EngineConfig.getInstance().getAccuracy(); OriginalAccuracy = EngineAccuracy; - while (running && !PrimaryRuntime.CanClose && internalRunning && !Thread.currentThread().isInterrupted()){ + while (running && internalRunning && !Thread.currentThread().isInterrupted()){ long now = System.nanoTime(); FrameTimes[0] = now - InitialTime; FrameTimes[1] += FrameTimes[0]; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java index dd7ff71..532e91b 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/RenderThread.java @@ -17,7 +17,7 @@ public class RenderThread extends EngineThread { private Renderer render; private final InitData initData; public static int VulkanCrashCount = 0; - public static boolean Headless = false; + public static boolean Headless = false; public RenderThread(EngineInstance engineInstance, InitData initData, GameLogic appLogic) { //this.window = window; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/VirtualEngineThread.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/VirtualEngineThread.java index e90dd75..b9bce35 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/VirtualEngineThread.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Threads/VirtualEngineThread.java @@ -108,7 +108,7 @@ public class VirtualEngineThread implements IEngineThread{ Logger.debug("{} Thread Started",ThreadName); EngineAccuracy = EngineConfig.getInstance().getAccuracy(); OriginalAccuracy = EngineAccuracy; - while (EngineThread.running && !PrimaryRuntime.CanClose && internalRunning && !Thread.currentThread().isInterrupted()){ + while (EngineThread.running && internalRunning && !Thread.currentThread().isInterrupted()){ long now = System.nanoTime(); FrameTimes[0] = now - InitialTime; FrameTimes[1] += FrameTimes[0]; diff --git a/terrain4j.properties b/terrain4j.properties index a6e6515..28ff3f5 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -35,5 +35,5 @@ throttle_on_unfocus=false user_display_name=TheSigma vkValidated=true vsync=false -z_near_plane=0.1f -z_far_plane=10000.0f +z_far_plane=0.1f +z_near_plane=16384.0f