载入中...
搜索中...
未找到
FogFroxelBridge.cpp
浏览该文件的文档.
2
3#include "common/Diagnostic.h"
5
6#include <algorithm>
7#include <cmath>
8
9#include <glm/common.hpp>
10#include <glm/geometric.hpp>
11
12namespace eve::graphics::fog {
13namespace {
14
16[[nodiscard]] glm::vec3 reconstructFroxelCenter(const AtmosphereVolume& volume, int x, int y, int z,
17 const glm::mat4& invViewProj) {
18 const int width = std::max(volume.getWidth(), 1);
19 const int height = std::max(volume.getHeight(), 1);
20 const float ndcX = ((static_cast<float>(x) + 0.5f) / static_cast<float>(width)) * 2.f - 1.f;
21 const float ndcY = ((static_cast<float>(y) + 0.5f) / static_cast<float>(height)) * 2.f - 1.f;
22 auto unproject = [&](float ndcZ) {
23 const glm::vec4 homogeneous = invViewProj * glm::vec4(ndcX, ndcY, ndcZ, 1.f);
24 return glm::vec3(homogeneous) / homogeneous.w;
25 };
26 const glm::vec3 nearPoint = unproject(0.f);
27 const glm::vec3 farPoint = unproject(1.f);
28 const float span = std::max(volume.getFarDistance() - volume.getNearDistance(), 1e-6f);
29 const float depth01 = (volume.sliceDistance(z) - volume.getNearDistance()) / span;
30 return glm::mix(nearPoint, farPoint, depth01);
31}
32
33} // namespace
34
36 const FogProfile& profile, const glm::mat4& invViewProj,
37 bool occupancySkip) {
38 if (volume.getWidth() <= 0 || field.width() <= 0) {
40 "froxel/density volumes are empty", "inject",
41 {}, "graphics.fog"));
42 }
43
44 int written = 0;
45 for (int z = 0; z < volume.getDepth(); ++z) {
46 for (int y = 0; y < volume.getHeight(); ++y) {
47 for (int x = 0; x < volume.getWidth(); ++x) {
48 const glm::vec3 world = reconstructFroxelCenter(volume, x, y, z, invViewProj);
49 const float density = field.sampleDensity(world);
50 if (occupancySkip && density < 1e-4f) continue;
51 auto& froxel = volume.at(x, y, z);
52 const float sigmaT = profile.extinctionAt(density);
53 froxel.extinction += sigmaT;
54 froxel.scattering += profile.scatteringAt(density);
55 froxel.anisotropy = profile.anisotropy();
56 froxel.emissive += field.sampleLightAssist(world);
57 ++written;
58 }
59 }
60 }
61 return Result<int>::success(written);
62}
63
65 const FogProfile& profile, const glm::mat4& invViewProj,
66 const glm::vec3& lightDir, const glm::vec3& lightColor,
67 float intensity, const BeerLightCache* beerCache) {
68 if (volume.getWidth() <= 0) {
70 "integrate", {}, "graphics.fog"));
71 }
72 const float len = glm::length(lightDir);
73 const glm::vec3 dir = len > 1e-6f ? lightDir / len : glm::vec3(0.f, 1.f, 0.f);
74 const float phaseScale = profile.phase(glm::dot(dir, glm::vec3(0.f, 0.f, -1.f)));
75
76 if (beerCache && beerCache->valid()) {
77 for (int z = 0; z < volume.getDepth(); ++z) {
78 for (int y = 0; y < volume.getHeight(); ++y) {
79 for (int x = 0; x < volume.getWidth(); ++x) {
80 const glm::vec3 world = reconstructFroxelCenter(volume, x, y, z, invViewProj);
81 volume.setLightVisibility(x, y, z, beerCache->sampleTransmittance(field, world));
82 }
83 }
84 }
85 }
86
87 volume.integrate(lightColor * intensity, phaseScale);
88 return Result<void>::success();
89}
90
91} // namespace eve::graphics::fog
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
double volume
Stable, structured diagnostics shared by engine modules.
std::uint32_t height
std::uint32_t width
World3D * world
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
Camera-frustum volume used by the volumetric fog passes and CPU references.
Cached light-path transmittance used by Fast / Enhanced quality tiers.
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.
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.
Unit-density optical profile for participating media.
Definition FogProfile.h:16
float extinctionAt(float density) const noexcept
Extinction for a sampled density value.
float anisotropy() const noexcept
Henyey–Greenstein anisotropy in [-0.99, 0.99].
Definition FogProfile.h:29
float phase(float cosTheta) const noexcept
Dual-lobe Henyey–Greenstein phase evaluated for cosθ.
glm::vec3 scatteringAt(float density) const noexcept
Scattering coefficient σ_s = albedo * σ_t.
glm::vec4 lightColor
glm::vec4 lightDir
glm::mat4 invViewProj