Skip to content

Commit 616d25e

Browse files
committed
[volume] improved lerpring
1 parent b582a4d commit 616d25e

1 file changed

Lines changed: 29 additions & 18 deletions

File tree

source/runtime/Rendering/Renderer.cpp

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -744,44 +744,55 @@ namespace spartan
744744

745745
unordered_map<Renderer_Option, float>& Renderer::GetOptions()
746746
{
747-
// local scratchpad to avoid permanently overwriting m_options (master user settings)
747+
// local scratchpad
748748
static unordered_map<Renderer_Option, float> resolved_options;
749-
750-
// start fresh every frame with the master settings
751749
resolved_options = m_options;
752750

753-
// get camera
754751
if (!World::GetCamera() || !World::GetCamera()->GetEntity())
755752
return resolved_options;
756753

757754
Vector3 cam_pos = World::GetCamera()->GetEntity()->GetPosition();
758-
const float blend_radius = 5.0f; // dirty hardcoded blend distance
755+
756+
// how many meters deep you must be to reach 100% volume influence
757+
// 0.1f means "at 10cm depth, I am fully active"
758+
const float blend_depth = 0.5f;
759759

760-
// iterate all entities
761760
const auto& entities = World::GetEntities();
762761
for (const auto& entity : entities)
763762
{
764-
// skip if no volume
765763
Volume* volume = entity->GetComponent<Volume>();
766-
if (!volume)
767-
continue;
764+
if (!volume) continue;
768765

769-
// check distance
770-
const math::BoundingBox& box = volume->GetBoundingBox();
771-
float dist = box.GetClosestPoint(cam_pos).Distance(cam_pos);
766+
// 1. transform local box to world space
767+
// (crucial: otherwise you compare world camera vs local box at 0,0,0)
768+
const math::BoundingBox& local_box = volume->GetBoundingBox();
769+
const Matrix& transform = entity->GetMatrix();
770+
math::BoundingBox world_box = local_box * transform; // or local_box.Transform(transform)
772771

773-
// skip if too far
774-
if (dist > blend_radius)
772+
// 2. fast early exit
773+
if (!world_box.Contains(cam_pos))
775774
continue;
776775

777-
// calculate alpha (1.0 inside, 0.0 at radius)
778-
float alpha = 1.0f - clamp(dist / blend_radius, 0.0f, 1.0f);
776+
// 3. calculate depth (distance to nearest face inside)
777+
// since we are inside, all these deltas are positive
778+
Vector3 d_min = cam_pos - world_box.GetMin();
779+
Vector3 d_max = world_box.GetMax() - cam_pos;
780+
781+
// the "depth" is the smallest distance to any of the 6 faces
782+
float depth = min(d_min.x, d_max.x);
783+
depth = min(depth, min(d_min.y, d_max.y));
784+
depth = min(depth, min(d_min.z, d_max.z));
785+
786+
// 4. calculate alpha
787+
// depth 0.0 (surface) -> alpha 0.0
788+
// depth 0.5 (inside) -> alpha 1.0
789+
float alpha = clamp(depth / blend_depth, 0.0f, 1.0f);
779790

780-
// blend overrides onto the scratchpad
791+
// 5. blend
781792
for (const auto& [option, vol_value] : volume->GetOptions())
782793
{
783794
float& current_val = resolved_options[option];
784-
current_val = lerp(current_val, vol_value, alpha);
795+
current_val = lerp(current_val, vol_value, alpha);
785796
}
786797
}
787798

0 commit comments

Comments
 (0)