载入中...
搜索中...
未找到
BeerLightCache.cpp
浏览该文件的文档.
2
3#include "common/Diagnostic.h"
4
5#include <algorithm>
6#include <cmath>
7
8#include <glm/common.hpp>
9#include <glm/geometric.hpp>
10
11namespace eve::graphics::fog {
12
14 valid_ = false;
15 ++key_.version;
16}
17
18bool BeerLightCache::matches(std::uint64_t densityRevision, const glm::vec3& lightDir,
19 float intensity) const noexcept {
20 if (!valid_) return false;
21 if (key_.densityRevision != densityRevision) return false;
22 if (std::fabs(key_.intensity - intensity) > 1e-5f) return false;
23 const glm::vec3 d = key_.direction - lightDir;
24 return glm::dot(d, d) < 1e-6f;
25}
26
28 const glm::vec3& lightDir, const glm::vec3& lightColor,
29 float intensity, int samplesPerCell) {
30 if (field.width() < 2) {
32 "density field is empty", "rebuild", {},
33 "graphics.fog"));
34 }
35 if (!std::isfinite(intensity) || intensity < 0.f || samplesPerCell < 1 || samplesPerCell > 64) {
37 DiagnosticCode::InvalidArgument, "intensity/samples out of range", "rebuild", {},
38 "graphics.fog"));
39 }
40 const float len = glm::length(lightDir);
41 if (!(len > 1e-6f) || !std::isfinite(len)) {
43 DiagnosticCode::InvalidArgument, "light direction must be non-zero and finite",
44 "lightDir", {}, "graphics.fog"));
45 }
46 const glm::vec3 dir = lightDir / len;
47
48 width_ = field.width();
49 height_ = field.height();
50 depth_ = field.depth();
51 transmittance_.assign(static_cast<std::size_t>(width_) * height_ * depth_, 1.f);
52
53 const glm::vec3 cell = field.cellSize();
54 const float stepLen = 0.5f * std::min({cell.x, cell.y, cell.z});
55 const FogWorldBounds& bounds = field.bounds();
56
57 for (int z = 0; z < depth_; ++z) {
58 for (int y = 0; y < height_; ++y) {
59 for (int x = 0; x < width_; ++x) {
60 glm::vec3 p = bounds.minimum + glm::vec3((x + 0.5f) * cell.x, (y + 0.5f) * cell.y,
61 (z + 0.5f) * cell.z);
62 float optical = 0.f;
63 for (int s = 0; s < samplesPerCell; ++s) {
64 // March toward the light (opposite the "direction toward the surface").
65 p -= dir * stepLen;
66 if (!bounds.contains(p)) break;
67 optical += profile.extinctionAt(field.sampleDensity(p)) * stepLen;
68 }
69 const std::size_t idx =
70 (static_cast<std::size_t>(z) * height_ + y) * width_ + static_cast<std::size_t>(x);
71 transmittance_[idx] = std::exp(-optical);
72 }
73 }
74 }
75
76 key_.direction = dir;
77 key_.color = lightColor;
78 key_.intensity = intensity;
79 key_.densityRevision = field.revision();
80 ++key_.version;
81 valid_ = true;
82 return Result<void>::success();
83}
84
86 const glm::vec3& world) const noexcept {
87 if (!valid_ || transmittance_.empty()) return 1.f;
88 const FogWorldBounds& bounds = field.bounds();
89 const glm::vec3 cell = field.cellSize();
90 const glm::vec3 local = (world - bounds.minimum) / cell;
91 const int x = std::clamp(static_cast<int>(local.x), 0, width_ - 1);
92 const int y = std::clamp(static_cast<int>(local.y), 0, height_ - 1);
93 const int z = std::clamp(static_cast<int>(local.z), 0, depth_ - 1);
94 const std::size_t idx =
95 (static_cast<std::size_t>(z) * height_ + y) * width_ + static_cast<std::size_t>(x);
96 return transmittance_[idx];
97}
98
99} // namespace eve::graphics::fog
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
const std::string & s
glm::vec4 p[6]
Stable, structured diagnostics shared by engine modules.
std::string local
int idx
World3D * world
float d
Cell cell
V3 dir
Definition TreeMesh.cpp:150
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Result< void > rebuild(const FogDensityField &field, const FogProfile &profile, const glm::vec3 &lightDir, const glm::vec3 &lightColor, float intensity, int samplesPerCell=6)
Rebuild transmittance along the primary light for each density cell.
bool matches(std::uint64_t densityRevision, const glm::vec3 &lightDir, float intensity) const noexcept
True when the cache matches the supplied state.
void invalidate()
Mark cache stale (quality change, light cut, etc.).
float sampleTransmittance(const FogDensityField &field, const glm::vec3 &world) const noexcept
Sample cached transmittance at a world position (1 = fully lit).
World-space density bands, curl assist velocity, and lighting helpers.
Unit-density optical profile for participating media.
Definition FogProfile.h:16
float extinctionAt(float density) const noexcept
Extinction for a sampled density value.
Axis-aligned world bounds for a fog simulation domain.
Definition FogTypes.h:96
glm::vec4 lightColor
glm::vec4 lightDir
glm::vec4 bounds