From 7759a63973c55407adc0fbc7226a2b63b6963793 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 28 Nov 2023 00:20:40 +0300 Subject: [PATCH 1/4] Removed dark overlay for content access mode --- src/frontend/hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index b7e1c656..c39f2267 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -307,7 +307,7 @@ void HudRenderer::draw(const GfxContext& ctx){ } } - if (pause || inventoryOpen) { + if (pause) { batch->texture(nullptr); batch->color = vec4(0.0f, 0.0f, 0.0f, 0.5f); batch->rect(0, 0, width, height); From 4a9a4ddd1484a07a7eba0bd4f6b8a07e53e73b4e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 28 Nov 2023 10:02:59 +0300 Subject: [PATCH 2/4] binary_io fix --- src/files/binary_io.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/files/binary_io.cpp b/src/files/binary_io.cpp index 94c8e7ba..f12b97ed 100644 --- a/src/files/binary_io.cpp +++ b/src/files/binary_io.cpp @@ -101,7 +101,7 @@ ubyte BinaryReader::get() { } int16_t BinaryReader::getInt16() { - if (pos+2 >= size) { + if (pos+2 > size) { throw std::underflow_error("unexpected end"); } pos += 2; @@ -110,7 +110,7 @@ int16_t BinaryReader::getInt16() { } int32_t BinaryReader::getInt32() { - if (pos+4 >= size) { + if (pos+4 > size) { throw std::underflow_error("unexpected end"); } pos += 4; @@ -121,7 +121,7 @@ int32_t BinaryReader::getInt32() { } int64_t BinaryReader::getInt64() { - if (pos+8 >= size) { + if (pos+8 > size) { throw std::underflow_error("unexpected end"); } pos += 8; From c08c31b0ad13b1baf53d0acaba19ac630210bb11 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 28 Nov 2023 11:01:22 +0300 Subject: [PATCH 3/4] day-night loop, dynamic skybox, clock on debug panel --- res/shaders/background.glslf | 11 + res/shaders/background.glslv | 14 + res/shaders/main.glslf | 5 +- res/shaders/main.glslv | 15 +- res/shaders/screen.glslf | 10 - res/shaders/skybox_gen.glslf | 291 ++++++++++++++++++ .../{screen.glslv => skybox_gen.glslv} | 20 +- src/assets/AssetsLoader.cpp | 2 + src/files/WorldFiles.cpp | 11 +- src/files/WorldFiles.h | 2 + src/frontend/graphics/Skybox.cpp | 111 +++++++ src/frontend/graphics/Skybox.h | 30 ++ src/frontend/hud.cpp | 16 +- src/frontend/screens.cpp | 3 + src/frontend/world_render.cpp | 36 ++- src/frontend/world_render.h | 4 +- src/util/timeutil.cpp | 14 + src/util/timeutil.h | 9 + src/window/Camera.cpp | 11 +- src/window/Camera.h | 2 +- src/window/Window.cpp | 9 + src/window/Window.h | 1 + src/world/World.cpp | 11 +- src/world/World.h | 9 + 24 files changed, 599 insertions(+), 48 deletions(-) create mode 100644 res/shaders/background.glslf create mode 100644 res/shaders/background.glslv delete mode 100644 res/shaders/screen.glslf create mode 100644 res/shaders/skybox_gen.glslf rename res/shaders/{screen.glslv => skybox_gen.glslv} (80%) create mode 100644 src/frontend/graphics/Skybox.cpp create mode 100644 src/frontend/graphics/Skybox.h create mode 100644 src/util/timeutil.cpp create mode 100644 src/util/timeutil.h diff --git a/res/shaders/background.glslf b/res/shaders/background.glslf new file mode 100644 index 00000000..c494c564 --- /dev/null +++ b/res/shaders/background.glslf @@ -0,0 +1,11 @@ +#version 330 core + +in vec3 v_coord; +out vec4 f_color; + +uniform samplerCube u_cubemap; + +void main(){ + vec3 dir = normalize(v_coord); + f_color = texture(u_cubemap, dir); +} diff --git a/res/shaders/background.glslv b/res/shaders/background.glslv new file mode 100644 index 00000000..e2d461c2 --- /dev/null +++ b/res/shaders/background.glslv @@ -0,0 +1,14 @@ +#version 330 core + +layout (location = 0) in vec2 v_position; + +out vec3 v_coord; + +uniform mat4 u_view; +uniform float u_ar; +uniform float u_zoom; + +void main(){ + v_coord = (vec4(v_position*vec2(u_ar, 1.0f)*u_zoom, -1.0, 1.0) * u_view).xyz; + gl_Position = vec4(v_position, 0.0, 1.0); +} diff --git a/res/shaders/main.glslf b/res/shaders/main.glslf index e37eedd4..1cc3d8b7 100644 --- a/res/shaders/main.glslf +++ b/res/shaders/main.glslf @@ -3,20 +3,23 @@ in vec4 a_color; in vec2 a_texCoord; in float a_distance; +in vec3 a_dir; out vec4 f_color; uniform sampler2D u_texture0; +uniform samplerCube u_cubemap; uniform vec3 u_fogColor; uniform float u_fogFactor; uniform float u_fogCurve; void main(){ + vec3 fogColor = texture(u_cubemap, a_dir).rgb; vec4 tex_color = texture(u_texture0, a_texCoord); float depth = (a_distance/256.0); float alpha = a_color.a * tex_color.a; // anyway it's any alpha-test alternative required if (alpha < 0.1f) discard; - f_color = mix(a_color * tex_color, vec4(u_fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve))); + f_color = mix(a_color * tex_color, vec4(fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve))); f_color.a = alpha; } diff --git a/res/shaders/main.glslv b/res/shaders/main.glslv index 6e1303fb..7f50bc1f 100644 --- a/res/shaders/main.glslv +++ b/res/shaders/main.glslv @@ -7,6 +7,7 @@ layout (location = 2) in float v_light; out vec4 a_color; out vec2 a_texCoord; out float a_distance; +out vec3 a_dir; uniform mat4 u_model; uniform mat4 u_proj; @@ -14,10 +15,13 @@ uniform mat4 u_view; uniform vec3 u_skyLightColor; uniform vec3 u_cameraPos; uniform float u_gamma; +uniform samplerCube u_cubemap; uniform vec3 u_torchlightColor; uniform float u_torchlightDistance; +#define SKY_LIGHT_MUL 2.5 + vec4 decompress_light(float compressed_light) { vec4 result; int compressed = floatBitsToInt(compressed_light); @@ -30,15 +34,22 @@ vec4 decompress_light(float compressed_light) { void main(){ vec2 pos2d = (u_model * vec4(v_position, 1.0)).xz-u_cameraPos.xz; - vec4 modelpos = u_model * vec4(v_position+vec3(0,pow(length(pos2d)*0.0, 3.0),0), 1.0); + vec4 modelpos = u_model * vec4(v_position, 1.0); vec4 viewmodelpos = u_view * modelpos; vec4 decomp_light = decompress_light(v_light); vec3 light = decomp_light.rgb; float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz)/u_torchlightDistance); + a_dir = modelpos.xyz - u_cameraPos; light += torchlight * u_torchlightColor; a_color = vec4(pow(light, vec3(u_gamma)),1.0f); a_texCoord = v_texCoord; - a_color.rgb = max(a_color.rgb, u_skyLightColor.rgb*decomp_light.a); + + vec3 skyLightColor = texture(u_cubemap, vec3(-0.4f, -0.4f, -0.4f)).rgb; + skyLightColor.g *= 0.9; + skyLightColor.b *= 0.8; + skyLightColor = min(vec3(1.0), skyLightColor*SKY_LIGHT_MUL); + + a_color.rgb = max(a_color.rgb, skyLightColor.rgb*decomp_light.a); a_distance = length(viewmodelpos); gl_Position = u_proj * viewmodelpos; } diff --git a/res/shaders/screen.glslf b/res/shaders/screen.glslf deleted file mode 100644 index f8db40a1..00000000 --- a/res/shaders/screen.glslf +++ /dev/null @@ -1,10 +0,0 @@ -#version 330 core - -in vec2 v_coord; -out vec4 f_color; - -uniform sampler2D u_texture; - -void main(){ - f_color = texture(u_texture, v_coord); -} diff --git a/res/shaders/skybox_gen.glslf b/res/shaders/skybox_gen.glslf new file mode 100644 index 00000000..d7886eec --- /dev/null +++ b/res/shaders/skybox_gen.glslf @@ -0,0 +1,291 @@ +/* +MIT License + +Copyright (c) 2019 Dimas Leenman + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#version 330 core + +// first, lets define some constants to use (planet radius, position, and scattering coefficients) +#define PLANET_POS vec3(0.0) /* the position of the planet */ +#define PLANET_RADIUS 6371e3 /* radius of the planet */ +#define ATMOS_RADIUS 6471e3 /* radius of the atmosphere */ +// scattering coeffs +#define RAY_BETA vec3(5.5e-6, 13.0e-6, 22.4e-6) /* rayleigh, affects the color of the sky */ +#define MIE_BETA vec3(21e-6) /* mie, affects the color of the blob around the sun */ +#define AMBIENT_BETA vec3(0.0) /* ambient, affects the scattering color when there is no lighting from the sun */ +#define ABSORPTION_BETA vec3(2.04e-5, 4.97e-5, 1.95e-6) /* what color gets absorbed by the atmosphere (Due to things like ozone) */ +#define G 0.9 /* mie scattering direction, or how big the blob around the sun is */ +// and the heights (how far to go up before the scattering has no effect) +#define HEIGHT_RAY 8e3 /* rayleigh height */ +#define HEIGHT_MIE 1.2e3 /* and mie */ +#define HEIGHT_ABSORPTION 30e3 /* at what height the absorption is at it's maximum */ +#define ABSORPTION_FALLOFF 4e3 /* how much the absorption decreases the further away it gets from the maximum height */ +// and the steps (more looks better, but is slower) +// the primary step has the most effect on looks +#define PRIMARY_STEPS 12 +#define LIGHT_STEPS 4 + +vec3 calculate_scattering( + vec3 start, // the start of the ray (the camera position) + vec3 dir, // the direction of the ray (the camera vector) + float max_dist, // the maximum distance the ray can travel (because something is in the way, like an object) + vec3 scene_color, // the color of the scene + vec3 light_dir, // the direction of the light + vec3 light_intensity, // how bright the light is, affects the brightness of the atmosphere + vec3 planet_position, // the position of the planet + float planet_radius, // the radius of the planet + float atmo_radius, // the radius of the atmosphere + vec3 beta_ray, // the amount rayleigh scattering scatters the colors (for earth: causes the blue atmosphere) + vec3 beta_mie, // the amount mie scattering scatters colors + vec3 beta_absorption, // how much air is absorbed + vec3 beta_ambient, // the amount of scattering that always occurs, cna help make the back side of the atmosphere a bit brighter + float g, // the direction mie scatters the light in (like a cone). closer to -1 means more towards a single direction + float height_ray, // how high do you have to go before there is no rayleigh scattering? + float height_mie, // the same, but for mie + float height_absorption, // the height at which the most absorption happens + float absorption_falloff, // how fast the absorption falls off from the absorption height + int steps_i, // the amount of steps along the 'primary' ray, more looks better but slower + int steps_l // the amount of steps along the light ray, more looks better but slower +) { + // add an offset to the camera position, so that the atmosphere is in the correct position + start -= planet_position; + // calculate the start and end position of the ray, as a distance along the ray + // we do this with a ray sphere intersect + float a = dot(dir, dir); + float b = 2.0 * dot(dir, start); + float c = dot(start, start) - (atmo_radius * atmo_radius); + float d = (b * b) - 4.0 * a * c; + + // stop early if there is no intersect + if (d < 0.0) return scene_color; + + // calculate the ray length + vec2 ray_length = vec2( + max((-b - sqrt(d)) / (2.0 * a), 0.0), + min((-b + sqrt(d)) / (2.0 * a), max_dist) + ); + + // if the ray did not hit the atmosphere, return a black color + if (ray_length.x > ray_length.y) return scene_color; + // prevent the mie glow from appearing if there's an object in front of the camera + bool allow_mie = max_dist > ray_length.y; + // make sure the ray is no longer than allowed + ray_length.y = min(ray_length.y, max_dist); + ray_length.x = max(ray_length.x, 0.0); + // get the step size of the ray + float step_size_i = (ray_length.y - ray_length.x) / float(steps_i); + + // next, set how far we are along the ray, so we can calculate the position of the sample + // if the camera is outside the atmosphere, the ray should start at the edge of the atmosphere + // if it's inside, it should start at the position of the camera + // the min statement makes sure of that + float ray_pos_i = ray_length.x + step_size_i * 0.5; + + // these are the values we use to gather all the scattered light + vec3 total_ray = vec3(0.0); // for rayleigh + vec3 total_mie = vec3(0.0); // for mie + + // initialize the optical depth. This is used to calculate how much air was in the ray + vec3 opt_i = vec3(0.0); + + // also init the scale height, avoids some vec2's later on + vec2 scale_height = vec2(height_ray, height_mie); + + // Calculate the Rayleigh and Mie phases. + // This is the color that will be scattered for this ray + // mu, mumu and gg are used quite a lot in the calculation, so to speed it up, precalculate them + float mu = dot(dir, light_dir); + float mumu = mu * mu; + float gg = g * g; + float phase_ray = 3.0 / (50.2654824574 /* (16 * pi) */) * (1.0 + mumu); + float phase_mie = allow_mie ? 3.0 / (25.1327412287 /* (8 * pi) */) * ((1.0 - gg) * (mumu + 1.0)) / (pow(1.0 + gg - 2.0 * mu * g, 1.5) * (2.0 + gg)) : 0.0; + + // now we need to sample the 'primary' ray. this ray gathers the light that gets scattered onto it + for (int i = 0; i < steps_i; ++i) { + + // calculate where we are along this ray + vec3 pos_i = start + dir * ray_pos_i; + + // and how high we are above the surface + float height_i = length(pos_i) - planet_radius; + + // now calculate the density of the particles (both for rayleigh and mie) + vec3 density = vec3(exp(-height_i / scale_height), 0.0); + + // and the absorption density. this is for ozone, which scales together with the rayleigh, + // but absorbs the most at a specific height, so use the sech function for a nice curve falloff for this height + // clamp it to avoid it going out of bounds. This prevents weird black spheres on the night side + float denom = (height_absorption - height_i) / absorption_falloff; + density.z = (1.0 / (denom * denom + 1.0)) * density.x; + + // multiply it by the step size here + // we are going to use the density later on as well + density *= step_size_i; + + // Add these densities to the optical depth, so that we know how many particles are on this ray. + opt_i += density; + + // Calculate the step size of the light ray. + // again with a ray sphere intersect + // a, b, c and d are already defined + a = dot(light_dir, light_dir); + b = 2.0 * dot(light_dir, pos_i); + c = dot(pos_i, pos_i) - (atmo_radius * atmo_radius); + d = (b * b) - 4.0 * a * c; + + // no early stopping, this one should always be inside the atmosphere + // calculate the ray length + float step_size_l = (-b + sqrt(d)) / (2.0 * a * float(steps_l)); + + // and the position along this ray + // this time we are sure the ray is in the atmosphere, so set it to 0 + float ray_pos_l = step_size_l * 0.5; + + // and the optical depth of this ray + vec3 opt_l = vec3(0.0); + + // now sample the light ray + // this is similar to what we did before + for (int l = 0; l < steps_l; ++l) { + + // calculate where we are along this ray + vec3 pos_l = pos_i + light_dir * ray_pos_l; + + // the heigth of the position + float height_l = length(pos_l) - planet_radius; + + // calculate the particle density, and add it + // this is a bit verbose + // first, set the density for ray and mie + vec3 density_l = vec3(exp(-height_l / scale_height), 0.0); + + // then, the absorption + float denom = (height_absorption - height_l) / absorption_falloff; + density_l.z = (1.0 / (denom * denom + 1.0)) * density_l.x; + + // multiply the density by the step size + density_l *= step_size_l; + + // and add it to the total optical depth + opt_l += density_l; + + // and increment where we are along the light ray. + ray_pos_l += step_size_l; + + } + + // Now we need to calculate the attenuation + // this is essentially how much light reaches the current sample point due to scattering + vec3 attn = exp(-beta_ray * (opt_i.x + opt_l.x) - beta_mie * (opt_i.y + opt_l.y) - beta_absorption * (opt_i.z + opt_l.z)); + + // accumulate the scattered light (how much will be scattered towards the camera) + total_ray += density.x * attn; + total_mie += density.y * attn; + + // and increment the position on this ray + ray_pos_i += step_size_i; + + } + + // calculate how much light can pass through the atmosphere + vec3 opacity = exp(-(beta_mie * opt_i.y + beta_ray * opt_i.x + beta_absorption * opt_i.z)); + + // calculate and return the final color + return ( + phase_ray * beta_ray * total_ray // rayleigh color + + phase_mie * beta_mie * total_mie // mie + + opt_i.x * beta_ambient // and ambient + ) * light_intensity + scene_color * opacity; // now make sure the background is rendered correctly +} + +vec2 ray_sphere_intersect( + vec3 start, // starting position of the ray + vec3 dir, // the direction of the ray + float radius // and the sphere radius +) { + // ray-sphere intersection that assumes + // the sphere is centered at the origin. + // No intersection when result.x > result.y + float a = dot(dir, dir); + float b = 2.0 * dot(dir, start); + float c = dot(start, start) - (radius * radius); + float d = (b*b) - 4.0*a*c; + if (d < 0.0) return vec2(1e5,-1e5); + return vec2( + (-b - sqrt(d))/(2.0*a), + (-b + sqrt(d))/(2.0*a) + ); +} + +in vec2 v_coord; +out vec4 f_color; + +uniform vec3 u_xaxis; +uniform vec3 u_yaxis; +uniform vec3 u_zaxis; +uniform vec3 u_lightDir; +uniform int u_quality; +uniform float u_mie; + +void main() { + vec3 camera_position = vec3(0.0f, PLANET_RADIUS+1.0f, 0.0f); + vec3 camera_vector = normalize(u_xaxis * v_coord.x + + u_yaxis * -v_coord.y - + u_zaxis); + // hide darkness at horizon + camera_vector.y = max(0.01, camera_vector.y)*(1.0-u_mie*0.08) + 0.08*u_mie; + camera_vector = normalize(camera_vector); + + // the color of this pixel + vec3 col = vec3(0.0);//scene.xyz; + + // get the atmosphere color + col += calculate_scattering( + camera_position, // the position of the camera + camera_vector, // the camera vector (ray direction of this pixel) + 1e12f, // max dist, essentially the scene depth + vec3(0.0f), // scene color, the color of the current pixel being rendered + u_lightDir, // light direction + vec3(40.0), // light intensity, 40 looks nice + PLANET_POS, // position of the planet + PLANET_RADIUS, // radius of the planet in meters + ATMOS_RADIUS, // radius of the atmosphere in meters + RAY_BETA, // Rayleigh scattering coefficient + MIE_BETA, // Mie scattering coefficient + ABSORPTION_BETA, // Absorbtion coefficient + AMBIENT_BETA, // ambient scattering, turned off for now. This causes the air to glow a bit when no light reaches it + G, // Mie preferred scattering direction + HEIGHT_RAY, // Rayleigh scale height + HEIGHT_MIE*u_mie*u_mie, // Mie scale height + HEIGHT_ABSORPTION, // the height at which the most absorption happens + ABSORPTION_FALLOFF, // how fast the absorption falls off from the absorption height + PRIMARY_STEPS*u_quality, // steps in the ray direction + LIGHT_STEPS*u_quality // steps in the light direction + ); + + // apply exposure, removing this makes the brighter colors look ugly + // you can play around with removing this + col = 1.0 - exp(-col); + + // Output to screen + f_color = vec4(col, 1.0); +} diff --git a/res/shaders/screen.glslv b/res/shaders/skybox_gen.glslv similarity index 80% rename from res/shaders/screen.glslv rename to res/shaders/skybox_gen.glslv index 391b937e..91124116 100644 --- a/res/shaders/screen.glslv +++ b/res/shaders/skybox_gen.glslv @@ -1,10 +1,10 @@ -#version 330 core - -layout (location = 0) in vec2 v_position; - -out vec2 v_coord; - -void main(){ - v_coord = v_position*0.5+0.5; - gl_Position = vec4(v_position, 0.0, 1.0); -} +#version 330 core + +layout (location = 0) in vec2 v_position; + +out vec2 v_coord; + +void main(){ + v_coord = v_position; + gl_Position = vec4(v_position, 0.0, 1.0); +} diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 75431a03..b1458a7a 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -110,6 +110,8 @@ void AssetsLoader::addDefaults(AssetsLoader& loader) { loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/main"), "main"); loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/lines"), "lines"); loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/ui"), "ui"); + loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/background"), "background"); + loader.add(ASSET_SHADER, resdir/path(SHADERS_FOLDER"/skybox_gen"), "skybox_gen"); loader.add(ASSET_ATLAS, resdir/path(TEXTURES_FOLDER"/blocks"), "blocks"); loader.add(ASSET_TEXTURE, resdir/path(TEXTURES_FOLDER"/menubg.png"), "menubg"); diff --git a/src/files/WorldFiles.cpp b/src/files/WorldFiles.cpp index 85664a6c..fe131b7e 100644 --- a/src/files/WorldFiles.cpp +++ b/src/files/WorldFiles.cpp @@ -27,6 +27,7 @@ #define PLAYER_FLAG_NOCLIP 0x2 #define WORLD_SECTION_MAIN 1 +#define WORLD_SECTION_DAYNIGHT 2 using glm::ivec2; using glm::vec3; @@ -235,11 +236,15 @@ void WorldFiles::writeWorldInfo(const WorldInfo& info) { BinaryWriter out; out.putCStr(WORLD_FORMAT_MAGIC); out.put(WORLD_FORMAT_VERSION); + out.put(WORLD_SECTION_MAIN); - out.putInt64(info.seed); out.put(info.name); + out.put(WORLD_SECTION_DAYNIGHT); + out.putFloat32(info.daytime); + out.putFloat32(info.daytimeSpeed); + files::write_bytes(getWorldFile(), (const char*)out.data(), out.size()); } @@ -260,6 +265,10 @@ bool WorldFiles::readWorldInfo(WorldInfo& info) { info.seed = inp.getInt64(); info.name = inp.getString(); break; + case WORLD_SECTION_DAYNIGHT: + info.daytime = inp.getFloat32(); + info.daytimeSpeed = inp.getFloat32(); + break; } } return false; diff --git a/src/files/WorldFiles.h b/src/files/WorldFiles.h index 5b8832a7..c16ebb4a 100644 --- a/src/files/WorldFiles.h +++ b/src/files/WorldFiles.h @@ -36,6 +36,8 @@ struct WorldInfo { std::string name; std::filesystem::path directory; uint64_t seed; + float daytime; + float daytimeSpeed; }; class WorldFiles { diff --git a/src/frontend/graphics/Skybox.cpp b/src/frontend/graphics/Skybox.cpp new file mode 100644 index 00000000..0ff04855 --- /dev/null +++ b/src/frontend/graphics/Skybox.cpp @@ -0,0 +1,111 @@ +#include "Skybox.h" +#include +#include +#include + +#include "../../graphics/Shader.h" +#include "../../graphics/Mesh.h" +#include "../../window/Window.h" + +using glm::vec3; + +Skybox::Skybox(uint size, Shader* shader) : size(size), shader(shader) { + glGenTextures(1, &cubemap); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + for (uint face = 0; face < 6; face++) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGB, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + } + glGenFramebuffers(1, &fbo); + + float vertices[] { + -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f + }; + vattr attrs[] {2, 0}; + mesh = new Mesh(vertices, 6, attrs); +} + +Skybox::~Skybox() { + glDeleteTextures(1, &cubemap); + glDeleteFramebuffers(1, &fbo); + delete mesh; +} + +void Skybox::draw(Shader* shader) { + shader->uniform1i("u_cubemap", 1); + bind(); + mesh->draw(); + unbind(); +} + +void Skybox::refresh(float t, float mie, uint quality) { + ready = true; + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); + shader->use(); + Window::viewport(0,0, size,size); + const vec3 xaxs[] = { + {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, 1.0f}, + {-1.0f, 0.0f, 0.0f}, + + {-1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + }; + const vec3 yaxs[] = { + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 0.0f, -1.0f}, + + {0.0f, 0.0f, 1.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + }; + + const vec3 zaxs[] = { + {1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + + {0.0f, 1.0f, 0.0f}, + {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, 1.0f}, + }; + t *= M_PI*2.0f; + + shader->uniform1i("u_quality", quality); + shader->uniform1f("u_mie", mie); + shader->uniform3f("u_lightDir", glm::normalize(vec3(sin(t), -cos(t), 0.7f))); + for (uint face = 0; face < 6; face++) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, cubemap, 0); + glClear(GL_COLOR_BUFFER_BIT); + glClearColor(1.0f, 0.0f, 0.0f, 1.0f); + shader->uniform3f("u_xaxis", xaxs[face]); + shader->uniform3f("u_yaxis", yaxs[face]); + shader->uniform3f("u_zaxis", zaxs[face]); + mesh->draw(GL_TRIANGLES); + } + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + glActiveTexture(GL_TEXTURE0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + Window::viewport(0, 0, Window::width, Window::height); +} + +void Skybox::bind() const { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); + glActiveTexture(GL_TEXTURE0); +} + +void Skybox::unbind() const { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + glActiveTexture(GL_TEXTURE0); +} \ No newline at end of file diff --git a/src/frontend/graphics/Skybox.h b/src/frontend/graphics/Skybox.h new file mode 100644 index 00000000..cdf18966 --- /dev/null +++ b/src/frontend/graphics/Skybox.h @@ -0,0 +1,30 @@ +#ifndef FRONTEND_GRAPHICS_SKYBOX_H_ +#define FRONTEND_GRAPHICS_SKYBOX_H_ + +#include "../../typedefs.h" + +class Mesh; +class Shader; + +class Skybox { + uint fbo; + uint cubemap; + uint size; + Mesh* mesh; + Shader* shader; + bool ready = false; +public: + Skybox(uint size, Shader* shader); + ~Skybox(); + + void draw(Shader* shader); + + void refresh(float t, float mie, uint quality); + void bind() const; + void unbind() const; + bool isReady() const { + return ready; + } +}; + +#endif // FRONTEND_GRAPHICS_SKYBOX_H_ \ No newline at end of file diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index c39f2267..e701ee5d 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -11,6 +11,7 @@ #include "../typedefs.h" #include "../content/Content.h" #include "../util/stringutil.h" +#include "../util/timeutil.h" #include "../assets/Assets.h" #include "../graphics/Shader.h" #include "../graphics/Batch2D.h" @@ -128,13 +129,22 @@ HudRenderer::HudRenderer(Engine* engine, sub->add(box); panel->add(sub); } + panel->add(shared_ptr