mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-13 15:01:49 +00:00
split clouds to segments
This commit is contained in:
parent
c32029d5b3
commit
f0e5b54164
2 changed files with 119 additions and 61 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include "CloudsRenderer.hpp"
|
#include "CloudsRenderer.hpp"
|
||||||
|
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
|
|
@ -10,11 +11,13 @@
|
||||||
#include "io/io.hpp"
|
#include "io/io.hpp"
|
||||||
#include "lighting/Lightmap.hpp"
|
#include "lighting/Lightmap.hpp"
|
||||||
#include "maths/FastNoiseLite.h"
|
#include "maths/FastNoiseLite.h"
|
||||||
|
#include "maths/voxmaths.hpp"
|
||||||
#include "util/timeutil.hpp"
|
#include "util/timeutil.hpp"
|
||||||
#include "window/Camera.hpp"
|
#include "window/Camera.hpp"
|
||||||
#include "world/Weather.hpp"
|
#include "world/Weather.hpp"
|
||||||
|
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
|
#include <glm/gtx/norm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
static debug::Logger logger("clouds-render");
|
static debug::Logger logger("clouds-render");
|
||||||
|
|
@ -70,7 +73,6 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.info() << "layer vertices: " << offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshData<ChunkVertex> createMesh() const {
|
MeshData<ChunkVertex> createMesh() const {
|
||||||
|
|
@ -160,70 +162,137 @@ private:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline constexpr int WIDTH = 256;
|
static inline constexpr int MAP_SIZE = 512;
|
||||||
static inline constexpr int DEPTH = 256;
|
|
||||||
|
|
||||||
|
|
||||||
CloudsRenderer::CloudsRenderer() {
|
CloudsRenderer::CloudsRenderer() {
|
||||||
VolumeRenderer volumeRenderer(1024 * 1024);
|
VolumeRenderer volumeRenderer(1024 * 512);
|
||||||
|
|
||||||
|
int diameter = 4;
|
||||||
|
int segmentSize = MAP_SIZE / diameter;
|
||||||
|
|
||||||
|
for (int layerid = 0; layerid < 2; layerid++) {
|
||||||
|
auto& layer = layers[layerid];
|
||||||
|
layer.diameter = diameter;
|
||||||
|
layer.segmentSize = segmentSize;
|
||||||
|
|
||||||
for (int layer = 0; layer < 2; layer++) {
|
|
||||||
fnl_state state = fnlCreateState();
|
fnl_state state = fnlCreateState();
|
||||||
const int w = WIDTH;
|
const int w = MAP_SIZE;
|
||||||
const int h = 8;
|
const int h = 8;
|
||||||
const int d = DEPTH;
|
const int d = MAP_SIZE;
|
||||||
const int dd = d * 1.5;
|
const int dd = d * 1.5;
|
||||||
|
|
||||||
state.seed = 5265 + layer * 3521;
|
state.seed = 5265 + layerid * 3521;
|
||||||
|
|
||||||
float pi2 = glm::two_pi<float>();
|
float pi2 = glm::two_pi<float>();
|
||||||
|
|
||||||
float heightmap[w * dd];
|
auto heightmap = std::make_unique<float[]>(w * dd);
|
||||||
for (int lz = 0; lz < dd; lz++) {
|
for (int lz = 0; lz < dd; lz++) {
|
||||||
for (int lx = 0; lx < w; lx++) {
|
for (int lx = 0; lx < w; lx++) {
|
||||||
float x = glm::sin(lx / static_cast<float>(w) * pi2) * w / pi2;
|
float x = glm::sin(lx / static_cast<float>(w) * pi2) * w / pi2;
|
||||||
float y = -glm::cos(lx / static_cast<float>(w) * pi2) * w / pi2;
|
float y = -glm::cos(lx / static_cast<float>(w) * pi2) * w / pi2;
|
||||||
float z = lz;
|
float z = lz;
|
||||||
float s = 1.5f;
|
float s = 1.5f;
|
||||||
auto n = fnlGetNoise3D(&state, x * s, y * s, z * s);
|
auto n = fnlGetNoise3D(&state, x * s * 0.7, y * s, z * s * 0.7);
|
||||||
n += fnlGetNoise3D(&state, x * s + fnlGetNoise2D(&state, x * s * 4 + 2, z * s * 4) * 0.25f, y * s, z * 3.0f) * 0.5f;
|
n += fnlGetNoise3D(&state, x * s + fnlGetNoise2D(&state, x * s * 4 + 2, z * s * 4) * 2.0f, y * s, z * 3.0f) * 0.5f;
|
||||||
n += fnlGetNoise3D(&state, x * s * 2, y * s * 2, z * s * 2) * 0.25f;
|
n += fnlGetNoise3D(&state, x * s * 2, y * s * 2, z * s * 2) * 0.25f;
|
||||||
n += fnlGetNoise3D(&state, x * s * 4, y * s * 4, z * s * 4) * 0.125f * 2;
|
n += fnlGetNoise3D(&state, x * s * 4, y * s * 4, z * s * 4) * 0.125f * 2;
|
||||||
n += fnlGetNoise3D(&state, x * s * 8, y * s * 8, z * s * 8) * 0.125f * 0.5f * 2;
|
n += fnlGetNoise3D(&state, x * s * 8, y * s * 8, z * s * 8) * 0.125f * 0.5f * 2;
|
||||||
n += fnlGetNoise3D(&state, x * s * 16, y * s * 16, z * s * 16) * 0.125f * 0.25f * 3;
|
n += fnlGetNoise3D(&state, x * s * 16, y * s * 16, z * s * 16) * 0.125f * 0.25f * 3;
|
||||||
n = glm::max(0.0f, n);
|
n = glm::max(0.0f, n);
|
||||||
// n = n * n * 2.0f;
|
n += -0.1f - layerid * 0.3f;
|
||||||
n -= 0.2f + layer * 0.5f;
|
|
||||||
// n -= 0.5f;
|
|
||||||
|
|
||||||
heightmap[lz * w + lx] = n;
|
heightmap[lz * w + lx] = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool voxels[w * h * d];
|
bool voxels[segmentSize * h * segmentSize];
|
||||||
for (int y = 0; y < h; y++) {
|
for (int sz = 0; sz < diameter; sz++) {
|
||||||
for (int z = 0; z < d; z++) {
|
for (int sx = 0; sx < diameter; sx++) {
|
||||||
for (int x = 0; x < w; x++) {
|
for (int y = 0; y < h; y++) {
|
||||||
float n = heightmap[z * w + x];
|
for (int z = 0; z < segmentSize; z++) {
|
||||||
if (z < d / 2) {
|
for (int x = 0; x < segmentSize; x++) {
|
||||||
float t = z / static_cast<float>(d / 2);
|
int gx = (sx * segmentSize) + x;
|
||||||
n = n * t + heightmap[(d + z) * w + x] * (1.0f - t);
|
int gz = (sz * segmentSize) + z;
|
||||||
|
|
||||||
|
float n = heightmap[gz * MAP_SIZE + gx];
|
||||||
|
if (gz < MAP_SIZE / 2) {
|
||||||
|
float t = gz / static_cast<float>(MAP_SIZE / 2);
|
||||||
|
n = n * t + heightmap[(MAP_SIZE + gz) * MAP_SIZE + gx] * (1.0f - t);
|
||||||
|
}
|
||||||
|
bool solid = y <= n * h && y >= (0.5f - n * 0.5f) * h;
|
||||||
|
voxels[vox_index(x, y, z, segmentSize, segmentSize)] = solid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool solid = y <= n * h && y >= (0.5f - n * 0.5f) * h;
|
|
||||||
voxels[vox_index(x, y, z, w, d)] = solid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CloudsMap map({segmentSize, h, segmentSize}, voxels);
|
||||||
|
|
||||||
|
volumeRenderer.build(map);
|
||||||
|
layer.meshes.push_back(std::make_unique<Mesh<ChunkVertex>>(
|
||||||
|
volumeRenderer.createMesh()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudsMap map({w, h, d}, voxels);
|
|
||||||
|
|
||||||
volumeRenderer.build(map);
|
|
||||||
meshes[layer] = std::make_unique<Mesh<ChunkVertex>>(volumeRenderer.createMesh());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CloudsRenderer::~CloudsRenderer() = default;
|
CloudsRenderer::~CloudsRenderer() = default;
|
||||||
|
|
||||||
|
void CloudsRenderer::draw(
|
||||||
|
Shader& shader,
|
||||||
|
Layer& layer,
|
||||||
|
const Camera& camera,
|
||||||
|
float timer,
|
||||||
|
int layerId
|
||||||
|
) {
|
||||||
|
float scale = 8;
|
||||||
|
int totalDiameter = layer.segmentSize * scale;
|
||||||
|
|
||||||
|
int gcellX = floordiv(camera.position.x, totalDiameter);
|
||||||
|
int gcellZ = floordiv(camera.position.z, totalDiameter);
|
||||||
|
|
||||||
|
float speed = 4.0f;
|
||||||
|
float speedX = glm::sin(layerId * 0.3f + 0.4f) * speed / (layerId + 1);
|
||||||
|
float speedZ = -glm::cos(layerId * 0.3f + 0.4f) * speed / (layerId + 1);
|
||||||
|
|
||||||
|
int radius = 4;
|
||||||
|
|
||||||
|
for (int x = -radius; x <= radius; x++) {
|
||||||
|
for (int z = -radius; z <= radius; z++) {
|
||||||
|
int lcellX = gcellX - floordiv(glm::floor(timer * speedX), totalDiameter);
|
||||||
|
int lcellZ = gcellZ - floordiv(glm::floor(timer * speedZ), totalDiameter);
|
||||||
|
glm::vec3 position(
|
||||||
|
-128 * scale + (x + gcellX) * layer.segmentSize * scale +
|
||||||
|
glm::mod(timer * speedX, static_cast<float>(totalDiameter)),
|
||||||
|
250 + layerId * 200,
|
||||||
|
-128 * scale + (z + gcellZ) * layer.segmentSize * scale +
|
||||||
|
glm::mod(timer * speedZ, static_cast<float>(totalDiameter))
|
||||||
|
);
|
||||||
|
if (glm::distance2(
|
||||||
|
glm::vec2(
|
||||||
|
position.x + totalDiameter * 0.5f,
|
||||||
|
position.z + totalDiameter * 0.5f
|
||||||
|
),
|
||||||
|
glm::vec2(camera.position.x, camera.position.z)
|
||||||
|
) > 4e6) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto matrix = glm::mat4(1.0f);
|
||||||
|
matrix = glm::translate(matrix, position);
|
||||||
|
matrix = glm::scale(matrix, glm::vec3(scale, scale, scale));
|
||||||
|
shader.uniformMatrix("u_model", matrix);
|
||||||
|
|
||||||
|
int lx = (x + radius + lcellX) % layer.diameter;
|
||||||
|
int lz = (z + radius + lcellZ) % layer.diameter;
|
||||||
|
if (lx < 0) lx += layer.diameter;
|
||||||
|
if (lz < 0) lz += layer.diameter;
|
||||||
|
|
||||||
|
layer.meshes[lz * layer.diameter + lx]->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CloudsRenderer::draw(
|
void CloudsRenderer::draw(
|
||||||
Shader& shader,
|
Shader& shader,
|
||||||
const Weather& weather,
|
const Weather& weather,
|
||||||
|
|
@ -233,37 +302,10 @@ void CloudsRenderer::draw(
|
||||||
int quality
|
int quality
|
||||||
) {
|
) {
|
||||||
shader.uniform4f("u_tint", glm::vec4(weather.cloudsTint(), 1.0f));
|
shader.uniform4f("u_tint", glm::vec4(weather.cloudsTint(), 1.0f));
|
||||||
|
shader.uniform1f("u_fogFactor", fogFactor * 0.03f);
|
||||||
|
shader.uniform1f("u_fogCurve", 0.7f - 0.3f);
|
||||||
|
|
||||||
float scale = 8;
|
for (int i = 0; i < std::min<int>(quality, layers.size()); i++) {
|
||||||
float totalWidth = WIDTH * scale;
|
draw(shader, layers[i], camera, timer, i);
|
||||||
float totalDepth = DEPTH * scale;
|
|
||||||
|
|
||||||
int cellX = glm::floor(camera.position.x / totalWidth + 0.5f);
|
|
||||||
int cellZ = glm::floor(camera.position.z / totalDepth + 0.5f);
|
|
||||||
|
|
||||||
float speed = 4.0f;
|
|
||||||
for (int i = 0; i < std::min<int>(quality, meshes.size()); i++) {
|
|
||||||
float speedX = glm::sin(i * 0.3f + 0.4f) * speed / (i + 1);
|
|
||||||
float speedZ = -glm::cos(i * 0.3f + 0.4f) * speed / (i + 1);
|
|
||||||
for (int x = -2; x <= 2; x++) {
|
|
||||||
for (int z = -2; z <= 2; z++) {
|
|
||||||
auto matrix = glm::mat4(1.0f);
|
|
||||||
matrix = glm::translate(
|
|
||||||
matrix,
|
|
||||||
glm::vec3(
|
|
||||||
-128 * scale + (x + cellX) * WIDTH * scale +
|
|
||||||
glm::mod(timer * speedX, totalWidth),
|
|
||||||
250 + i * 200,
|
|
||||||
-128 * scale + (z + cellZ) * DEPTH * scale +
|
|
||||||
glm::mod(timer * speedZ, totalDepth)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
matrix = glm::scale(matrix, glm::vec3(scale, scale, scale));
|
|
||||||
shader.uniform1f("u_fogFactor", fogFactor * 0.03f);
|
|
||||||
shader.uniform1f("u_fogCurve", 0.7f - 0.3f);
|
|
||||||
shader.uniformMatrix("u_model", matrix);
|
|
||||||
meshes[i]->draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
#include "commons.hpp"
|
#include "commons.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
class Shader;
|
class Shader;
|
||||||
|
|
@ -22,5 +24,19 @@ public:
|
||||||
int quality
|
int quality
|
||||||
);
|
);
|
||||||
private:
|
private:
|
||||||
std::array<std::unique_ptr<Mesh<ChunkVertex>>, 2> meshes;
|
struct Layer {
|
||||||
|
int diameter;
|
||||||
|
int segmentSize;
|
||||||
|
std::vector<std::unique_ptr<Mesh<ChunkVertex>>> meshes;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<Layer, 2> layers;
|
||||||
|
|
||||||
|
void draw(
|
||||||
|
Shader& shader,
|
||||||
|
Layer& layer,
|
||||||
|
const Camera& camera,
|
||||||
|
float timer,
|
||||||
|
int layerId
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue