summaryrefslogtreecommitdiff
path: root/src/World
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2023-07-12 03:39:01 +0200
committerMel <einebeere@gmail.com>2023-07-12 03:39:01 +0200
commitf09e5791837bb003f7c5db8c0e3162636bc9a9c2 (patch)
tree36b9a007f119388bb7943489e8d203de04269483 /src/World
parent0ce26f2a49fd6d64a690b84b1932126edfbfbee6 (diff)
downloadmeowcraft-f09e5791837bb003f7c5db8c0e3162636bc9a9c2.tar.zst
meowcraft-f09e5791837bb003f7c5db8c0e3162636bc9a9c2.zip
3D Clouds
Diffstat (limited to 'src/World')
-rw-r--r--src/World/Clouds.cpp70
-rw-r--r--src/World/Clouds.hpp10
2 files changed, 61 insertions, 19 deletions
diff --git a/src/World/Clouds.cpp b/src/World/Clouds.cpp
index 6c5dba3..36f2441 100644
--- a/src/World/Clouds.cpp
+++ b/src/World/Clouds.cpp
@@ -1,15 +1,16 @@
#include "Clouds.hpp"
#include "../Math/MVP.hpp"
#include "../Math/Perlin.hpp"
+#include "../Math/AABB.hpp"
+#include "../GFX/Util/Primitives.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(
+Clouds::Clouds(Real ascept, Real fov, Real near, Real far, Vector<3, F32> sky_color, Vector<3, F32> sun_direction)
+ : m_program(
{GFX::Shading::Shader::Type::Vertex, vertex},
{GFX::Shading::Shader::Type::Fragment, fragment}
),
@@ -21,24 +22,41 @@ Clouds::Clouds(Real ascept, Real fov, Real near, Real far, Vector<3, F32> sky_co
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");
+ auto sun_direction_uniform = m_program.uniform("sun_direction");
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);
+ sun_direction_uniform.set(sun_direction);
m_program.unbind();
}
void Clouds::update(U64 time) {
- m_position.x() += time / 5000.0;
+ m_x_offset += time / 5000.0;
}
void Clouds::render(const GFX::Camera& camera) const {
+ auto position = camera.position();
+
+ I32 center_x = std::round((position.x() - m_x_offset) / TileSize);
+ I32 center_y = std::round(position.z() / TileSize);
+
+ for (Int x = -1; x <= 1; x++) {
+ for (Int y = -1; y <= 1; y++) {
+ render_single_instance(camera, center_x + x, center_y + y);
+ }
+ }
+}
+
+void Clouds::render_single_instance(const GFX::Camera& camera, Int x, Int y) const {
+ Vector<3> position{TileSize * x + m_x_offset, Height, TileSize * y};
+
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_model_uniform.set(Math::MVP::model<F32>(position, Vector<3>{Scale}, {}));
m_mesh.bind();
glDrawElements(GL_TRIANGLES, m_mesh.size(), GL_UNSIGNED_INT, nullptr);
@@ -51,8 +69,8 @@ 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++) {
+ for (Int x = 1; x < CloudMatrixSize; x++) {
+ for (Int y = 1; y < CloudMatrixSize; y++) {
if (noise.at({x, y * 2}) > 0.55) {
clouds(x, y) = true;
}
@@ -62,20 +80,31 @@ Clouds::CloudMatrix Clouds::create_cloud_matrix() {
}
GFX::Mesh Clouds::create_mesh(const CloudMatrix& cloud_matrix) {
- GFX::Util::MeshBuilder builder{};
+ GFX::Util::MeshBuilder<Vector<3, F32>> 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 };
+ auto is_occupied = [&](Int xn, Int yn) {
+ if (xn < 0 || xn >= CloudMatrixSize || yn < 0 || yn >= CloudMatrixSize) return false;
+ return cloud_matrix(xn, yn);
+ };
+ std::array<bool, 4> neighbors = {
+ is_occupied(x - 1, y), is_occupied(x + 1, y),
+ is_occupied(x, y - 1), is_occupied(x, y + 1),
+ };
- for (auto& p : positions) p += {x, 0, y};
+ using FaceSet = GFX::Util::Primitives::FaceSet;
+ U8 faces = FaceSet::Top | FaceSet::Bottom;
+ if (!neighbors[0]) faces |= FaceSet::Left;
+ if (!neighbors[1]) faces |= FaceSet::Right;
+ if (!neighbors[2]) faces |= FaceSet::Front;
+ if (!neighbors[3]) faces |= FaceSet::Back;
- builder.positions(positions);
- builder.indices(indices);
+ auto aabb = Math::AABB{{x, 0, y}, {x + 1, 1, y + 1}};
+ auto box = GFX::Util::Primitives::box(aabb, (FaceSet::Value)faces);
+ builder.primitive(box);
}
}
@@ -90,7 +119,9 @@ uniform mat4 view_matrix;
uniform mat4 projection_matrix;
layout (location = 0) in vec3 position;
+layout (location = 1) in vec3 normal;
+out vec3 surface_normal;
out float depth;
void main() {
@@ -99,7 +130,8 @@ void main() {
vec4 clip_position = projection_matrix * view_position;
gl_Position = clip_position;
- depth = clamp((length(view_position) - 75) / 125, 0.0, 1.0);
+ surface_normal = (model_matrix * vec4(normal, 0.0)).xyz;
+ depth = clamp((length(view_position) - 200) / 400, 0.0, 1.0);
}
)v";
@@ -107,14 +139,18 @@ const Char* Clouds::fragment = R"f(
#version 330 core
uniform vec3 sky_color;
+uniform vec3 sun_direction;
+in vec3 surface_normal;
in float depth;
out vec4 color;
void main() {
- vec3 white = vec3(1.0, 1.0, 1.0);
+ float brightness = dot(normalize(surface_normal), normalize(-sun_direction));
+ vec3 diffuse = vec3(1 - clamp(brightness, -0.3, 0.2));
+ vec3 base = vec3(1.0, 1.0, 1.0) * diffuse;
- color = vec4(mix(sky_color, white, 1 - depth), 0.5);
+ color = vec4(mix(sky_color, base, 1 - depth), 0.3);
}
)f";
diff --git a/src/World/Clouds.hpp b/src/World/Clouds.hpp
index 6a91901..b2d5a10 100644
--- a/src/World/Clouds.hpp
+++ b/src/World/Clouds.hpp
@@ -9,21 +9,27 @@ namespace MC::World {
class Clouds {
public:
- Clouds(Real ascept, Real fov, Real near, Real far, Vector<3, F32> sky_color);
+ Clouds(Real ascept, Real fov, Real near, Real far, Vector<3, F32> sky_color, Vector<3, F32> sun_direction);
void update(U64 time);
void render(const GFX::Camera& camera) const;
private:
constexpr static U32 CloudMatrixSize = 128;
+ constexpr static Int Height = 200;
+ constexpr static Real Scale = 15;
+ constexpr static Real TileSize = CloudMatrixSize * Scale;
+
using CloudMatrix = Matrix<CloudMatrixSize, CloudMatrixSize, Bool>;
+ void render_single_instance(const GFX::Camera& camera, Int x, Int y) const;
+
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;
+ Real m_x_offset = 0.0;
GFX::Shading::Program m_program;
GFX::BindableMesh m_mesh;