diff options
Diffstat (limited to 'src/World/Clouds.cpp')
| -rw-r--r-- | src/World/Clouds.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/World/Clouds.cpp b/src/World/Clouds.cpp new file mode 100644 index 0000000..6c5dba3 --- /dev/null +++ b/src/World/Clouds.cpp @@ -0,0 +1,121 @@ +#include "Clouds.hpp" +#include "../Math/MVP.hpp" +#include "../Math/Perlin.hpp" +#include "../GFX/Util/MeshBuilder.hpp" +#include <GL/glew.h> +#include <array> + +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<F32>({}, {}, {})); + m_view_uniform.set(Math::MVP::view<F32>({}, {})); + m_projection_uniform.set(Math::MVP::perspective_projection<F32>(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<F32>(camera.position(), camera.angles())); + m_model_uniform.set(Math::MVP::model<F32>(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<Vector<3, F32>, 4> positions = {{{0, 0, 0}, {1, 0, 0}, {0, 0, 1}, {1, 0, 1}}}; + std::array<U32, 6> 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"; + +} |
