diff --git a/resources/EngineResources/GLShaders/lighting_frag.glsl b/resources/EngineResources/GLShaders/lighting_frag.glsl new file mode 100644 index 0000000..b14bec1 --- /dev/null +++ b/resources/EngineResources/GLShaders/lighting_frag.glsl @@ -0,0 +1,172 @@ +#version 450 +#extension GL_EXT_scalar_block_layout: require +// CREDITS: functions obtained from this link: https://github.com/SaschaWillems/Vulkan +// developed by Sascha Willems, https://twitter.com/JoeyDeVriez, licensed under MIT License (MIT) +// also Vulkan Book https://github.com/lwjglgamedev/vulkanbook/blob/master/bookcontents/chapter-15/chapter-15.md + + +const int MAX_LIGHTS = 32; +const float PI = 3.14159265359; + +struct Light { + vec3 position; + uint directional; + float intensity; + vec3 color; +}; + +in vec2 inTextCoord; + +out vec4 outFragColor; + +uniform sampler2D outAlbedo; +uniform sampler2D outPosition; +uniform sampler2D outNormals; +uniform sampler2D outPBR; + +struct Attenuation +{ + float constant; + float linear; + float exponent; +}; +struct Light { + vec3 position; + int lightType; + float intensity; + vec3 color; + vec3 conedir; + float cutoff; + Attenuation attenuation; +}; +uniform Light lights[MAX_LIGHTS]; +struct SceneInfo { + vec3 camPos; + float ambientLightIntensity; + vec3 ambientLightColor; + int LightCount; +}; + +uniform SceneInfo sceneInfo; + +float distributionGGX(vec3 N, vec3 H, float roughness) { + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} + +float geometrySchlickGGX(float NdotV, float roughness) { + float r = (roughness + 1.0); + float k = (r * r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} + +float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = geometrySchlickGGX(NdotV, roughness); + float ggx1 = geometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} + +vec3 fresnelSchlick(float cosTheta, vec3 F0) { + return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); +} + +vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) { + vec3 tmpSub = light.position - worldPos; + vec3 L = normalize(tmpSub); + vec3 H = normalize(V + L); + + // Calculate distance and attenuation + float distance = length(tmpSub); + float attenuation = 1.0 / (distance * distance); + float intensity = 10.0f; + vec3 radiance = light.color * light.intensity * attenuation; + + // Cook-Torrance BRDF + float NDF = distributionGGX(N, H, roughness); + float G = geometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + float NdotL = max(dot(N, L), 0.0); + return (kD * albedo / PI + specular) * radiance * NdotL; +} + +vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) { + vec3 L = normalize(-light.position); + vec3 H = normalize(V + L); + + vec3 radiance = light.color * light.intensity; + + // Cook-Torrance BRDF + float NDF = distributionGGX(N, H, roughness); + float G = geometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + float NdotL = max(dot(N, L), 0.0); + return (kD * albedo / PI + specular) * radiance * NdotL; +} + +void main() { + vec3 albedo = texture(outAlbedo, inTextCoord).rgb; + vec3 normal = texture(outNormals, inTextCoord).rgb; + vec3 worldPos = texture(outPosition, inTextCoord).rgb; + vec3 pbr = texture(outPBR, inTextCoord).rgb; + + float roughness = pbr.g; + float metallic = pbr.b; + + vec3 N = normalize(normal); + vec3 V = normalize(sceneInfo.camPos - worldPos); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + vec3 Lo = vec3(0.0); + for (uint i = 0; i < sceneInfo.LightCount; i++) { + Light light = lights[i]; + if (light.lightType == 1) { + Lo += calculateDirectionalLight(light, V, N, F0, albedo, metallic, roughness); + } else { + Lo += calculatePointLight(light, worldPos, V, N, F0, albedo, metallic, roughness); + } + } + vec3 ambient = sceneInfo.ambientLightColor * albedo * sceneInfo.ambientLightIntensity; + vec3 color = ambient + Lo; + + outFragColor = vec4(color, 1.0f); + if (length(normal) < 0.001) { + outFragColor = vec4(albedo,1.0f); + return; + } + // outFragColor = vec4(normal, 1.0f); +} diff --git a/resources/EngineResources/GLShaders/scene_frag.glsl b/resources/EngineResources/GLShaders/scene_frag.glsl index 626f7c7..8a53eab 100644 --- a/resources/EngineResources/GLShaders/scene_frag.glsl +++ b/resources/EngineResources/GLShaders/scene_frag.glsl @@ -1,25 +1,256 @@ #version 330 core +const int MAX_LIGHTS = 32; +const float PI = 3.14159265359; +const float SPECULAR_POWER = 10; + in vec4 outPos; in vec3 outNormal; in vec3 outTangent; in vec3 outBitangent; in vec2 outTextCoords; -out vec4 outAlbedo; +out vec4 fragColor; -struct Material +struct Attenuation { + float constant; + float linear; + float exponent; +}; +struct Light { + vec3 position; + int lightType; + float intensity; + vec3 color; + vec3 conedir; + float cutoff; + Attenuation attenuation; +}; + +struct Material { vec4 diffuse; + int hasTexture; + int hasNormalMap; + int hasRoughMap; + float roughnessFactor; + float metallicFactor; }; uniform sampler2D textureSampler; +uniform sampler2D normalSampler; +uniform sampler2D roughnessSampler; +uniform Light lights[MAX_LIGHTS]; +struct SceneInfo { + vec3 camPos; + float ambientLightIntensity; + vec3 ambientLightColor; + int LightCount; +}; uniform Material material; +uniform SceneInfo sceneInfo; + + + +vec4 calcAmbient(Light ambientLight, vec4 ambient) { + return vec4(ambientLight.intensity * ambientLight.color, 1) * ambient; +} + +vec4 calcLightColor(vec4 diffuse, vec4 specular, vec3 lightColor, float light_intensity, vec3 position, vec3 to_light_dir, vec3 normal, float Metallic) { + vec4 diffuseColor = vec4(0, 0, 0, 1); + vec4 specColor = vec4(0, 0, 0, 1); + + float diffuseFactor = max(dot(normal, to_light_dir), 0.0); + diffuseColor = diffuse * vec4(lightColor, 1.0) * light_intensity * diffuseFactor; + + vec3 camera_direction = normalize(-position); + vec3 from_light_dir = -to_light_dir; + vec3 reflected_light = normalize(reflect(from_light_dir, normal)); + float specularFactor = max(dot(camera_direction, reflected_light), 0.0); + specularFactor = pow(specularFactor, SPECULAR_POWER); + specColor = specular * light_intensity * specularFactor * Metallic * vec4(lightColor, 1.0); + + return (diffuseColor + specColor); +} + +vec4 calcPointLight(vec4 diffuse, vec4 specular, Light light, vec3 position, vec3 normal, float Metallic) { + vec3 light_direction = light.position - position; + vec3 to_light_dir = normalize(light_direction); + vec4 light_color = calcLightColor(diffuse, specular, light.color, light.intensity, position, to_light_dir, normal,Metallic); + + float distance = length(light_direction); + float attenuationInv = light.attenuation.constant + light.attenuation.linear * distance + + light.attenuation.exponent * distance * distance; + return light_color / attenuationInv; +} + +vec4 calcSpotLight(vec4 diffuse, vec4 specular, Light light, vec3 position, vec3 normal,float Metallic) { + vec3 light_direction = light.position - position; + vec3 to_light_dir = normalize(light_direction); + vec3 from_light_dir = -to_light_dir; + float spot_alfa = dot(from_light_dir, normalize(light.conedir)); + + vec4 color = vec4(0, 0, 0, 0); + + if (spot_alfa > light.cutoff) + { + color = calcPointLight(diffuse, specular, light, position, normal,Metallic); + color *= (1.0 - (1.0 - spot_alfa)/(1.0 - light.cutoff)); + } + return color; +} + +vec4 calcDirLight(vec4 diffuse, vec4 specular, Light light, vec3 position, vec3 normal,float Metallic) { + return calcLightColor(diffuse, specular, light.color, light.intensity, position, normalize(light.position), normal,Metallic); +} + +vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN) +{ + vec3 newNormal = normal; + if (material.hasNormalMap > 0) + { + newNormal = texture(normalSampler, textCoords).rgb; + newNormal = normalize(newNormal * 2.0 - 1.0); + newNormal = normalize(TBN * newNormal); + } + return newNormal; +} + +float distributionGGX(vec3 N, vec3 H, float roughness) { + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; + + float nom = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; + + return nom / denom; +} + +float geometrySchlickGGX(float NdotV, float roughness) { + float r = (roughness + 1.0); + float k = (r * r) / 8.0; + + float nom = NdotV; + float denom = NdotV * (1.0 - k) + k; + + return nom / denom; +} + +float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = geometrySchlickGGX(NdotV, roughness); + float ggx1 = geometrySchlickGGX(NdotL, roughness); + + return ggx1 * ggx2; +} + +vec3 fresnelSchlick(float cosTheta, vec3 F0) { + return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); +} + +vec3 calculatePointLight(Light light, vec3 worldPos, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) { + vec3 tmpSub = light.position - worldPos; + vec3 L = normalize(tmpSub); + vec3 H = normalize(V + L); + + // Calculate distance and attenuation + float distance = length(tmpSub); + float attenuation = 1.0 / (distance * distance); + float intensity = 10.0f; + vec3 radiance = light.color * light.intensity * attenuation; + + // Cook-Torrance BRDF + float NDF = distributionGGX(N, H, roughness); + float G = geometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + float NdotL = max(dot(N, L), 0.0); + return (kD * albedo / PI + specular) * radiance * NdotL; +} + +vec3 calculateDirectionalLight(Light light, vec3 V, vec3 N, vec3 F0, vec3 albedo, float metallic, float roughness) { + vec3 L = normalize(-light.position); + vec3 H = normalize(V + L); + + vec3 radiance = light.color * light.intensity; + + // Cook-Torrance BRDF + float NDF = distributionGGX(N, H, roughness); + float G = geometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + float NdotL = max(dot(N, L), 0.0); + return (kD * albedo / PI + specular) * radiance * NdotL; +} + void main() { - vec4 texColor = texture(textureSampler,outTextCoords); - if(texColor.a < 0.4){discard;} - outAlbedo = texColor; - texColor = texColor + material.diffuse; + vec4 text_color = texture(textureSampler, outTextCoords); + if(text_color.a < 0.5) discard; + vec4 diffuse = text_color; + + mat3 TBN = mat3(outTangent, outBitangent, outNormal); + vec3 newNormal = calcNormal(material, outNormal, outTextCoords, TBN); + + float ao = 0.5; + float roughnessFactor = 0.0; + float metallicFactor = 0.0; + + if (material.hasRoughMap > 0) { + vec4 metRoughValue = texture(roughnessSampler, outTextCoords); + roughnessFactor = metRoughValue.g; + metallicFactor = metRoughValue.b; + } else { + roughnessFactor = material.roughnessFactor; + metallicFactor = material.metallicFactor; + } + vec4 specular = text_color + metallicFactor - roughnessFactor; + + vec4 pbr = vec4(ao, roughnessFactor, metallicFactor, text_color.a); + float roughness = pbr.g; + float metallic = pbr.b; + + vec3 N = normalize(newNormal); + vec3 V = normalize(sceneInfo.camPos - outPos.rgb); + + vec3 F0 = vec3(0.04); + F0 = mix(F0, text_color.rgb, metallic); + + vec3 Lo = vec3(0.0); + for (int i = 0; i < sceneInfo.LightCount; i++) { + Light light = lights[i]; + vec3 Pos = vec3(outPos.rgb); + if (light.lightType == 1) { + //Lo += calculateDirectionalLight(light, V, N, F0, text_color.rgb, metallic, roughness); + Lo += calcDirLight(diffuse, specular, light, Pos, outNormal,metallic).rgb; + } else { + // Lo += calculatePointLight(light, outPos.rgb, V, N, F0, text_color.rgb, metallic, roughness); + Lo += calcPointLight(diffuse, specular, light, Pos, outNormal,metallic).rgb; + } + } + vec3 ambient = sceneInfo.ambientLightColor * text_color.rgb * sceneInfo.ambientLightIntensity; + vec3 color = ambient + Lo; + + fragColor = vec4(color, 1.0f); } \ No newline at end of file diff --git a/resources/EngineResources/GLShaders/scene_frag_deferred.glsl b/resources/EngineResources/GLShaders/scene_frag_deferred.glsl new file mode 100644 index 0000000..a090f71 --- /dev/null +++ b/resources/EngineResources/GLShaders/scene_frag_deferred.glsl @@ -0,0 +1,77 @@ +#version 450 + +const int MAX_TEXTURES = 256; + +out vec4 outPos; +out vec3 outNormal; +out vec3 outTangent; +out vec3 outBitangent; +out vec2 outTextCoords; + +out vec4 outAlbedo ; +out vec4 outPosition; +out vec4 outNormals; +out vec4 outPBR; + +struct Material { + vec4 diffuse; + int hasTexture; + int hasNormalMap; + int hasRoughMap; + float roughnessFactor; + float metallicFactor; +}; + +uniform sampler2D textureSampler; +uniform sampler2D normalSampler; +uniform sampler2D roughnessSampler; +uniform Material material; + +vec3 calcNormal(Material material, vec3 normal, vec2 textCoords, mat3 TBN) +{ + vec3 newNormal = normal; + if (material.hasNormalMap > 0) + { + newNormal = texture(normalSampler, textCoords).rgb; + newNormal = normalize(newNormal * 2.0 - 1.0); + newNormal = normalize(TBN * newNormal); + } + return newNormal; +} + +layout(push_constant) uniform pc { + layout(offset = 64) uint materialIdx; +} push_constants; + +void main() +{ + outPosition = outPos; + + if (material.hasTexture == 1) { + outAlbedo = texture(textureSampler, outTextCoords); + } else { + outAlbedo = material.diffuse; + } + + + if(outAlbedo.a < 0.5) discard; + + mat3 TBN = mat3( outTangent, outBitangent, outNormal); + vec3 newNormal = calcNormal(material, outNormal, outTextCoords, TBN); + outNormals = vec4(newNormal, 1.0f); + + float ao = 0.5f; + float roughnessFactor = 0.0f; + float metallicFactor = 0.0f; + if (material.hasRoughMap > 0) { + vec4 metRoughValue = texture(roughnessSampler, outTextCoords); + roughnessFactor = metRoughValue.g; + metallicFactor = metRoughValue.b; + } else { + roughnessFactor = material.roughnessFactor; + metallicFactor = material.metallicFactor; + } + + outPBR = vec4(ao, roughnessFactor, metallicFactor, 1.0f); + +} \ No newline at end of file diff --git a/resources/EngineResources/GLShaders/scene_vert.glsl b/resources/EngineResources/GLShaders/scene_vert.glsl index efef138..b4b7f9f 100644 --- a/resources/EngineResources/GLShaders/scene_vert.glsl +++ b/resources/EngineResources/GLShaders/scene_vert.glsl @@ -19,12 +19,19 @@ uniform mat4 viewMatrix; void main() { - vec4 worldPos = modelMatrix * vec4(inPos,1); - gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(inPos, 1.0); - mat3 mNormal = transpose(inverse(mat3(modelMatrix))); - outPos = worldPos; - outNormal = mNormal * normalize(inNormal); - outTangent = mNormal * normalize(inTangent); - outBitangent = mNormal * normalize(inBitangent); +// vec4 worldPos = modelMatrix * vec4(inPos,1); +// gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(inPos, 1.0); +// mat3 mNormal = transpose(inverse(mat3(modelMatrix))); +// outPos = worldPos; +// outNormal = mNormal * normalize(inNormal); +// outTextCoords = inTextCoords; + + mat4 modelViewMatrix = viewMatrix * modelMatrix; + vec4 mvPosition = modelViewMatrix * vec4(inPos, 1.0); + gl_Position = projectionMatrix * mvPosition; + outPos = mvPosition; + outNormal = normalize(modelViewMatrix * vec4(inNormal, 0.0)).xyz; + outTangent = inNormal * normalize(inTangent); + outBitangent = inNormal * normalize(inBitangent); outTextCoords = inTextCoords; } \ No newline at end of file diff --git a/resources/EngineResources/shaders/scene_fragment.glsl b/resources/EngineResources/shaders/scene_fragment.glsl index 3832979..759800e 100644 --- a/resources/EngineResources/shaders/scene_fragment.glsl +++ b/resources/EngineResources/shaders/scene_fragment.glsl @@ -1,6 +1,6 @@ #version 450 -const int MAX_TEXTURES = 128; +const int MAX_TEXTURES = 256; layout(location = 0) in vec4 inPos; layout(location = 1) in vec3 inNormal; diff --git a/resources/EngineResources/shaders/scene_fragment_deferred.glsl b/resources/EngineResources/shaders/scene_fragment_deferred.glsl index e7a2cc6..fc873e0 100644 --- a/resources/EngineResources/shaders/scene_fragment_deferred.glsl +++ b/resources/EngineResources/shaders/scene_fragment_deferred.glsl @@ -1,6 +1,6 @@ #version 450 -const int MAX_TEXTURES = 128; +const int MAX_TEXTURES = 256; layout(location = 0) in vec4 inPos; layout(location = 1) in vec3 inNormal; diff --git a/resources/EngineResources/shaders/scene_fragment_deferred.glsl.spv b/resources/EngineResources/shaders/scene_fragment_deferred.glsl.spv index 36a0e20..16cea28 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 24eb61d..dea4039 100644 --- a/resources/EngineResources/shaders/scene_opaque_fragment.glsl +++ b/resources/EngineResources/shaders/scene_opaque_fragment.glsl @@ -1,6 +1,6 @@ #version 450 -const int MAX_TEXTURES = 128; +const int MAX_TEXTURES = 256; layout(location = 0) in vec4 inPos; layout(location = 1) in vec3 inNormal; diff --git a/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl b/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl index e0550f0..b230395 100644 --- a/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl +++ b/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl @@ -1,6 +1,6 @@ #version 450 -const int MAX_TEXTURES = 128; +const int MAX_TEXTURES = 256; layout(location = 0) in vec4 inPos; layout(location = 1) in vec3 inNormal; diff --git a/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl.spv b/resources/EngineResources/shaders/scene_opaque_fragment_deferred.glsl.spv index 54f86b3..c06da7b 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 d4f061b..f909b2e 100644 --- a/resources/EngineResources/shaders/scene_translucent_fragment.glsl +++ b/resources/EngineResources/shaders/scene_translucent_fragment.glsl @@ -1,6 +1,6 @@ #version 450 -const int MAX_TEXTURES = 128; +const int MAX_TEXTURES = 256; layout(location = 0) in vec4 inPos; layout(location = 1) in vec3 inNormal; diff --git a/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl b/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl index f11c471..1bdcf4a 100644 --- a/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl +++ b/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl @@ -1,6 +1,6 @@ #version 450 -const int MAX_TEXTURES = 128; +const int MAX_TEXTURES = 256; layout(location = 0) in vec4 inPos; layout(location = 1) in vec3 inNormal; diff --git a/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl.spv b/resources/EngineResources/shaders/scene_translucent_fragment_deferred.glsl.spv index 6544db2..e6305d2 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/skybox_fragment.glsl b/resources/EngineResources/shaders/skybox_fragment.glsl index e504856..42aa7ea 100644 --- a/resources/EngineResources/shaders/skybox_fragment.glsl +++ b/resources/EngineResources/shaders/skybox_fragment.glsl @@ -7,5 +7,7 @@ layout(location = 1) out vec4 outColor; layout(set = 2, binding = 0) uniform samplerCube skyboxSampler; void main() { - outColor = vec4(texture(skyboxSampler, outTexCoords).rgb, 1.0); + vec3 textureIn = texture(skyboxSampler, outTexCoords).rgb; + vec3 adjusted =vec3(0.0,textureIn.y/200.0,textureIn.z/150.0); + outColor = vec4(adjusted, 1.0); } \ 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 3198391..5d6b9f8 100644 Binary files a/resources/EngineResources/shaders/skybox_fragment.glsl.spv and b/resources/EngineResources/shaders/skybox_fragment.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 96cc71c..777fd24 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Display/OpenGLRenderer.java @@ -66,7 +66,8 @@ public class OpenGLRenderer implements Renderer{ Logger.debug("OpenGL version: [{}]", glGetString(GL_VERSION)); Logger.debug("GLSL version: [{}]", glGetString(GL_SHADING_LANGUAGE_VERSION)); glEnable(GL_DEPTH_TEST); - glClearColor(0.0f, 0.0f, 0.1f, 0.0f); + + glClearColor(0.6f, 0.7f, 1.0f, 0.0f); if(!LoggedNullCapabilities){ Logger.debug("Creating OpenGL Context On Render Thread"); LoggedNullCapabilities = true; diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/ConvexMesh.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/ConvexMesh.java index 889bdc1..91cf252 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/ConvexMesh.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Logic/Physics/RigidBody/ConvexMesh.java @@ -124,7 +124,7 @@ public class ConvexMesh { int[][] e = {{0,1},{1,2},{2,3},{3,0},{4,5},{5,6},{6,7},{7,4},{0,4},{1,5},{2,6},{3,7}}; mesh.Edges.addAll(Arrays.asList(e)); if(!PrimaryRuntime.IsServer && !RenderThread.Headless) { - PrimaryRuntime.GetEngineInstance().scene().AddActor(new VisualisedCollisionActor3D("VISUALISEDACTOR" + mesh.MeshID.toString(), mesh.Position, mesh.MeshID)); + // PrimaryRuntime.GetEngineInstance().scene().AddActor(new VisualisedCollisionActor3D("VISUALISEDACTOR" + mesh.MeshID.toString(), mesh.Position, mesh.MeshID)); } return mesh; } 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 bb4e724..bc994f9 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/GameCore.java @@ -99,6 +99,12 @@ public class GameCore implements GameLogic { public InitData Initialise(EngineInstance engineInstance) { Scene scene = (Scene) engineInstance.scene(); List models = 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)); MelonaData = ModelLoader.LoadModel("resources/models/cube/Cube.json"); CubeModelID = MelonaData.ID(); List MelonaMat = ModelLoader.LoadMaterials("resources/models/cube/Cube_mat.json"); @@ -141,6 +147,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(MelonaMat); materials.addAll(CollisionVisualisationMat); materials.addAll(MelonaMaterial); @@ -169,13 +179,47 @@ public class GameCore implements GameLogic { guiTextures.add(guiTexture); } - scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f); - scene.GetLightingManager().SetAmbientLightIntensity(0.6f); - - SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.3f), true, 2.00f); + //scene.GetLightingManager().GetAmbientLightColour().set(1.0f, 0.9f, 0.75f); + //scene.GetLightingManager().SetAmbientLightIntensity(0.6f); + scene.GetLightingManager().GetAmbientLightColour().set(0.3f, 0.35f, 0.5f); + scene.GetLightingManager().SetAmbientLightIntensity(0.01f); + // SkyLight = new Light(new Vector3f(1.5f, 1.20f, 1.0f),new Vector3f(0.0f, -1.0f, 0.3f), true, 2.00f); + SkyLight = new Light(new Vector3f(0.25f, 1.0f, 1.5f),new Vector3f(0.0f, -1.0f, 0.0f), true, 1.70f); + SkyLight.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(SkyLight); ILight[] lightArr = new ILight[lights.size()]; @@ -188,7 +232,7 @@ public class GameCore implements GameLogic { } //if(PrimaryRuntime.IsServer) { permutation.GeneratePermutationArray(5783904701859L); - GenerateChunk(new Vector3i(0, 0, 0), 16); + //GenerateChunk(new Vector3i(0, 0, 0), 16); for(int i = 0; i < 20; i++){ SpawnNewActor(engineInstance, new Vector3f(-5 + (float)Math.random() * 10,10 + (float)Math.random() * 10, -5 + (float)Math.random() * 10), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1)); } @@ -293,7 +337,7 @@ public class GameCore implements GameLogic { return player; } - public void SpawnNewActor(EngineInstance engineInstance, Vector3f Position, Vector3f Rotation, Vector3f Direction){ + public Actor3D SpawnNewActor(EngineInstance engineInstance, Vector3f Position, Vector3f Rotation, Vector3f Direction){ var scene = engineInstance.scene(); Camera camera = scene.GetCamera(); SpawnPosition.set(Position); @@ -314,6 +358,7 @@ public class GameCore implements GameLogic { RigidPhysicsController physicsController = (RigidPhysicsController) Melona.GetPhysicsController(); //RigidBody.RigidBodyRegister.get(physicsController.RigidBodyID).LinearVelocity.set(0,0,-20f -(40f * (float)Math.random())); scene.AddActor(Melona); + return Melona; } public void SpawnNewActorEditorComponent(EngineInstance engineInstance, Vector3f Position, Vector3f Rotation, Vector3f Direction){ diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/ILight.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/ILight.java index 9832234..4b98d90 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/ILight.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/ILight.java @@ -12,4 +12,14 @@ public interface ILight { public void SetColour(Vector3f Colour); public void SetPositon(float Position); public void SetDirectional(boolean Directional); + public Light.Attenuation GetAttenuation(); + public Light.LightType GetType(); + public void SetType(Light.LightType type); + public void SetAttenuation(Light.Attenuation attenuation); + public Vector3f getConeDirection(); + public float getCutOff(); + public float getCutOffAngle(); + + public void setConeDirection(float x, float y, float z); + public void setConeDirection(Vector3f coneDirection); } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/InputEvents/DebugCameraController.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/InputEvents/DebugCameraController.java index 8925802..cb485ba 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/InputEvents/DebugCameraController.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/InputEvents/DebugCameraController.java @@ -1,9 +1,14 @@ package net.halbear.Terrain4J.EngineCore.Main.Scene.InputEvents; import net.halbear.Terrain4J.EngineCore.Input.KeyboardInput; +import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidBody; +import net.halbear.Terrain4J.EngineCore.Logic.Physics.RigidBody.RigidPhysicsController; import net.halbear.Terrain4J.EngineCore.Main.GameCore; +import net.halbear.Terrain4J.EngineCore.Main.PrimaryRuntime; import net.halbear.Terrain4J.EngineCore.Main.Scene.*; +import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3D; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.PlayerActor3D; +import org.joml.Vector3f; import static org.lwjgl.glfw.GLFW.*; @@ -28,8 +33,16 @@ public class DebugCameraController implements IPlayerInputEvents { if(input.keyPressed(GLFW_KEY_SPACE)){ camera.MoveUp(MovementDist); } + if(input.keySinglePress(GLFW_KEY_F3)){ + Scene.GUI_MODE = (Scene.GUI_MODE + 1) % 2; + } if(input.keyPressed(GLFW_KEY_LEFT_CONTROL)){ camera.Sprint(true); } else camera.Sprint(false); + if(input.keySinglePress(GLFW_KEY_F)){ + for(int i = 0; i < 20; i++){ + Actor3D Melona = GameCore.SpawnNewActor(PrimaryRuntime.GetEngineInstance(), new Vector3f(-5 + (float)Math.random() * 10,10 + (float)Math.random() * 10, -5 + (float)Math.random() * 10), camera.GetRotation(), camera.GetDirection()); + } + } } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Light.java b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Light.java index 4549d83..b0c2e7c 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Light.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/Main/Scene/Light.java @@ -4,18 +4,90 @@ import org.joml.Vector3f; public class Light implements ILight{ + public LightType GetType() { + return type; + } + + public void SetType(LightType type) { + this.type = type; + } + + public enum LightType{ + Spot, + Point, + Directional, + Ambient + } + + private Attenuation attenuation; private final Vector3f Colour; private final Vector3f Position; - private boolean Directional; - private float Intensity; + private boolean Directional = false; + private float Intensity = 0; + private LightType type = LightType.Point; + private Vector3f coneDirection = new Vector3f(); + private float cutOff = 0; + private float cutOffAngle = 0; public Light(Vector3f Colour, Vector3f Position, boolean Directional, float Intensity){ + attenuation = new Attenuation(0, 0, 1); this.Colour = Colour; this.Position = Position; this.Directional = Directional; this.Intensity = Intensity; } + public Light(Vector3f Colour, Vector3f Position, LightType type, float Intensity){ + attenuation = new Attenuation(0, 0, 1); + this.Colour = Colour; + this.Position = Position; + this.Directional = type == LightType.Directional; + this.type = type; + this.Intensity = Intensity; + } + + public Light(Vector3f Colour, Vector3f Position, Vector3f coneDirection, float cutOffAngle, float Intensity){ + attenuation = new Attenuation(0, 0, 1); + this.Colour = Colour; + this.Position = Position; + this.Directional = false; + this.type = LightType.Spot; + this.Intensity = Intensity; + } + + public Vector3f getConeDirection() { + return coneDirection; + } + + public float getCutOff() { + return cutOff; + } + + public float getCutOffAngle() { + return cutOffAngle; + } + + public void setConeDirection(float x, float y, float z) { + coneDirection.set(x, y, z); + } + + public void setConeDirection(Vector3f coneDirection) { + this.coneDirection = coneDirection; + } + + public final void setCutOffAngle(float cutOffAngle) { + this.cutOffAngle = cutOffAngle; + cutOff = (float) Math.cos(Math.toRadians(cutOffAngle)); + } + + public Attenuation GetAttenuation() { + return attenuation; + } + + public void SetAttenuation(Attenuation attenuation) { + this.attenuation = attenuation; + } + @Override public Vector3f GetColour() { return Colour; @@ -55,4 +127,41 @@ public class Light implements ILight{ public void SetDirectional(boolean Directional) { this.Directional = Directional; } + + public static class Attenuation { + + private float constant; + private float exponent; + private float linear; + + public Attenuation(float constant, float linear, float exponent) { + this.constant = constant; + this.linear = linear; + this.exponent = exponent; + } + + public float getConstant() { + return constant; + } + + public float getExponent() { + return exponent; + } + + public float getLinear() { + return linear; + } + + public void setConstant(float constant) { + this.constant = constant; + } + + public void setExponent(float exponent) { + this.exponent = exponent; + } + + public void setLinear(float linear) { + this.linear = linear; + } + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMaterial.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMaterial.java index b431551..08d942a 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMaterial.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLMaterial.java @@ -8,10 +8,15 @@ import java.util.List; public class GLMaterial { private final List meshList; private String texturePath; + String NormalTexturePath; + boolean hasMetalRoughnessMap; + boolean hasNormalMap; + String MetalRoughnessMap; + Vector4f DiffuseColour; + float Roughness; + float Metallic; public static final Vector4f DEFAULT_COLOUR = new Vector4f(0.0f, 0.0f, 0.0f, 1.0f); - private Vector4f DiffuseColour; - public GLMaterial() { meshList = new ArrayList<>(); DiffuseColour = DEFAULT_COLOUR; @@ -39,4 +44,44 @@ public class GLMaterial { public void SetDiffuseColour(Vector4f diffuseColour) { this.DiffuseColour = diffuseColour; } + + public String GetNormalTexturePath() { + return NormalTexturePath; + } + + public void SetNormalTexturePath(String texturePath) { + this.NormalTexturePath = texturePath; + } + + public boolean HasNormalMap() { + return hasNormalMap; + } + public void HasNormalMap(boolean Set){this.hasNormalMap = Set;} + + public String GetRoughnessTexturePath() { + return MetalRoughnessMap; + } + + public void SetRoughnessTexturePath(String texturePath) { + this.MetalRoughnessMap = texturePath; + } + + public boolean HasRoughnessMap() { + return hasMetalRoughnessMap; + } + public void HasRoughnessMap(boolean Set){this.hasMetalRoughnessMap = Set;} + public float GetRoughness() { + return Roughness; + } + public void SetRoughness(float roughness) { + this.Roughness = roughness; + } + + public float GetMetallic() { + return Metallic; + } + public void SetMetallic(float metallic) { + this.Metallic = metallic; + } + } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModelLoader.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModelLoader.java deleted file mode 100644 index 8d9e0b9..0000000 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/GlModels/GLModelLoader.java +++ /dev/null @@ -1,151 +0,0 @@ -//package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels; -// -//import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.Texture; -//import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Images.TextureCache; -//import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; -//import org.joml.Vector4f; -//import org.lwjgl.PointerBuffer; -//import org.lwjgl.assimp.*; -//import org.lwjgl.system.MemoryStack; -// -//import java.io.File; -//import java.nio.IntBuffer; -//import java.util.ArrayList; -//import java.util.List; -// -//import static org.lwjgl.assimp.Assimp.*; -// -//public class GLModelLoader { -// private GLModelLoader() { -// } -// -// -// -// public static GLModel loadModel(String ModelId, String ModelPath, TextureCache textureCache) { -// return loadModel(ModelId, ModelPath, textureCache, aiProcess_GenSmoothNormals | aiProcess_JoinIdenticalVertices | -// aiProcess_Triangulate | aiProcess_FixInfacingNormals | aiProcess_CalcTangentSpace | aiProcess_LimitBoneWeights | -// aiProcess_PreTransformVertices); -// -// } -// -// public static GLModel loadModel(String ModelId, String ModelPath, TextureCache textureCache, int Flags) { -// File file = new File(ModelPath); -// if (!file.exists()) { -// throw new RuntimeException("Model path does not exist: " + ModelPath); -// } -// String ModelDir = file.getParent(); -// -// AIScene aiScene = aiImportFile(ModelPath, Flags); -// if (aiScene == null) { -// throw new RuntimeException("Error loading model: " + ModelPath); -// } -// -// int MaterialCount = aiScene.mNumMaterials(); -// List materialList = new ArrayList<>(); -// for (int i = 0; i < MaterialCount; i++) { -// AIMaterial aiMaterial = AIMaterial.create(aiScene.mMaterials().get(i)); -// materialList.add(ProcessMaterial(aiMaterial, ModelDir, textureCache)); -// } -// -// int MeshCount = aiScene.mNumMeshes(); -// PointerBuffer aiMeshes = aiScene.mMeshes(); -// GLMaterial defaultMaterial = new GLMaterial(); -// for (int i = 0; i < MeshCount; i++) { -// AIMesh aiMesh = AIMesh.create(aiMeshes.get(i)); -// GLMesh mesh = ProcessMesh(aiMesh); -// int materialIdx = aiMesh.mMaterialIndex(); -// GLMaterial material; -// if (materialIdx >= 0 && materialIdx < materialList.size()) { -// material = materialList.get(materialIdx); -// } else { -// material = defaultMaterial; -// } -// material.GetMeshList().add(mesh); -// } -// -// if (!defaultMaterial.GetMeshList().isEmpty()) { -// materialList.add(defaultMaterial); -// } -// -// return new GLModel(ModelId, materialList); -// } -// -// private static GLMaterial ProcessMaterial(AIMaterial aiMaterial, String modelDir, TextureCache textureCache) { -// GLMaterial Material = new GLMaterial(); -// try (MemoryStack stack = MemoryStack.stackPush()) { -// AIColor4D color = AIColor4D.create(); -// -// int result = aiGetMaterialColor(aiMaterial, AI_MATKEY_COLOR_DIFFUSE, aiTextureType_NONE, 0, -// color); -// if (result == aiReturn_SUCCESS) { -// Material.SetDiffuseColour(new Vector4f(color.r(), color.g(), color.b(), color.a())); -// } -// -// AIString aiTexturePath = AIString.calloc(stack); -// aiGetMaterialTexture(aiMaterial, aiTextureType_DIFFUSE, 0, aiTexturePath, (IntBuffer) null, -// null, null, null, null, null); -// String TexturePath = aiTexturePath.dataString(); -// if (TexturePath != null && TexturePath.length() > 0) { -// Material.SetTexturePath(modelDir + File.separator + new File(TexturePath).getName()); -// textureCache.CreateTexture(Material.GetTexturePath()); -// Material.SetDiffuseColour(GLMaterial.DEFAULT_COLOUR); -// } -// -// return Material; -// } -// } -// private static GLMesh ProcessMesh(AIMesh aiMesh) { -// float[] vertices = ProcessVertices(aiMesh); -// float[] textCoords = ProcessTextCoords(aiMesh); -// int[] indices = ProcessIndices(aiMesh); -// -// if (textCoords.length == 0) { -// int numElements = (vertices.length / 3) * 2; -// textCoords = new float[numElements]; -// } -// -// return new GLMesh(vertices, textCoords, indices); -// } -// -// private static int[] ProcessIndices(AIMesh aiMesh) { -// List indices = new ArrayList<>(); -// int FaceCount = aiMesh.mNumFaces(); -// AIFace.Buffer aiFaces = aiMesh.mFaces(); -// for (int i = 0; i < FaceCount; i++) { -// AIFace aiFace = aiFaces.get(i); -// IntBuffer buffer = aiFace.mIndices(); -// while (buffer.remaining() > 0) { -// indices.add(buffer.get()); -// } -// } -// return indices.stream().mapToInt(Integer::intValue).toArray(); -// } -// -// private static float[] ProcessTextCoords(AIMesh aiMesh) { -// AIVector3D.Buffer TextureCoordBuffer = aiMesh.mTextureCoords(0); -// if (TextureCoordBuffer == null) { -// return new float[]{}; -// } -// float[] data = new float[TextureCoordBuffer.remaining() * 2]; -// int index = 0; -// while (TextureCoordBuffer.remaining() > 0) { -// AIVector3D TextureCoord = TextureCoordBuffer.get(); -// data[index++] = TextureCoord.x(); -// data[index++] = 1 - TextureCoord.y(); -// } -// return data; -// } -// -// private static float[] ProcessVertices(AIMesh aiMesh) { -// AIVector3D.Buffer VertexBuffer = aiMesh.mVertices(); -// float[] data = new float[VertexBuffer.remaining() * 3]; -// int index = 0; -// while (VertexBuffer.remaining() > 0) { -// AIVector3D TextureCoord = VertexBuffer.get(); -// data[index++] = TextureCoord.x(); -// data[index++] = TextureCoord.y(); -// data[index++] = TextureCoord.z(); -// } -// return data; -// } -//} diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java index 165fc35..a1138a2 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Rendering/ForwardRenderer.java @@ -1,9 +1,12 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Rendering; import imgui.extension.imguizmo.flag.Mode; +import net.halbear.Terrain4J.EngineCore.Logic.Rendering.VulkanContext; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3D; import net.halbear.Terrain4J.EngineCore.Main.Scene.Actor.Actor3DElement; +import net.halbear.Terrain4J.EngineCore.Main.Scene.ILight; import net.halbear.Terrain4J.EngineCore.Main.Scene.IScene; +import net.halbear.Terrain4J.EngineCore.Main.Scene.Light; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.GLMaterial; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.GLMesh; import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.GlModels.GLModel; @@ -14,24 +17,31 @@ import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader.ShaderProgram import net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader.UniformsMap; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Universal.Interfaces.ITextureCache; import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Rendering.Pipeline.Images.ITexture; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanBuffer; +import net.halbear.Terrain4J.EngineCore.RenderingAPI.Vulkan.Util.VulkanUtils; import net.halbear.Terrain4J.EngineCore.ServerNetworking.ClientSideNetworkUtils; +import org.joml.Matrix4f; import org.joml.Vector3f; +import org.joml.Vector4f; +import org.lwjgl.system.MemoryUtil; import org.tinylog.Logger; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import static org.lwjgl.opengl.GL11.*; -import static org.lwjgl.opengl.GL13.GL_TEXTURE0; -import static org.lwjgl.opengl.GL13.glActiveTexture; +import static org.lwjgl.opengl.GL13.*; import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER; import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER; import static org.lwjgl.opengl.GL30.glBindVertexArray; public class ForwardRenderer implements SceneRender{ + private static final int MAX_LIGHTS = 32; + private final ShaderProgram shaderProgram; private UniformsMap uniformsMap; @@ -48,8 +58,32 @@ public class ForwardRenderer implements SceneRender{ uniformsMap.CreateUniform("projectionMatrix"); uniformsMap.CreateUniform("modelMatrix"); uniformsMap.CreateUniform("textureSampler"); + uniformsMap.CreateUniform("normalSampler"); + uniformsMap.CreateUniform("roughnessSampler"); uniformsMap.CreateUniform("viewMatrix"); + uniformsMap.CreateUniform("sceneInfo.camPos"); + uniformsMap.CreateUniform("sceneInfo.ambientLightIntensity"); + uniformsMap.CreateUniform("sceneInfo.ambientLightColor"); + uniformsMap.CreateUniform("sceneInfo.LightCount"); uniformsMap.CreateUniform("material.diffuse"); + uniformsMap.CreateUniform("material.hasTexture"); + uniformsMap.CreateUniform("material.hasNormalMap"); + uniformsMap.CreateUniform("material.hasRoughMap"); + uniformsMap.CreateUniform("material.roughnessFactor"); + uniformsMap.CreateUniform("material.metallicFactor"); + + for (int i = 0; i < MAX_LIGHTS; i++) { + String name = "lights[" + i + "]"; + uniformsMap.CreateUniform(name + ".position"); + uniformsMap.CreateUniform(name + ".lightType"); + uniformsMap.CreateUniform(name + ".intensity"); + uniformsMap.CreateUniform(name + ".color"); + uniformsMap.CreateUniform(name + ".conedir"); + uniformsMap.CreateUniform(name + ".cutoff"); + uniformsMap.CreateUniform(name + ".attenuation.constant"); + uniformsMap.CreateUniform(name + ".attenuation.linear"); + uniformsMap.CreateUniform(name + ".attenuation.exponent"); + } } @Override @@ -60,9 +94,17 @@ public class ForwardRenderer implements SceneRender{ @Override public void Render(IScene scene, ModelsCache modelsCache, TextureCache textureCache) { shaderProgram.Bind(); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); uniformsMap.SetUniform("projectionMatrix", scene.GetProjection().GetProjectionMatrix()); uniformsMap.SetUniform("viewMatrix", scene.GetCamera().GetViewMatrix()); + uniformsMap.SetUniform("sceneInfo.camPos", scene.GetCamera().GetPosition()); + uniformsMap.SetUniform("sceneInfo.ambientLightIntensity", scene.GetLightingManager().GetAmbientLightIntensity()); + uniformsMap.SetUniform("sceneInfo.ambientLightColor", scene.GetLightingManager().GetAmbientLightColour()); uniformsMap.SetUniform("textureSampler", 0); + uniformsMap.SetUniform("normalSampler", 1); + uniformsMap.SetUniform("roughnessSampler", 2); + UpdateLights(scene); Map models = modelsCache.GetModelMap(); for (Actor3D actor : scene.GetActors()) { if(actor instanceof Actor3DElement &&( !((Actor3DElement) actor).RenderOnTopOfPlayer && ClientSideNetworkUtils.OwnsActor(((Actor3DElement) actor).GetParentID()) || new Vector3f().set(actor.GetPosition()).sub(scene.GetCamera().GetPosition()).absolute().lengthSquared() < 4f)) continue; @@ -71,9 +113,21 @@ public class ForwardRenderer implements SceneRender{ if(model == null) continue; model.GetMeshList().stream().forEach(mesh -> { GLMaterial material = modelsCache.GetMaterial(mesh.MaterialID()); + uniformsMap.SetUniform("material.diffuse", material.GetDiffuseColour()); + uniformsMap.SetUniform("material.hasTexture", 1); + uniformsMap.SetUniform("material.hasNormalMap", material.HasNormalMap() ? 1 : 0); + uniformsMap.SetUniform("material.hasRoughMap", material.HasRoughnessMap() ? 1 : 0); + uniformsMap.SetUniform("material.roughnessFactor", material.GetRoughness()); + uniformsMap.SetUniform("material.metallicFactor", material.GetMetallic()); ITexture texture = textureCache.GetTexture(material.GetTexturePath()); glActiveTexture(GL_TEXTURE0); texture.Bind(); + texture = textureCache.GetTexture(material.HasNormalMap() ? material.GetNormalTexturePath() : TextureCache.DEFAULT_TEXTURE_PATH); + glActiveTexture(GL_TEXTURE1); + texture.Bind(); + texture = textureCache.GetTexture(material.HasRoughnessMap() ? material.GetRoughnessTexturePath() : TextureCache.DEFAULT_TEXTURE_PATH); + glActiveTexture(GL_TEXTURE2); + texture.Bind(); uniformsMap.SetUniform("material.diffuse", material.GetDiffuseColour()); glBindVertexArray(mesh.GetVaoID()); uniformsMap.SetUniform("modelMatrix", actor.GetModelMatrix()); @@ -85,4 +139,62 @@ public class ForwardRenderer implements SceneRender{ shaderProgram.UnBind(); } + + public void UpdateLights( IScene scene){ + ILight[] lights = scene.GetLightingManager().GetLights(); + Matrix4f viewMatrix = scene.GetCamera().GetViewMatrix(); + int lightCount = Math.min(lights != null ? lights.length : 0, MAX_LIGHTS); + uniformsMap.SetUniform("sceneInfo.LightCount", lightCount); + ILight light; + for(int i = 0; i < lightCount; i++){ + if (i < MAX_LIGHTS) { + light =lights[i];; + } else { + light = null; + } + String name = "lights[" + i + "]"; + UpdateLight(light, name, viewMatrix); + } + } + + private void UpdateLight(ILight light, String prefix, Matrix4f viewMatrix) { + Vector4f aux = new Vector4f(); + Vector3f lightPosition = new Vector3f(); + Vector3f color = new Vector3f(); + float intensity = 0.0f; + float constant = 0.0f; + float linear = 0.0f; + float exponent = 0.0f; + int LightType = 0; + Vector3f ConeDir = new Vector3f(0,0,0); + float Cutoff = 0f; + if (light != null) { + switch(light.GetType()){ + case Point -> LightType = 0; + case Directional -> LightType = 1; + case Ambient -> LightType = 2; + case Spot -> LightType = 3; + } + aux.set(light.GetPosition(), 1); + aux.mul(viewMatrix); + lightPosition.set(aux.x, aux.y, aux.z); + color.set(light.GetColour()); + intensity = light.GetIntensity(); + Light.Attenuation attenuation = light.GetAttenuation(); + constant = attenuation.getConstant(); + linear = attenuation.getLinear(); + exponent = attenuation.getExponent(); + ConeDir = light.getConeDirection(); + Cutoff = light.getCutOff(); + } + uniformsMap.SetUniform(prefix + ".position", lightPosition); + uniformsMap.SetUniform(prefix + ".lightType", LightType); + uniformsMap.SetUniform(prefix + ".intensity", intensity); + uniformsMap.SetUniform(prefix + ".color", color); + uniformsMap.SetUniform(prefix + ".conedir", ConeDir); + uniformsMap.SetUniform(prefix + ".cutoff", Cutoff); + uniformsMap.SetUniform(prefix + ".attenuation.constant", constant); + uniformsMap.SetUniform(prefix + ".attenuation.linear", linear); + uniformsMap.SetUniform(prefix + ".attenuation.exponent", exponent); + } } diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java index a677895..e82ca83 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/ShaderProgram.java @@ -71,7 +71,10 @@ public class ShaderProgram { public void LinkShaderProgram(List ShaderModules){ glLinkProgram(ProgramID); if(glGetProgrami(ProgramID, GL_LINK_STATUS) == GL_FALSE){ - Logger.error("Failed to link shader program: [{}]", glGetProgramInfoLog(ProgramID, 1024)); + String infoLog = glGetProgramInfoLog(ProgramID, 1024); + ShaderModules.forEach(ShaderID -> glDetachShader(ProgramID, ShaderID)); + ShaderModules.forEach(GL30::glDeleteShader); + throw new RuntimeException("Failed to link shader program: " + infoLog); } ShaderModules.forEach(ShaderID -> glDetachShader(ProgramID, ShaderID)); diff --git a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/UniformsMap.java b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/UniformsMap.java index 8f082c6..a1bb1b9 100644 --- a/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/UniformsMap.java +++ b/src/main/java/net/halbear/Terrain4J/EngineCore/RenderingAPI/OpenGL/Shader/UniformsMap.java @@ -2,6 +2,7 @@ package net.halbear.Terrain4J.EngineCore.RenderingAPI.OpenGL.Shader; import org.joml.Matrix4f; import org.joml.Vector2f; +import org.joml.Vector3f; import org.joml.Vector4f; import org.lwjgl.system.MemoryStack; @@ -53,4 +54,12 @@ public class UniformsMap { public void SetUniform(String uniformName, Vector2f value) { glUniform2f(GetUniformLocation(uniformName), value.x, value.y); } + + public void SetUniform(String uniformName, float value) { + glUniform1f(GetUniformLocation(uniformName), value); + } + + public void SetUniform(String uniformName, Vector3f value) { + glUniform3f(GetUniformLocation(uniformName), value.x, value.y, value.z); + } } 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 9279d28..d5a5122 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 @@ -18,7 +18,7 @@ import java.util.UUID; import static org.lwjgl.vulkan.VK10.VK_FORMAT_R8G8B8A8_SRGB; public class TextureCache implements ITextureCache { - public static final int MAX_TEXTURES = 128; + public static final int MAX_TEXTURES = 256; private final IndexedLinkedHashMap TextureMap; private final List ActualTextures; diff --git a/terrain4j.properties b/terrain4j.properties index eba432f..cfd03fa 100644 --- a/terrain4j.properties +++ b/terrain4j.properties @@ -1,5 +1,5 @@ #created new properties file -#Sat Aug 29 04:15:30 BST 2026 +#Sat Aug 29 18:05:29 BST 2026 AlphaToCoverage=false Debug_Shaders=false DefaultTexturePath=resources/EngineResources/Texture/NoTexture.png