载入中...
搜索中...
未找到
FogSystem.cpp
浏览该文件的文档.
2
3#include "common/Diagnostic.h"
4#include "common/Status.h"
7
8#include <algorithm>
9#include <cmath>
10
11#include <glm/geometric.hpp>
12
13namespace eve::graphics::fog {
14
16 quality_ = quality;
17 beerCache_.invalidate();
18 return Result<void>::success();
19}
20
21Result<void> FogSystem::configureDomain(int simWidth, int simHeight, int simDepth,
22 const FogWorldBounds& bounds, float fixedDt) {
23 auto resized = density_.resize(simWidth, simHeight, simDepth, bounds);
24 if (!resized.ok()) return resized;
25 auto configured = fluid_.configure(density_, fixedDt);
26 if (!configured.ok()) return configured;
27 beerCache_.invalidate();
28 return Result<void>::success();
29}
30
31Result<void> FogSystem::seedHeightFog(float baseDensity, float baseHeight, float falloff,
32 float curlScale, std::uint32_t seed) {
33 auto seeded = density_.seedHeightBand(baseDensity, baseHeight, falloff, curlScale, seed);
34 if (!seeded.ok()) return seeded;
35 auto pulled = fluid_.pullDensity(density_);
36 if (!pulled.ok()) return pulled;
37 beerCache_.invalidate();
38 return Result<void>::success();
39}
40
42 auto stepped = fluid_.step(dt, wind_, &interactor_, simTime_);
43 if (!stepped.ok()) return stepped;
44 auto pushed = fluid_.pushDensity(density_);
45 if (!pushed.ok()) return Result<FogCflReport>::failure(pushed.status());
46 simTime_ += dt;
47 ++frameIndex_;
48 beerCache_.invalidate();
49 return stepped;
50}
51
53 float intensity) {
54 const auto budget = budgetFor(quality_);
56 beerCache_.invalidate();
58 }
59 if (beerCache_.matches(density_.revision(),
60 glm::length(lightDir) > 1e-6f ? glm::normalize(lightDir) : glm::vec3(0, 1, 0),
61 intensity)) {
63 }
64 return beerCache_.rebuild(density_, profile_, lightDir, lightColor, intensity, 6);
65}
66
67Result<FogRayResult> FogSystem::marchRay(const glm::vec3& origin, const glm::vec3& direction,
68 const FogVolumeBound& bound, const glm::vec3& lightDir,
69 const glm::vec3& lightColor, float lightIntensity,
70 const glm::vec3& skyAmbient, const glm::vec3& groundAmbient,
71 float sceneDepth) const {
72 const auto budget = budgetFor(quality_);
73 const BeerLightCache* cache =
74 (budget.beerLightCache && beerCache_.valid()) ? &beerCache_ : nullptr;
75 return rayMarch_.integrate(density_, profile_, origin, direction, bound, lightDir, lightColor,
76 lightIntensity, skyAmbient, groundAmbient, budget.raySamples, sceneDepth,
77 cache, quality_ != FogQuality::PhysicalReference);
78}
79
81 const glm::vec3& lightDir, const glm::vec3& lightColor,
82 float intensity) {
83 const auto budget = budgetFor(quality_);
84 if (volume.getWidth() != budget.froxelWidth || volume.getHeight() != budget.froxelHeight ||
85 volume.getDepth() != budget.froxelDepth) {
87 volume.setDepthRange(0.1f, std::max(density_.bounds().size().z, 40.f));
88 } else {
89 volume.clear();
90 }
91
92 auto cacheReady = ensureBeerCache(lightDir, lightColor, intensity);
93 if (!cacheReady.ok()) return Result<int>::failure(cacheReady.status());
94
95 auto injected =
96 froxelBridge_.inject(volume, density_, profile_, invViewProj, budget.occupancySkip);
97 if (!injected.ok()) return injected;
98
99 const BeerLightCache* cache =
100 (budget.beerLightCache && beerCache_.valid()) ? &beerCache_ : nullptr;
101 auto integrated = froxelBridge_.integrate(volume, density_, profile_, invViewProj, lightDir,
102 lightColor, intensity, cache);
103 if (!integrated.ok()) return Result<int>::failure(integrated.status());
104
105 if (budget.temporalHistory && frameIndex_ > 1) {
106 // Lightweight self-history: blend with a cleared-then-reintegrated snapshot is
107 // intentionally skipped here; callers may keep an external history volume.
108 (void)budget.historyWeight;
109 }
110 return injected;
111}
112
114 if (volume.getWidth() <= 0 || density_.width() <= 0) {
116 "froxel/density volumes are empty",
117 "injectToFroxel", {}, "graphics.fog"));
118 }
119 const auto budget = budgetFor(quality_);
120 return froxelBridge_.inject(volume, density_, profile_, invViewProj, budget.occupancySkip);
121}
122
124 if (!volumetric) {
126 DiagnosticCode::InvalidArgument, "volumetric is null", "volumetric", {}, "graphics.fog"));
127 }
129 if (!volume) {
131 DiagnosticCode::Failed, "volumetric has no AtmosphereVolume; call configureFroxelGrid first",
132 "atmosphereVolume", {}, "graphics.fog"));
133 }
134 return injectToFroxel(*volume, volumetric->getInvViewProj());
135}
136
138 const glm::vec3& lightColor, float intensity) {
139 if (!volumetric) {
141 DiagnosticCode::InvalidArgument, "volumetric is null", "volumetric", {}, "graphics.fog"));
142 }
144 if (!volume) {
146 DiagnosticCode::Failed, "volumetric has no AtmosphereVolume; call configureFroxelGrid first",
147 "atmosphereVolume", {}, "graphics.fog"));
148 }
149
150 // Keep Volumetric atlas metadata in sync with the quality grid. Resizing the
151 // AtmosphereVolume alone leaves froxelAtlasCols_/Rows_ stale and corrupts upload.
152 const auto budget = budgetFor(quality_);
153 float nearDistance = volume->getNearDistance();
154 float farDistance = volume->getFarDistance();
155 if (!(farDistance > nearDistance)) {
156 nearDistance = 0.1f;
157 farDistance = std::max(density_.bounds().size().z, 40.f);
158 }
160 nearDistance, farDistance);
161 volume = volumetric->getAtmosphereVolume();
162 if (!volume) {
164 DiagnosticCode::Failed, "configureFroxelGrid left AtmosphereVolume empty",
165 "atmosphereVolume", {}, "graphics.fog"));
166 }
167
168 auto cacheReady = ensureBeerCache(lightDir, lightColor, intensity);
169 if (!cacheReady.ok()) return Result<int>::failure(cacheReady.status());
170
171 const glm::mat4& invViewProj = volumetric->getInvViewProj();
172 auto injected =
173 froxelBridge_.inject(*volume, density_, profile_, invViewProj, budget.occupancySkip);
174 if (!injected.ok()) return injected;
175
176 const BeerLightCache* cache =
177 (budget.beerLightCache && beerCache_.valid()) ? &beerCache_ : nullptr;
178 auto integrated = froxelBridge_.integrate(*volume, density_, profile_, invViewProj, lightDir,
179 lightColor, intensity, cache);
180 if (!integrated.ok()) return Result<int>::failure(integrated.status());
181 return injected;
182}
183
185 const glm::vec3& direction, float sceneDepth,
186 float mediumDensity) const {
187 const auto budget = budgetFor(quality_);
188 return volLight_.integrate(beam, profile_, origin, direction, sceneDepth, budget.volLightSegments,
189 mediumDensity);
190}
191
193 std::uint32_t seed) const {
194 return dust_.generate(density_.bounds(), count, simTime_, turbulenceMeters, seed);
195}
196
198 float neighborOpacity) const noexcept {
199 return art_.stylize(physical, viewZ, neighborOpacity);
200}
201
202} // namespace eve::graphics::fog
double volume
Stable, structured diagnostics shared by engine modules.
std::uint32_t seed
Definition PointSet.cpp:807
V3 origin
Definition RoadBake.cpp:138
RoadLaneDirection direction
std::uint32_t count
Structured operation status used by the common Result foundation.
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
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
Camera-frustum volume used by the volumetric fog passes and CPU references.
Volumetric light + fog.
Definition Volumetric.h:38
const glm::mat4 & getInvViewProj() const
Inverse view-projection last written by setCamera / setInvViewProj.
Definition Volumetric.h:215
AtmosphereVolume * getAtmosphereVolume() const
Access the froxel media grid for native density/light injection.
Definition Volumetric.h:213
void configureFroxelGrid(int width, int height, int depth, float nearDistance, float farDistance)
Configure the CPU reference/fallback froxel grid used by the atlas renderer. Quality presets choose s...
Result< FogRayResult > integrate(const AnalyticBeam &beam, const FogProfile &profile, const glm::vec3 &origin, const glm::vec3 &direction, float sceneDepth, int segments, float mediumDensity) const
Integrate the beam contribution along a view ray.
Cached light-path transmittance used by Fast / Enhanced quality tiers.
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.).
const FogWorldBounds & bounds() const noexcept
Result< void > seedHeightBand(float baseDensity, float baseHeight, float falloff, float curlScale, std::uint32_t seed)
Seed a height-banded density layer with optional curl noise.
Result< void > resize(int width, int height, int depth, const FogWorldBounds &bounds)
Allocate a regular lattice over world bounds.
std::uint64_t revision() const noexcept
Result< void > integrate(AtmosphereVolume &volume, const FogDensityField &field, const FogProfile &profile, const glm::mat4 &invViewProj, const glm::vec3 &lightDir, const glm::vec3 &lightColor, float intensity, const BeerLightCache *beerCache)
Integrate froxels with optional Beer-cache visibility.
Result< int > inject(AtmosphereVolume &volume, const FogDensityField &field, const FogProfile &profile, const glm::mat4 &invViewProj, bool occupancySkip)
Inject density-field media into an AtmosphereVolume froxel grid.
Result< FogRayResult > integrate(const FogDensityField &field, const FogProfile &profile, const glm::vec3 &origin, const glm::vec3 &direction, const FogVolumeBound &bound, const glm::vec3 &lightDir, const glm::vec3 &lightColor, float lightIntensity, const glm::vec3 &skyAmbient, const glm::vec3 &groundAmbient, int sampleCount, float sceneDepth, const BeerLightCache *beerCache, bool useAnalyticSegments) const
Integrate one view ray through the density field.
Result< int > injectToFroxel(AtmosphereVolume &volume, const glm::mat4 &invViewProj)
Add MAC density into an existing froxel grid without clearing or integrating.
Result< std::vector< DustParticle > > generateDust(int count, float turbulenceMeters, std::uint32_t seed=7u) const
Generate procedural dust for the simulation bounds.
Result< void > setQuality(FogQuality quality)
Select Fast / Enhanced / PhysicalReference and invalidate caches.
Definition FogSystem.cpp:15
Result< FogRayResult > integrateBeam(const AnalyticBeam &beam, const glm::vec3 &origin, const glm::vec3 &direction, float sceneDepth, float mediumDensity) const
Analytic beam integration using the active quality segment count.
FogQuality quality() const noexcept
Quality.
Definition FogSystem.h:49
Result< FogRayResult > marchRay(const glm::vec3 &origin, const glm::vec3 &direction, const FogVolumeBound &bound, const glm::vec3 &lightDir, const glm::vec3 &lightColor, float lightIntensity, const glm::vec3 &skyAmbient, const glm::vec3 &groundAmbient, float sceneDepth) const
World-space ray march through the live density field.
Definition FogSystem.cpp:67
Result< int > renderToFroxel(AtmosphereVolume &volume, const glm::mat4 &invViewProj, const glm::vec3 &lightDir, const glm::vec3 &lightColor, float intensity)
Inject + integrate the density field into a froxel AtmosphereVolume.
Definition FogSystem.cpp:80
Result< int > syncToVolumetric(Volumetric *volumetric, const glm::vec3 &lightDir, const glm::vec3 &lightColor, float intensity)
Map the live density field into a Volumetric froxel grid and integrate lighting. Resizes the atlas to...
FogQualityBudget budget() const noexcept
Budget.
Definition FogSystem.h:51
ContinuousArtOutput stylize(const FogRayResult &physical, float viewZ, float neighborOpacity=0.f) const noexcept
Apply ContinuousArt to a physical ray result.
Result< int > injectToVolumetric(Volumetric *volumetric)
Additive MAC inject into a Volumetric that already holds height fog / volumes. Does not resize,...
Result< void > configureDomain(int simWidth, int simHeight, int simDepth, const FogWorldBounds &bounds, float fixedDt=1.f/60.f)
Allocate density + MAC over world bounds at the quality froxel-ish resolution. Simulation resolution ...
Definition FogSystem.cpp:21
Result< void > seedHeightFog(float baseDensity, float baseHeight, float falloff, float curlScale, std::uint32_t seed=1u)
Seed a height-banded fog volume.
Definition FogSystem.cpp:31
Result< FogCflReport > stepSimulation(float dt)
Advance wind + MAC fluid by wall-clock dt (fixed substeps inside).
Definition FogSystem.cpp:41
Result< void > ensureBeerCache(const glm::vec3 &lightDir, const glm::vec3 &lightColor, float intensity)
Refresh BeerLightCache when quality/light/density require it.
Definition FogSystem.cpp:52
Result< void > configure(const FogDensityField &field, float fixedDt=kDefaultFixedDt)
Allocate MAC arrays matching a density field lattice.
Result< void > pullDensity(const FogDensityField &field)
Copy concentration from a density field (same resolution).
Result< void > pushDensity(FogDensityField &field) const
Write concentration back into a density field.
Result< FogCflReport > step(float dt, SceneWind &wind, FogInteractor *interactor, float simTime)
Advance simulation by wall-clock dt using fixed substeps.
Result< std::vector< DustParticle > > generate(const FogWorldBounds &volume, int count, float timeSeconds, float turbulenceMeters, std::uint32_t seed) const
Generate dust inside an AABB for the current view time.
FogQualityBudget budgetFor(FogQuality quality) noexcept
Resolve the budget for a quality preset.
Definition FogTypes.h:52
FogQuality
Tracking / cache / skip budget for the realtime fog pipeline.
Definition FogTypes.h:13
@ PhysicalReference
Dense tracking, no skip shortcuts.
Analytic beam volume: capped cone frustum or pyramidal spot.
Stylized fog presentation derived from a physical FogRayResult.
Definition FogTypes.h:169
Optical result of integrating one view ray through fog.
Definition FogTypes.h:122
Analytic volume used to bound a camera ray before sampling.
Definition FogRayMarch.h:17
Axis-aligned world bounds for a fog simulation domain.
Definition FogTypes.h:96
glm::vec3 size() const noexcept
Returns the size of .
Definition FogTypes.h:101
glm::vec4 lightColor
glm::vec4 lightDir
glm::mat4 invViewProj
glm::vec4 bounds