载入中...
搜索中...
未找到
ProceduralDust.cpp
浏览该文件的文档.
2
3#include "common/Diagnostic.h"
4
5#include <cmath>
6
7#include <glm/common.hpp>
8
9namespace eve::graphics::fog {
10namespace {
11
12[[nodiscard]] float hash11(std::uint32_t n) noexcept {
13 n ^= n >> 16;
14 n *= 0x7feb352du;
15 n ^= n >> 15;
16 n *= 0x846ca68bu;
17 n ^= n >> 16;
18 return static_cast<float>(n & 0x00FFFFFFu) / static_cast<float>(0x01000000u);
19}
20
21[[nodiscard]] std::uint32_t mix(std::uint32_t a, std::uint32_t b) noexcept {
22 return a * 747796405u + b * 2891336453u;
23}
24
25} // namespace
26
28 float timeSeconds, float turbulenceMeters,
29 std::uint32_t seed) const {
30 if (count < 1 || count > 4096) {
32 DiagnosticCode::InvalidArgument, "dust count must be in [1,4096]", "count", {},
33 "graphics.fog"));
34 }
35 if (!std::isfinite(timeSeconds) || !std::isfinite(turbulenceMeters) || turbulenceMeters < 0.f) {
37 DiagnosticCode::InvalidArgument, "time/turbulence must be finite; turbulence >= 0",
38 "turbulence", {}, "graphics.fog"));
39 }
40 const glm::vec3 size = volume.size();
41 if (!(size.x > 0.f && size.y > 0.f && size.z > 0.f)) {
43 DiagnosticCode::InvalidArgument, "volume bounds must have positive extent", "volume", {},
44 "graphics.fog"));
45 }
46
47 std::vector<DustParticle> out;
48 out.reserve(static_cast<std::size_t>(count));
49 for (int i = 0; i < count; ++i) {
50 const std::uint32_t h0 = mix(seed, static_cast<std::uint32_t>(i) * 3u + 1u);
51 const std::uint32_t h1 = mix(seed, static_cast<std::uint32_t>(i) * 3u + 2u);
52 const std::uint32_t h2 = mix(seed, static_cast<std::uint32_t>(i) * 3u + 3u);
53 const float ux = hash11(h0);
54 const float uy = hash11(h1);
55 const float uz = hash11(h2);
56
59 p.position = volume.minimum + glm::vec3(ux, uy, uz) * size;
60
61 // Continuous, camera-independent turbulence — no persistent buffer.
62 const float phase = timeSeconds * (p.band == DustParticle::Band::Fine ? 0.7f : 0.35f);
63 const float amp =
64 turbulenceMeters * (p.band == DustParticle::Band::Fine ? 0.55f : 1.f);
65 p.position += glm::vec3(amp * std::sin(phase + ux * 6.2831853f),
66 amp * 0.45f * std::sin(phase * 1.3f + uy * 6.2831853f),
67 amp * std::cos(phase * 0.9f + uz * 6.2831853f));
68 p.position = glm::clamp(p.position, volume.minimum, volume.maximum);
69 p.size = p.band == DustParticle::Band::Fine ? 0.015f : 0.04f;
70 p.brightness = 0.55f + 0.45f * hash11(mix(h0, h2));
71 out.push_back(p);
72 }
73 return Result<std::vector<DustParticle>>::success(std::move(out));
74}
75
76} // namespace eve::graphics::fog
double volume
float phase
Definition CaveMesh.cpp:58
glm::vec4 p[6]
Stable, structured diagnostics shared by engine modules.
glm::vec3 n
Definition Grass.cpp:63
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
std::uint32_t seed
Definition PointSet.cpp:807
std::uint32_t count
float size
Definition TreeMesh.cpp:156
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
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.
Deterministic dust mote spawned inside an analytic volume.
enum eve::graphics::fog::DustParticle::Band band
Axis-aligned world bounds for a fog simulation domain.
Definition FogTypes.h:96