#include "Clouds.hpp" #include "../Math/MVP.hpp" #include "../Math/Perlin.hpp" #include "../GFX/Util/MeshBuilder.hpp" #include #include namespace MC::World { Clouds::Clouds(Real ascept, Real fov, Real near, Real far, Vector<3, F32> sky_color) : m_position(-1000, 120, -1000), m_program( {GFX::Shading::Shader::Type::Vertex, vertex}, {GFX::Shading::Shader::Type::Fragment, fragment} ), m_mesh(GFX::Binder::load(create_mesh(create_cloud_matrix()))), m_model_uniform(), m_view_uniform(), m_projection_uniform() { m_program.bind(); m_model_uniform = m_program.uniform("model_matrix"); m_view_uniform = m_program.uniform("view_matrix"); m_projection_uniform = m_program.uniform("projection_matrix"); auto sky_color_uniform = m_program.uniform("sky_color"); m_model_uniform.set(Math::MVP::model({}, {}, {})); m_view_uniform.set(Math::MVP::view({}, {})); m_projection_uniform.set(Math::MVP::perspective_projection(ascept, fov, near, far)); sky_color_uniform.set(sky_color); m_program.unbind(); } void Clouds::update(U64 time) { m_position.x() += time / 5000.0; } void Clouds::render(const GFX::Camera& camera) const { m_program.bind(); m_view_uniform.set(Math::MVP::view(camera.position(), camera.angles())); m_model_uniform.set(Math::MVP::model(m_position, Vector<3>{10.0}, {})); m_mesh.bind(); glDrawElements(GL_TRIANGLES, m_mesh.size(), GL_UNSIGNED_INT, nullptr); m_mesh.unbind(); m_program.unbind(); } Clouds::CloudMatrix Clouds::create_cloud_matrix() { Math::Perlin::Noise<2> noise{}; CloudMatrix clouds{false}; for (Int x = 0; x < CloudMatrixSize; x++) { for (Int y = 0; y < CloudMatrixSize; y++) { if (noise.at({x, y * 2}) > 0.55) { clouds(x, y) = true; } } } return clouds; } GFX::Mesh Clouds::create_mesh(const CloudMatrix& cloud_matrix) { GFX::Util::MeshBuilder builder{}; for (Int x = 0; x < CloudMatrixSize; x++) { for (Int y = 0; y < CloudMatrixSize; y++) { if (!cloud_matrix(x, y)) continue; U32 s = builder.vertex_count(); std::array, 4> positions = {{{0, 0, 0}, {1, 0, 0}, {0, 0, 1}, {1, 0, 1}}}; std::array indices = { s + 0, s + 1, s + 2, s + 1, s + 3, s + 2 }; for (auto& p : positions) p += {x, 0, y}; builder.positions(positions); builder.indices(indices); } } return builder.mesh(); } const Char* Clouds::vertex = R"v( #version 330 core uniform mat4 model_matrix; uniform mat4 view_matrix; uniform mat4 projection_matrix; layout (location = 0) in vec3 position; out float depth; void main() { vec4 world_position = model_matrix * vec4(position, 1.0); vec4 view_position = view_matrix * world_position; vec4 clip_position = projection_matrix * view_position; gl_Position = clip_position; depth = clamp((length(view_position) - 75) / 125, 0.0, 1.0); } )v"; const Char* Clouds::fragment = R"f( #version 330 core uniform vec3 sky_color; in float depth; out vec4 color; void main() { vec3 white = vec3(1.0, 1.0, 1.0); color = vec4(mix(sky_color, white, 1 - depth), 0.5); } )f"; }