mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-11 05:51:51 +00:00
test clouds
This commit is contained in:
parent
cf69d3e8f4
commit
e24a5db97a
7 changed files with 409 additions and 69 deletions
|
|
@ -130,21 +130,22 @@ void Shadows::refresh(
|
||||||
const std::function<void(Camera&)>& renderShadowPass
|
const std::function<void(Camera&)>& renderShadowPass
|
||||||
) {
|
) {
|
||||||
static int frameid = 0;
|
static int frameid = 0;
|
||||||
if (shadows) {
|
if (!shadows) {
|
||||||
if (frameid % 2 == 0) {
|
return;
|
||||||
generateShadowsMap(
|
}
|
||||||
camera, pctx, *shadowMap, shadowCamera, 1.0f, renderShadowPass
|
if (frameid % 2 == 0) {
|
||||||
);
|
generateShadowsMap(
|
||||||
} else {
|
camera, pctx, *shadowMap, shadowCamera, 1.0f, renderShadowPass
|
||||||
generateShadowsMap(
|
);
|
||||||
camera,
|
} else {
|
||||||
pctx,
|
generateShadowsMap(
|
||||||
*wideShadowMap,
|
camera,
|
||||||
wideShadowCamera,
|
pctx,
|
||||||
3.0f,
|
*wideShadowMap,
|
||||||
renderShadowPass
|
wideShadowCamera,
|
||||||
);
|
3.0f,
|
||||||
}
|
renderShadowPass
|
||||||
|
);
|
||||||
}
|
}
|
||||||
frameid++;
|
frameid++;
|
||||||
}
|
}
|
||||||
|
|
@ -176,10 +177,7 @@ void Shadows::generateShadowsMap(
|
||||||
shadowCamera.setAspectRatio(1.0f);
|
shadowCamera.setAspectRatio(1.0f);
|
||||||
|
|
||||||
float t = worldInfo.daytime - 0.25f;
|
float t = worldInfo.daytime - 0.25f;
|
||||||
if (t < 0.0f) {
|
t = glm::mod(t < 0.0f ? t + 1.0f : t, 0.5f);
|
||||||
t += 1.0f;
|
|
||||||
}
|
|
||||||
t = fmod(t, 0.5f);
|
|
||||||
|
|
||||||
float sunCycleStep = 1.0f / 500.0f;
|
float sunCycleStep = 1.0f / 500.0f;
|
||||||
float sunAngle = glm::radians(
|
float sunAngle = glm::radians(
|
||||||
|
|
@ -206,15 +204,13 @@ void Shadows::generateShadowsMap(
|
||||||
|
|
||||||
shadowCamera.setProjection(glm::ortho(min.x, max.x, min.y, max.y, 0.1f, 1000.0f));
|
shadowCamera.setProjection(glm::ortho(min.x, max.x, min.y, max.y, 0.1f, 1000.0f));
|
||||||
|
|
||||||
{
|
auto sctx = pctx.sub();
|
||||||
auto sctx = pctx.sub();
|
sctx.setDepthTest(true);
|
||||||
sctx.setDepthTest(true);
|
sctx.setCullFace(true);
|
||||||
sctx.setCullFace(true);
|
sctx.setViewport({resolution, resolution});
|
||||||
sctx.setViewport({resolution, resolution});
|
shadowMap.bind();
|
||||||
shadowMap.bind();
|
if (renderShadowPass) {
|
||||||
if (renderShadowPass) {
|
renderShadowPass(shadowCamera);
|
||||||
renderShadowPass(shadowCamera);
|
|
||||||
}
|
|
||||||
shadowMap.unbind();
|
|
||||||
}
|
}
|
||||||
|
shadowMap.unbind();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
251
src/graphics/render/CloudsRenderer.cpp
Executable file
251
src/graphics/render/CloudsRenderer.cpp
Executable file
|
|
@ -0,0 +1,251 @@
|
||||||
|
#include "CloudsRenderer.hpp"
|
||||||
|
|
||||||
|
#include "assets/Assets.hpp"
|
||||||
|
#include "coders/imageio.hpp"
|
||||||
|
#include "debug/Logger.hpp"
|
||||||
|
#include "graphics/core/ImageData.hpp"
|
||||||
|
#include "graphics/core/Mesh.hpp"
|
||||||
|
#include "graphics/core/Shader.hpp"
|
||||||
|
#include "graphics/core/Texture.hpp"
|
||||||
|
#include "io/io.hpp"
|
||||||
|
#include "lighting/Lightmap.hpp"
|
||||||
|
#include "maths/FastNoiseLite.h"
|
||||||
|
#include "util/timeutil.hpp"
|
||||||
|
#include "window/Camera.hpp"
|
||||||
|
|
||||||
|
#include <glm/ext.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
static debug::Logger logger("clouds-render");
|
||||||
|
|
||||||
|
class CloudsMap {
|
||||||
|
public:
|
||||||
|
glm::ivec3 size;
|
||||||
|
const bool* voxels;
|
||||||
|
|
||||||
|
CloudsMap() = default;
|
||||||
|
|
||||||
|
CloudsMap(const glm::ivec3& size, const bool* voxels)
|
||||||
|
: size(size), voxels(voxels) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOpen(int x, int y, int z) const {
|
||||||
|
if (x >= 0 && x < size.x && y >= 0 && y < size.y && z >= 0 && z < size.z) {
|
||||||
|
return !voxels[vox_index(x, y, z, size.x, size.z)];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class VolumeRenderer final {
|
||||||
|
public:
|
||||||
|
VolumeRenderer(size_t capacity)
|
||||||
|
: vertices(std::make_unique<ChunkVertex[]>(capacity)),
|
||||||
|
indexBuffer(std::make_unique<uint32_t[]>(capacity * 6)),
|
||||||
|
capacity(capacity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~VolumeRenderer() = default;
|
||||||
|
|
||||||
|
void build(CloudsMap volumeMap) {
|
||||||
|
this->map = std::move(volumeMap);
|
||||||
|
overflow = false;
|
||||||
|
offset = 0;
|
||||||
|
indexOffset = 0;
|
||||||
|
indexCount = 0;
|
||||||
|
|
||||||
|
int end = map.size.x * map.size.y * map.size.z;
|
||||||
|
for (int i = 0; i < end; i++) {
|
||||||
|
int x = i % map.size.x;
|
||||||
|
int y = i / (map.size.z * map.size.x);
|
||||||
|
int z = (i / map.size.x) % map.size.z;
|
||||||
|
const auto& vox = map.voxels[i];
|
||||||
|
if (!vox) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cube({x, y, z});
|
||||||
|
if (overflow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info() << "layer vertices: " << offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshData<ChunkVertex> createMesh() const {
|
||||||
|
return MeshData(
|
||||||
|
util::Buffer(vertices.get(), offset),
|
||||||
|
std::vector<util::Buffer<uint32_t>> {
|
||||||
|
util::Buffer(indexBuffer.get(), indexCount),
|
||||||
|
},
|
||||||
|
util::Buffer(
|
||||||
|
ChunkVertex::ATTRIBUTES,
|
||||||
|
sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<ChunkVertex[]> vertices;
|
||||||
|
std::unique_ptr<uint32_t[]> indexBuffer;
|
||||||
|
size_t capacity;
|
||||||
|
uint32_t indexOffset = 0;
|
||||||
|
uint32_t indexCount = 0;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
bool overflow = false;
|
||||||
|
CloudsMap map {};
|
||||||
|
|
||||||
|
void vertex(
|
||||||
|
const glm::vec3& coord,
|
||||||
|
const glm::vec3& normal
|
||||||
|
) {
|
||||||
|
auto& vert = vertices[offset++];
|
||||||
|
vert.position = coord;
|
||||||
|
vert.uv = {};
|
||||||
|
vert.normal = {
|
||||||
|
static_cast<uint8_t>(normal.r * 127 + 128),
|
||||||
|
static_cast<uint8_t>(normal.g * 127 + 128),
|
||||||
|
static_cast<uint8_t>(normal.b * 127 + 128),
|
||||||
|
255
|
||||||
|
};
|
||||||
|
vert.color = {
|
||||||
|
0, 0, 0, static_cast<uint8_t>((coord.y / 8.0f * 0.25f + 0.75f) * 255)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void face(
|
||||||
|
const glm::vec3& coord,
|
||||||
|
const glm::vec3& X,
|
||||||
|
const glm::vec3& Y,
|
||||||
|
const glm::vec3& Z
|
||||||
|
) {
|
||||||
|
if (!isOpen(coord + Z)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (offset + 4 >= capacity) {
|
||||||
|
overflow = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float s = 0.5f;
|
||||||
|
vertex(coord + (-X - Y + Z) * s, Z);
|
||||||
|
vertex(coord + ( X - Y + Z) * s, Z);
|
||||||
|
vertex(coord + ( X + Y + Z) * s, Z);
|
||||||
|
vertex(coord + (-X + Y + Z) * s, Z);
|
||||||
|
|
||||||
|
const uint32_t indices[] {0, 1, 2, 0, 2, 3};
|
||||||
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
indexBuffer[indexCount++] = indexOffset + indices[i];
|
||||||
|
}
|
||||||
|
indexOffset += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isOpen(const glm::ivec3& pos) const {
|
||||||
|
return pos.y < 0 || pos.y >= map.size.y ||
|
||||||
|
map.isOpen(pos.x, pos.y, pos.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cube(const glm::ivec3& coord) {
|
||||||
|
const glm::ivec3 X(1, 0, 0);
|
||||||
|
const glm::ivec3 Y(0, 1, 0);
|
||||||
|
const glm::ivec3 Z(0, 0, 1);
|
||||||
|
|
||||||
|
face(coord, X, Y, Z);
|
||||||
|
face(coord, -X, Y, -Z);
|
||||||
|
face(coord, X, -Z, Y);
|
||||||
|
face(coord, X, Z, -Y);
|
||||||
|
face(coord, -Z, Y, X);
|
||||||
|
face(coord, Z, Y, -X);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline constexpr int WIDTH = 256 / 2;
|
||||||
|
static inline constexpr int DEPTH = 256 / 2;
|
||||||
|
|
||||||
|
|
||||||
|
CloudsRenderer::CloudsRenderer(const Assets& assets) : assets(assets) {
|
||||||
|
timeutil::ScopeLogTimer log(111);
|
||||||
|
|
||||||
|
VolumeRenderer volumeRenderer(1024 * 1024);
|
||||||
|
|
||||||
|
for (int layer = 0; layer < 2; layer++) {
|
||||||
|
fnl_state state = fnlCreateState();
|
||||||
|
const int w = WIDTH;
|
||||||
|
const int h = 8;
|
||||||
|
const int d = DEPTH;
|
||||||
|
|
||||||
|
state.seed = 52365 + layer * 3521;
|
||||||
|
|
||||||
|
bool voxels[w * h * d];
|
||||||
|
for (int y = 0; y < h; y++) {
|
||||||
|
for (int z = 0; z < d; z++) {
|
||||||
|
for (int x = 0; x < w; x++) {
|
||||||
|
float s = 2.0f;
|
||||||
|
auto n = fnlGetNoise2D(&state, x * s, z * s);
|
||||||
|
n += fnlGetNoise2D(&state, x * s + fnlGetNoise2D(&state, x * s * 4 + 2, z * s * 4) * 0.25f, z * 3.0f) * 0.5f;
|
||||||
|
n += fnlGetNoise2D(&state, x * s * 2, z * s * 2) * 0.25f;
|
||||||
|
n += fnlGetNoise2D(&state, x * s * 4, z * s * 4) * 0.125f * 2;
|
||||||
|
n += fnlGetNoise2D(&state, x * s * 8, z * s * 8) * 0.125f * 0.5f * 2;
|
||||||
|
n += fnlGetNoise2D(&state, x * s * 16, z * s * 16) * 0.125f * 0.25f * 3;
|
||||||
|
n = glm::max(0.0f, n);
|
||||||
|
// n = n * n * 2.0f;
|
||||||
|
n -= 0.2f + layer * 0.5f;
|
||||||
|
// n -= 0.5f;
|
||||||
|
|
||||||
|
bool solid = y <= n * h && y >= (0.5f - n * 0.5f) * h;
|
||||||
|
voxels[vox_index(x, y, z, w, d)] = solid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloudsMap map({w, h, d}, voxels);
|
||||||
|
|
||||||
|
timeutil::ScopeLogTimer log2(222);
|
||||||
|
volumeRenderer.build(map);
|
||||||
|
testMeshes[layer] = std::make_unique<Mesh<ChunkVertex>>(volumeRenderer.createMesh());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloudsRenderer::~CloudsRenderer() = default;
|
||||||
|
|
||||||
|
#include "util/timeutil.hpp"
|
||||||
|
|
||||||
|
void CloudsRenderer::draw(float timer, float fogFactor, const Camera& camera) {
|
||||||
|
auto& shader = assets.require<Shader>("main");
|
||||||
|
assets.require<Texture>("misc/blank").bind();
|
||||||
|
|
||||||
|
float scale = 15;
|
||||||
|
float totalWidth = WIDTH * scale;
|
||||||
|
float totalDepth = DEPTH * scale;
|
||||||
|
|
||||||
|
int cellX = glm::round(camera.position.x / totalWidth);
|
||||||
|
int cellZ = glm::round(camera.position.z / totalDepth);
|
||||||
|
|
||||||
|
float speed = 10.0f;
|
||||||
|
|
||||||
|
timeutil::ScopeLogTimer log(555);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
float speedX = glm::sin(i * 0.3f) * speed / (i + 1);
|
||||||
|
float speedZ = -glm::cos(i * 0.3f) * 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::rotate(matrix, timer * 0.003f * (i % 2 * 2 - 1) + i, glm::vec3(0, 1, 0));
|
||||||
|
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);
|
||||||
|
testMeshes[i]->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/graphics/render/CloudsRenderer.hpp
Executable file
19
src/graphics/render/CloudsRenderer.hpp
Executable file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "commons.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Assets;
|
||||||
|
class Camera;
|
||||||
|
|
||||||
|
class CloudsRenderer final {
|
||||||
|
public:
|
||||||
|
CloudsRenderer(const Assets& assets);
|
||||||
|
~CloudsRenderer();
|
||||||
|
|
||||||
|
void draw(float timer, float fogFactor, const Camera& camera);
|
||||||
|
private:
|
||||||
|
const Assets& assets;
|
||||||
|
std::array<std::unique_ptr<Mesh<ChunkVertex>>, 2> testMeshes;
|
||||||
|
};
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
#include "Skybox.hpp"
|
#include "Skybox.hpp"
|
||||||
#include "Emitter.hpp"
|
#include "Emitter.hpp"
|
||||||
#include "TextNote.hpp"
|
#include "TextNote.hpp"
|
||||||
|
#include "CloudsRenderer.hpp"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -116,6 +117,7 @@ WorldRenderer::WorldRenderer(
|
||||||
);
|
);
|
||||||
shadowMapping = std::make_unique<Shadows>(level);
|
shadowMapping = std::make_unique<Shadows>(level);
|
||||||
debugLines = std::make_unique<DebugLinesRenderer>(level);
|
debugLines = std::make_unique<DebugLinesRenderer>(level);
|
||||||
|
cloudsRenderer = std::make_unique<CloudsRenderer>(assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldRenderer::~WorldRenderer() = default;
|
WorldRenderer::~WorldRenderer() = default;
|
||||||
|
|
@ -210,6 +212,7 @@ void WorldRenderer::renderOpaque(
|
||||||
setupWorldShader(shader, camera, settings, fogFactor);
|
setupWorldShader(shader, camera, settings, fogFactor);
|
||||||
|
|
||||||
chunksRenderer->drawChunks(camera, shader);
|
chunksRenderer->drawChunks(camera, shader);
|
||||||
|
cloudsRenderer->draw(timer, fogFactor, camera);
|
||||||
blockWraps->draw(ctx, player);
|
blockWraps->draw(ctx, player);
|
||||||
|
|
||||||
if (hudVisible) {
|
if (hudVisible) {
|
||||||
|
|
@ -369,7 +372,7 @@ void WorldRenderer::renderFrame(
|
||||||
if (gbufferPipeline) {
|
if (gbufferPipeline) {
|
||||||
postProcessing.bindDepthBuffer();
|
postProcessing.bindDepthBuffer();
|
||||||
} else {
|
} else {
|
||||||
postProcessing.getFramebuffer()->bind();
|
ctx.setFramebuffer(postProcessing.getFramebuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background sky plane
|
// Background sky plane
|
||||||
|
|
@ -448,43 +451,45 @@ void WorldRenderer::renderBlockOverlay(const DrawContext& wctx) {
|
||||||
int y = std::floor(player.currentCamera->position.y);
|
int y = std::floor(player.currentCamera->position.y);
|
||||||
int z = std::floor(player.currentCamera->position.z);
|
int z = std::floor(player.currentCamera->position.z);
|
||||||
auto block = player.chunks->get(x, y, z);
|
auto block = player.chunks->get(x, y, z);
|
||||||
if (block && block->id) {
|
|
||||||
const auto& def = level.content.getIndices()->blocks.require(block->id);
|
|
||||||
if (def.overlayTexture.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto textureRegion = util::get_texture_region(
|
|
||||||
assets, def.overlayTexture, "blocks:notfound"
|
|
||||||
);
|
|
||||||
DrawContext ctx = wctx.sub();
|
|
||||||
ctx.setDepthTest(false);
|
|
||||||
ctx.setCullFace(false);
|
|
||||||
|
|
||||||
auto& shader = assets.require<Shader>("ui3d");
|
if (block == nullptr || block->id == BLOCK_AIR || block->id == BLOCK_VOID) {
|
||||||
shader.use();
|
return;
|
||||||
batch3d->begin();
|
|
||||||
shader.uniformMatrix("u_projview", glm::mat4(1.0f));
|
|
||||||
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
|
||||||
auto light = player.chunks->getLight(x, y, z);
|
|
||||||
float s = Lightmap::extract(light, 3) / 15.0f;
|
|
||||||
glm::vec4 tint(
|
|
||||||
glm::min(1.0f, Lightmap::extract(light, 0) / 15.0f + s),
|
|
||||||
glm::min(1.0f, Lightmap::extract(light, 1) / 15.0f + s),
|
|
||||||
glm::min(1.0f, Lightmap::extract(light, 2) / 15.0f + s),
|
|
||||||
1.0f
|
|
||||||
);
|
|
||||||
batch3d->texture(textureRegion.texture);
|
|
||||||
batch3d->sprite(
|
|
||||||
glm::vec3(),
|
|
||||||
glm::vec3(0, 1, 0),
|
|
||||||
glm::vec3(1, 0, 0),
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
textureRegion.region,
|
|
||||||
tint
|
|
||||||
);
|
|
||||||
batch3d->flush();
|
|
||||||
}
|
}
|
||||||
|
const auto& def = level.content.getIndices()->blocks.require(block->id);
|
||||||
|
if (def.overlayTexture.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto textureRegion = util::get_texture_region(
|
||||||
|
assets, def.overlayTexture, "blocks:notfound"
|
||||||
|
);
|
||||||
|
DrawContext ctx = wctx.sub();
|
||||||
|
ctx.setDepthTest(false);
|
||||||
|
ctx.setCullFace(false);
|
||||||
|
|
||||||
|
auto& shader = assets.require<Shader>("ui3d");
|
||||||
|
shader.use();
|
||||||
|
batch3d->begin();
|
||||||
|
shader.uniformMatrix("u_projview", glm::mat4(1.0f));
|
||||||
|
shader.uniformMatrix("u_apply", glm::mat4(1.0f));
|
||||||
|
auto light = player.chunks->getLight(x, y, z);
|
||||||
|
float s = Lightmap::extract(light, 3) / 15.0f;
|
||||||
|
glm::vec4 tint(
|
||||||
|
glm::min(1.0f, Lightmap::extract(light, 0) / 15.0f + s),
|
||||||
|
glm::min(1.0f, Lightmap::extract(light, 1) / 15.0f + s),
|
||||||
|
glm::min(1.0f, Lightmap::extract(light, 2) / 15.0f + s),
|
||||||
|
1.0f
|
||||||
|
);
|
||||||
|
batch3d->texture(textureRegion.texture);
|
||||||
|
batch3d->sprite(
|
||||||
|
glm::vec3(),
|
||||||
|
glm::vec3(0, 1, 0),
|
||||||
|
glm::vec3(1, 0, 0),
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
textureRegion.region,
|
||||||
|
tint
|
||||||
|
);
|
||||||
|
batch3d->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldRenderer::clear() {
|
void WorldRenderer::clear() {
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ class Shader;
|
||||||
class Shadows;
|
class Shadows;
|
||||||
class Skybox;
|
class Skybox;
|
||||||
class TextsRenderer;
|
class TextsRenderer;
|
||||||
|
class CloudsRenderer;
|
||||||
struct EngineSettings;
|
struct EngineSettings;
|
||||||
|
|
||||||
struct CompileTimeShaderSettings {
|
struct CompileTimeShaderSettings {
|
||||||
|
|
@ -57,6 +58,7 @@ class WorldRenderer {
|
||||||
std::unique_ptr<Shadows> shadowMapping;
|
std::unique_ptr<Shadows> shadowMapping;
|
||||||
std::unique_ptr<DebugLinesRenderer> debugLines;
|
std::unique_ptr<DebugLinesRenderer> debugLines;
|
||||||
std::unique_ptr<PrecipitationRenderer> precipitation;
|
std::unique_ptr<PrecipitationRenderer> precipitation;
|
||||||
|
std::unique_ptr<CloudsRenderer> cloudsRenderer;
|
||||||
Weather weather {};
|
Weather weather {};
|
||||||
|
|
||||||
float timer = 0.0f;
|
float timer = 0.0f;
|
||||||
|
|
|
||||||
55
src/voxels/VoxelsVolume.cpp
Normal file
55
src/voxels/VoxelsVolume.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
#include "VoxelsVolume.hpp"
|
||||||
|
|
||||||
|
#include "constants.hpp"
|
||||||
|
#include "content/Content.hpp"
|
||||||
|
#include "voxels/Block.hpp"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
void VoxelsVolume::compressInto(VoxelsVolume& dst, const Content& content) const {
|
||||||
|
assert(dst.w < w && dst.h < h && dst.d < d);
|
||||||
|
assert(w % dst.w == 0 && h % dst.h == 0 && d % dst.d == 0);
|
||||||
|
|
||||||
|
int stepW = w / dst.w;
|
||||||
|
int stepH = h / dst.h;
|
||||||
|
int stepD = d / dst.d;
|
||||||
|
int height = dst.h;
|
||||||
|
int depth = dst.d;
|
||||||
|
int width = dst.w;
|
||||||
|
|
||||||
|
auto dstVoxels = dst.getVoxels();
|
||||||
|
auto dstLights = dst.getLights();
|
||||||
|
|
||||||
|
const auto& blockDefs = content.getIndices()->blocks;
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int z = 0; z < depth; z++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
voxel selectedVoxel {BLOCK_AIR, {}};
|
||||||
|
light_t light = 0;
|
||||||
|
for (int ly = 0; ly < stepH; ly++) {
|
||||||
|
for (int lz = 0; lz < stepD; lz++) {
|
||||||
|
for (int lx = 0; lx < stepW; lx++) {
|
||||||
|
size_t srcIndex = vox_index(
|
||||||
|
x * stepW + lx, y * stepH + ly, z * stepD, w, d
|
||||||
|
);
|
||||||
|
auto vox = voxels[srcIndex];
|
||||||
|
if (vox.id == BLOCK_VOID) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto& def = blockDefs.require(vox.id);
|
||||||
|
if (def.rt.solid) {
|
||||||
|
selectedVoxel = std::move(vox);
|
||||||
|
} else if (light == 0) {
|
||||||
|
light = lights[srcIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t dstIndex = vox_index(x, y, z, dst.w, dst.d);
|
||||||
|
dstLights[dstIndex] = light;
|
||||||
|
dstVoxels[dstIndex] = std::move(selectedVoxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,15 +6,17 @@
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
class Content;
|
||||||
|
|
||||||
class VoxelsVolume {
|
class VoxelsVolume {
|
||||||
public:
|
public:
|
||||||
static inline constexpr size_t MAX_VOXELS = CHUNK_VOL * 2;
|
|
||||||
|
|
||||||
VoxelsVolume(int w, int h, int d)
|
VoxelsVolume(int w, int h, int d)
|
||||||
: VoxelsVolume(0, 0, 0, w, h, d) {}
|
: VoxelsVolume(0, 0, 0, w, h, d) {}
|
||||||
|
|
||||||
VoxelsVolume(int x, int y, int z, int w, int h, int d)
|
VoxelsVolume(int x, int y, int z, int w, int h, int d)
|
||||||
: x(x), y(y), z(z), w(w), h(h), d(d) {
|
: x(x), y(y), z(z), w(w), h(h), d(d),
|
||||||
|
voxels(std::make_unique<voxel[]>(w * h * d)),
|
||||||
|
lights(std::make_unique<light_t[]>(w * h * d)) {
|
||||||
std::memset(voxels.get(), 0xFF, sizeof(voxel) * w * h * d);
|
std::memset(voxels.get(), 0xFF, sizeof(voxel) * w * h * d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,10 +54,18 @@ public:
|
||||||
return voxels.get();
|
return voxels.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const voxel* getVoxels() const {
|
||||||
|
return voxels.get();
|
||||||
|
}
|
||||||
|
|
||||||
light_t* getLights() {
|
light_t* getLights() {
|
||||||
return lights.get();
|
return lights.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const light_t* getLights() const {
|
||||||
|
return lights.get();
|
||||||
|
}
|
||||||
|
|
||||||
inline blockid_t pickBlockId(int bx, int by, int bz) const {
|
inline blockid_t pickBlockId(int bx, int by, int bz) const {
|
||||||
if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h ||
|
if (bx < x || by < y || bz < z || bx >= x + w || by >= y + h ||
|
||||||
bz >= z + d) {
|
bz >= z + d) {
|
||||||
|
|
@ -80,6 +90,8 @@ public:
|
||||||
}
|
}
|
||||||
return lights[vox_index(bx - x, by - y, bz - z, w, d)];
|
return lights[vox_index(bx - x, by - y, bz - z, w, d)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void compressInto(VoxelsVolume& dst, const Content& content) const;
|
||||||
private:
|
private:
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
int w, h, d;
|
int w, h, d;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue