diff --git a/res/content/base/block_materials/carpet.json b/res/content/base/block_materials/carpet.json index 4d4d11dca..00c3688ec 100644 --- a/res/content/base/block_materials/carpet.json +++ b/res/content/base/block_materials/carpet.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/carpet", "place-sound": "blocks/carpet_place", - "break-sound": "blocks/carpet_break" + "break-sound": "blocks/carpet_break", + "sound-absorption": 0.96 } diff --git a/res/content/base/block_materials/glass.json b/res/content/base/block_materials/glass.json index fd2e23238..8ad365675 100644 --- a/res/content/base/block_materials/glass.json +++ b/res/content/base/block_materials/glass.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/glass", "place-sound": "blocks/glass_place", - "break-sound": "blocks/glass_break" + "break-sound": "blocks/glass_break", + "sound-absorption": 0.3 } diff --git a/res/content/base/block_materials/grass.json b/res/content/base/block_materials/grass.json index 148c80c09..ff091aa95 100644 --- a/res/content/base/block_materials/grass.json +++ b/res/content/base/block_materials/grass.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/grass", "place-sound": "steps/grass", - "break-sound": "steps/grass" + "break-sound": "steps/grass", + "sound-absorption": 0.85 } diff --git a/res/content/base/block_materials/grass_block.json b/res/content/base/block_materials/grass_block.json index d45672a28..98ed4618a 100644 --- a/res/content/base/block_materials/grass_block.json +++ b/res/content/base/block_materials/grass_block.json @@ -2,5 +2,6 @@ "steps-sound": "steps/grass", "place-sound": "blocks/ground_place", "break-sound": "blocks/ground_break", - "hit-sound": "blocks/ground_hit" + "hit-sound": "blocks/ground_hit", + "sound-absorption": 0.8 } diff --git a/res/content/base/block_materials/ground.json b/res/content/base/block_materials/ground.json index 951cb5dfe..8e78a8563 100644 --- a/res/content/base/block_materials/ground.json +++ b/res/content/base/block_materials/ground.json @@ -2,5 +2,6 @@ "steps-sound": "steps/ground", "place-sound": "blocks/ground_place", "break-sound": "blocks/ground_break", - "hit-sound": "blocks/ground_hit" + "hit-sound": "blocks/ground_hit", + "sound-absorption": 0.7 } diff --git a/res/content/base/block_materials/metal.json b/res/content/base/block_materials/metal.json index 6f45903e1..0ab1b2b28 100644 --- a/res/content/base/block_materials/metal.json +++ b/res/content/base/block_materials/metal.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/metal", "place-sound": "blocks/metal_place", - "break-sound": "blocks/metal_break" + "break-sound": "blocks/metal_break", + "sound-absorption": 0.1 } diff --git a/res/content/base/block_materials/sand.json b/res/content/base/block_materials/sand.json index 67316ba36..c047aab9c 100644 --- a/res/content/base/block_materials/sand.json +++ b/res/content/base/block_materials/sand.json @@ -1,5 +1,6 @@ { "steps-sound": "steps/sand", "place-sound": "blocks/ground_place", - "break-sound": "blocks/ground_break" + "break-sound": "blocks/ground_break", + "sound-absorption": 0.8 } diff --git a/res/content/base/block_materials/stone.json b/res/content/base/block_materials/stone.json index 43f579e7a..75052af52 100644 --- a/res/content/base/block_materials/stone.json +++ b/res/content/base/block_materials/stone.json @@ -2,5 +2,6 @@ "steps-sound": "steps/stone", "place-sound": "blocks/stone_place", "break-sound": "blocks/stone_break", - "hit-sound": "blocks/stone_hit" + "hit-sound": "blocks/stone_hit", + "sound-absorption": 0.3 } diff --git a/res/content/base/block_materials/wood.json b/res/content/base/block_materials/wood.json index 0c8e9a469..edf1801c2 100644 --- a/res/content/base/block_materials/wood.json +++ b/res/content/base/block_materials/wood.json @@ -2,5 +2,6 @@ "steps-sound": "steps/wood", "place-sound": "blocks/wood_place", "break-sound": "blocks/wood_break", - "hit-sound": "blocks/wood_hit" + "hit-sound": "blocks/wood_hit", + "sound-absorption": 0.5 } diff --git a/src/audio/AL/ALAudio.cpp b/src/audio/AL/ALAudio.cpp index 66b5b8c8c..eba10df17 100644 --- a/src/audio/AL/ALAudio.cpp +++ b/src/audio/AL/ALAudio.cpp @@ -788,10 +788,18 @@ void ALAudio::setAcoustics(Acoustics acoustics) { return; } int reverbEffect = effects[REVERB_EFFECT]; + AL_CHECK(alEffectf( + reverbEffect, + AL_REVERB_GAIN, + glm::max(0.1f, glm::min(acoustics.reverbGain, 0.8f) * + (1.0f - glm::min(1.0f, acoustics.reverbAbsorption))) + )); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_REFLECTIONS_DELAY, acoustics.reverbReflectionsDelay)); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_LATE_REVERB_DELAY, acoustics.reverbLateReflectionsDelay)); AL_CHECK(alEffectf(reverbEffect, AL_REVERB_DECAY_TIME, std::max(0.1f, acoustics.reverbDecayTime))); - AL_CHECK(alEffectf(reverbEffect, AL_REVERB_ROOM_ROLLOFF_FACTOR, 0.14f)); - // AL_CHECK(alEffectf(reverbEffect, AL_REVERB_GAIN, 0.0f)); - // AL_CHECK(alEffectf(reverbEffect, AL_REVERB_GAINHF, 0.0f)); - AL_CHECK(alEffectf(reverbEffect, AL_REVERB_REFLECTIONS_GAIN, 0.99f)); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_ROOM_ROLLOFF_FACTOR, acoustics.reverbRoomRolloff)); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_REFLECTIONS_GAIN, glm::pow(acoustics.reverbGain, 2.0f))); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_LATE_REVERB_GAIN, glm::pow(acoustics.reverbGain, 2.0f))); + AL_CHECK(alEffectf(reverbEffect, AL_REVERB_DECAY_HFRATIO, 1.0f - acoustics.reverbAbsorption)); alAuxiliaryEffectSloti(effectSlots[0], AL_EFFECTSLOT_EFFECT, reverbEffect); } diff --git a/src/audio/effects.hpp b/src/audio/effects.hpp index e292621d3..f8f10e4af 100644 --- a/src/audio/effects.hpp +++ b/src/audio/effects.hpp @@ -28,6 +28,11 @@ namespace audio { }; struct Acoustics { + float reverbGain; + float reverbReflectionsDelay; + float reverbLateReflectionsDelay; float reverbDecayTime; + float reverbRoomRolloff; + float reverbAbsorption; }; } diff --git a/src/graphics/render/Decorator.cpp b/src/graphics/render/Decorator.cpp index f8a6c8372..29405ef37 100644 --- a/src/graphics/render/Decorator.cpp +++ b/src/graphics/render/Decorator.cpp @@ -97,34 +97,63 @@ void Decorator::updateAcoustics(const Camera& camera) { const auto& start = camera.position; float rayLength = 40.0f; + auto& blocks = level.content.getIndices()->blocks; + int rays = 100; int hit = 0; float averageDistance = 0.0f; + float averageAbsorption = 0.0f; + float speedOfSound = 300.0f; + float minDistance = rayLength; for (int i = 0; i < rays; i++) { - glm::vec3 dir { - random.randFloat() - 0.5f, - random.randFloat() - 0.5f, - random.randFloat() - 0.5f, - }; + float u1 = random.randFloat(); + float u2 = random.randFloat(); + float z = 2.0f * u1 - 1.0f; + float phi = 2.0f * glm::pi() * u2; + float r = std::sqrt(1.0f - z * z); + + glm::vec3 dir = { r * std::cos(phi), r * std::sin(phi), z }; + dir = glm::normalize(dir); - auto end = chunks.rayCastToObstacle(start, dir, rayLength); + glm::vec3 end; + glm::ivec3 norm; + glm::ivec3 iend; + auto vox = chunks.rayCast(start, dir, rayLength, end, norm, iend); + if (vox == nullptr) { + continue; + } auto distance = glm::distance(start, end); if (distance >= rayLength * 0.98f) { continue; } + if (distance < minDistance) { + minDistance = distance; + } + auto def = blocks.get(vox->id); + if (def == nullptr) { + continue; + } + auto material = level.content.findBlockMaterial(def->material); + if (material == nullptr) { + return; + } hit++; - averageDistance += distance * 0.2f; + averageDistance += distance; + averageAbsorption += material->soundAbsorption; } - float decayTime = - glm::sqrt(averageDistance / hit) * - glm::max(0.0f, glm::pow(hit / static_cast(rays), 3.0f) - 0.6f) * - 1.6f; - decayTime *= 2.5f; - decayTime *= decayTime; - logger.info() << "rays hit " << hit << "/" << rays << " decay-time: " << decayTime; + averageDistance /= hit; + averageAbsorption /= hit; + float decayTime = 20.0f * (averageDistance / rayLength); + float escapeRatio = static_cast(rays - hit) / static_cast(rays); + acoustics.reverbGain = glm::pow(hit / static_cast(rays), 3.0f); + acoustics.reverbReflectionsDelay = minDistance / speedOfSound; + acoustics.reverbLateReflectionsDelay = averageDistance / speedOfSound; acoustics.reverbDecayTime = decayTime; + acoustics.reverbRoomRolloff = escapeRatio * 1.5f; + acoustics.reverbAbsorption = averageAbsorption; + audio::set_acoustics(std::move(acoustics)); } diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index 65830efc5..11933a697 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -24,7 +24,8 @@ dv::value BlockMaterial::serialize() const { {"steps-sound", stepsSound}, {"place-sound", placeSound}, {"break-sound", breakSound}, - {"hit-sound", hitSound} + {"hit-sound", hitSound}, + {"sound-absorption", soundAbsorption} }); } @@ -34,6 +35,7 @@ void BlockMaterial::deserialize(const dv::value& src) { src.at("place-sound").get(placeSound); src.at("break-sound").get(breakSound); src.at("hit-sound").get(hitSound); + src.at("sound-absorption").get(soundAbsorption); } CoordSystem::CoordSystem(glm::ivec3 axisX, glm::ivec3 axisY, glm::ivec3 axisZ) diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 99b9dee70..4465b6398 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -147,6 +147,7 @@ struct BlockMaterial : Serializable { std::string placeSound; std::string breakSound; std::string hitSound; + float soundAbsorption = 0.5f; dv::value toTable() const; // for compatibility dv::value serialize() const override;