add rain noise & add rain splashes (WIP)

This commit is contained in:
MihailRis 2025-02-11 02:26:00 +03:00
parent 8dfc948fe3
commit 7635fdf807
18 changed files with 118 additions and 16 deletions

View File

@ -5,7 +5,8 @@
"sounds": [
"blocks/door_open",
"blocks/door_close",
"events/pickup"
"events/pickup",
"ambient/rain"
],
"models": [
"drop-item"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -209,7 +209,9 @@ void LevelScreen::update(float delta) {
playerController->postUpdate(delta, !inputLocked, hud->isPause());
hud->update(hudVisible);
decorator->update(delta, *camera);
decorator->update(
hud->isPause() ? 0.0f : delta, *camera, worldRenderer->weather
);
}
void LevelScreen::draw(float delta) {

View File

@ -17,6 +17,8 @@
#include "util/stringutil.hpp"
#include "engine/Engine.hpp"
#include "io/io.hpp"
#include "audio/audio.hpp"
#include "maths/util.hpp"
namespace fs = std::filesystem;
@ -80,8 +82,79 @@ void Decorator::addParticles(const Block& def, const glm::ivec3& pos) {
}
}
void Decorator::updateRandom(
float delta,
const glm::ivec3& areaCenter,
const WeatherPreset& weather
) {
util::PseudoRandom random(rand());
const auto& chunks = *player.chunks;
const auto& indices = *level.content.getIndices();
ParticlesPreset rainSplash;
rainSplash.frames = {
"particles:rain_splash_0",
"particles:rain_splash_1",
"particles:rain_splash_2"
};
rainSplash.lifetime = 0.2f;
rainSplash.spawnInterval = 0.0f;
rainSplash.size = {0.2f, 0.2f, 0.2f};
auto pos = areaCenter + glm::ivec3(
random.rand32() % 12,
random.rand32() % 12,
random.rand32() % 12
);
if (auto vox = chunks.get(pos)) {
const auto& def = indices.blocks.require(vox->id);
auto dst2 = util::distance2(pos, areaCenter);
if (dst2 < 256 && def.obstacle &&
!weather.fall.noise.empty()) {
bool is_covered = false;
for (int y = pos.y + 1; y < CHUNK_H; y++) {
if (indices.blocks.require(chunks.get(pos.x, y, pos.z)->id).obstacle) {
is_covered = true;
break;
}
}
if (!is_covered) {
if (dst2 < 128) {
auto treg = util::get_texture_region(
assets, "particles:rain_splash_0", ""
);
renderer.particles->add(std::make_unique<Emitter>(
level,
glm::vec3{pos.x + random.randFloat(), pos.y + 1.1, pos.z + random.randFloat()},
rainSplash,
treg.texture,
treg.region,
2
));
}
if (random.rand() % 200 < 2 && pos.y < areaCenter.y + 1) {
auto sound = assets.get<audio::Sound>(weather.fall.noise);
audio::play(
sound,
pos,
false,
1.0f,
1.0f,
false,
audio::PRIORITY_LOW,
audio::get_channel_index("ambient")
);
}
}
}
}
}
void Decorator::update(
float delta, const glm::ivec3& areaStart, const glm::ivec3& areaCenter
float delta,
const glm::ivec3& areaStart,
const glm::ivec3& areaCenter
) {
int index = currentIndex;
currentIndex = (currentIndex + BIG_PRIME) % UPDATE_BLOCKS;
@ -93,7 +166,8 @@ void Decorator::update(
int lz = (index / UPDATE_AREA_DIAMETER) % UPDATE_AREA_DIAMETER;
int ly = (index / UPDATE_AREA_DIAMETER / UPDATE_AREA_DIAMETER);
auto pos = areaStart + glm::ivec3(lx, ly, lz);
glm::ivec3 offset {lx, ly, lz};
auto pos = areaStart + offset;
if (auto vox = chunks.get(pos)) {
const auto& def = indices.blocks.require(vox->id);
@ -103,11 +177,17 @@ void Decorator::update(
}
}
void Decorator::update(float delta, const Camera& camera) {
void Decorator::update(
float delta, const Camera& camera, const WeatherPreset& weather
) {
glm::ivec3 pos = camera.position;
for (int i = 0; i < ITERATIONS; i++) {
update(delta, pos - glm::ivec3(UPDATE_AREA_DIAMETER / 2), pos);
}
int randIters = std::min(50'000, static_cast<int>(delta * 24'000));
for (int i = 0; i < randIters; i++) {
updateRandom(delta, pos, weather);
}
const auto& chunks = *player.chunks;
const auto& indices = *level.content.getIndices();
auto iter = blockEmitters.begin();

View File

@ -18,6 +18,7 @@ class Block;
class Engine;
class LevelController;
class WorldRenderer;
struct WeatherPreset;
class Decorator {
Engine& engine;
@ -31,7 +32,14 @@ class Decorator {
NotePreset playerNamePreset {};
void update(
float delta, const glm::ivec3& areaStart, const glm::ivec3& areaCenter
float delta,
const glm::ivec3& areaStart,
const glm::ivec3& areaCenter
);
void updateRandom(
float delta,
const glm::ivec3& areaCenter,
const WeatherPreset& weather
);
void addParticles(const Block& def, const glm::ivec3& pos);
public:
@ -43,5 +51,5 @@ public:
Player& player
);
void update(float delta, const Camera& camera);
void update(float delta, const Camera& camera, const WeatherPreset& weather);
};

View File

@ -92,14 +92,11 @@ static UVRegion calc_uv(
return {u1, v1, u1 + m * scale, v1 + FACE_SIZE.y * scale};
}
void PrecipitationRenderer::render(const Camera& camera, float delta) {
void PrecipitationRenderer::render(
const Camera& camera, float delta, const WeatherPreset& weather
) {
timer += delta;
WeatherPreset weather {};
auto& fall = weather.fall;
fall.vspeed = 2.0f;
fall.texture = "misc/rain";
const int radius = 6;
const int depth = 12;
@ -116,7 +113,7 @@ void PrecipitationRenderer::render(const Camera& camera, float delta) {
}
batch->begin();
auto& texture = assets.require<Texture>(fall.texture);
auto& texture = assets.require<Texture>(weather.fall.texture);
texture.setMipMapping(false);
batch->setTexture(&texture, {});

View File

@ -8,6 +8,7 @@ class Chunks;
class Camera;
class MainBatch;
struct GraphicsSettings;
struct WeatherPreset;
class PrecipitationRenderer {
std::unique_ptr<MainBatch> batch;
@ -28,5 +29,5 @@ public:
~PrecipitationRenderer();
void render(const Camera& camera, float delta);
void render(const Camera& camera, float delta, const WeatherPreset& weather);
};

View File

@ -101,6 +101,12 @@ WorldRenderer::WorldRenderer(
settings.graphics.skyboxResolution.get(),
assets->require<Shader>("skybox_gen")
);
weather = {};
auto& fall = weather.fall;
fall.vspeed = 2.0f;
fall.texture = "misc/rain";
fall.noise = "ambient/rain";
}
WorldRenderer::~WorldRenderer() = default;
@ -196,7 +202,7 @@ void WorldRenderer::renderLevel(
setupWorldShader(entityShader, camera, settings, fogFactor);
entityShader.uniform1i("u_alphaClip", false);
precipitation->render(camera, pause ? 0.0f : delta);
precipitation->render(camera, pause ? 0.0f : delta, weather);
skybox->unbind();
}

View File

@ -10,6 +10,8 @@
#include "typedefs.hpp"
#include "presets/WeatherPreset.hpp"
class Level;
class Player;
class Camera;
@ -73,6 +75,7 @@ public:
std::unique_ptr<ParticlesRenderer> particles;
std::unique_ptr<BlockWrapsRenderer> blockWraps;
std::unique_ptr<PrecipitationRenderer> precipitation;
WeatherPreset weather;
static bool showChunkBorders;
static bool showEntitiesDebug;

View File

@ -10,6 +10,7 @@ dv::value WeatherPreset::serialize() const {
froot["vspeed"] = fall.vspeed;
froot["hspeed"] = fall.hspeed;
froot["scale"] = fall.scale;
froot["noise"] = fall.noise;
root["fall"] = froot;
return root;
@ -22,5 +23,6 @@ void WeatherPreset::deserialize(const dv::value& src) {
froot.at("vspeed").get(fall.vspeed);
froot.at("hspeed").get(fall.hspeed);
froot.at("scale").get(fall.scale);
froot.at("noise").get(fall.noise);
}
}

View File

@ -6,6 +6,8 @@ struct WeatherPreset : Serializable {
struct {
/// @brief Precipitation texture
std::string texture;
/// @brief Fall sound
std::string noise;
/// @brief Vertical speed
float vspeed = 1.0f;
/// @brief Max horizontal speed