summaryrefslogtreecommitdiff
path: root/src/World
diff options
context:
space:
mode:
Diffstat (limited to 'src/World')
-rw-r--r--src/World/Clouds.cpp121
-rw-r--r--src/World/Clouds.hpp36
2 files changed, 157 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";
+
+}
diff --git a/src/World/Clouds.hpp b/src/World/Clouds.hpp
new file mode 100644
index 0000000..6a91901
--- /dev/null
+++ b/src/World/Clouds.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "../GFX/Binder.hpp"
+#include "../GFX/Shading/Program.hpp"
+#include "../GFX/Shading/Uniform.hpp"
+#include "../GFX/Camera.hpp"
+
+namespace MC::World {
+
+class Clouds {
+public:
+ Clouds(Real ascept, Real fov, Real near, Real far, Vector<3, F32> sky_color);
+
+ void update(U64 time);
+ void render(const GFX::Camera& camera) const;
+private:
+ constexpr static U32 CloudMatrixSize = 128;
+ using CloudMatrix = Matrix<CloudMatrixSize, CloudMatrixSize, Bool>;
+
+ static CloudMatrix create_cloud_matrix();
+ static GFX::Mesh create_mesh(const CloudMatrix& cloud_matrix);
+
+ static const Char* vertex;
+ static const Char* fragment;
+
+ Vector<3> m_position;
+
+ GFX::Shading::Program m_program;
+ GFX::BindableMesh m_mesh;
+
+ GFX::Shading::Uniform m_model_uniform;
+ GFX::Shading::Uniform m_view_uniform;
+ GFX::Shading::Uniform m_projection_uniform;
+};
+
+}