20#include <simplesquirrel/simplesquirrel.hpp>
22#include "weather/shaders/weather_vert_spv.inc"
23#include "weather/shaders/weather_frag_spv.inc"
24#include "weather/shaders/bolt_vert_spv.inc"
25#include "weather/shaders/bolt_frag_spv.inc"
33 uint32_t
s = 0x9e3779b9u;
35 s =
s * 1664525u + 1013904223u;
38 float unit() {
return float(
next() % 10000u) / 9999.f; }
42constexpr int kRainCount = 1600;
43constexpr int kSnowCount = 1400;
44constexpr int kBoltCount = 4;
46constexpr float kBoxXZ = 26.f;
47constexpr float kBoxY = 20.f;
58void genRainTexture(std::vector<uint8_t> &rgba) {
59 const int w = 8,
h = 32;
60 rgba.resize(
size_t(
w) *
h * 4);
61 for (
int y = 0;
y <
h; ++
y) {
62 const float v = (float(
y) + 0.5f) /
float(
h);
63 const float endFade = 1.f - 2.f * std::fabs(
v - 0.5f);
64 for (
int x = 0;
x <
w; ++
x) {
65 const float u = (float(
x) + 0.5f) /
float(
w);
66 const float edge = 1.f - 2.f * std::fabs(
u - 0.5f);
67 const float alpha = std::pow(
edge, 2.f) * std::pow(endFade, 2.5f);
68 const int i = (
y *
w +
x) * 4;
72 rgba[i + 3] = uint8_t(std::min(255.f, alpha * 255.f));
78void genSnowTexture(std::vector<uint8_t> &rgba) {
79 const int w = 16,
h = 16;
80 rgba.resize(
size_t(
w) *
h * 4);
81 const float cx = (float(
w) - 1.f) * 0.5f;
82 const float cy = (float(
h) - 1.f) * 0.5f;
83 for (
int y = 0;
y <
h; ++
y) {
84 for (
int x = 0;
x <
w; ++
x) {
85 const float dx = (float(
x) -
cx) /
cx;
86 const float dy = (float(
y) -
cy) /
cy;
87 const float r = std::sqrt(
dx *
dx +
dy *
dy);
88 float alpha = 1.f -
r;
89 if (alpha < 0.f) alpha = 0.f;
90 alpha = std::pow(alpha, 2.2f);
91 const int i = (
y *
w +
x) * 4;
95 rgba[i + 3] = uint8_t(std::min(255.f, alpha * 255.f));
106graphics::Mesh *buildFieldMesh(graphics::Graphics *gfx, Lcg &rng,
int count,
float len,
110 const int vertCount =
count * 4;
111 const int idxCount =
count * 6;
112 std::vector<float>
pos(vertCount * 3);
113 std::vector<float> nrm(vertCount * 3, 0.f);
114 std::vector<float>
uv(vertCount * 2);
115 std::vector<uint32_t>
idx(idxCount);
117 for (
int i = 0; i <
count; ++i) {
118 const float ax = rng.range(-kBoxXZ, kBoxXZ);
119 const float ay = rng.range(0.f, kBoxY);
120 const float az = rng.range(-kBoxXZ, kBoxXZ);
121 const int v0 = i * 4;
122 const int b = v0 * 3,
t = v0 * 2;
131 const float lengthScale = rng.range(0.55f, 1.45f);
132 const float widthScale = rng.range(0.65f, 1.25f);
133 const float speedScale = rng.range(0.82f, 1.18f);
134 for (
int j = 0; j < 4; ++j) {
135 nrm[
b + j * 3 + 0] = lengthScale;
136 nrm[
b + j * 3 + 1] = widthScale;
137 nrm[
b + j * 3 + 2] = speedScale;
141 uv[
t + 0] = -0.5f;
uv[
t + 1] = 0.f;
142 uv[
t + 2] = -0.5f;
uv[
t + 3] = 1.f;
143 uv[
t + 4] = 0.5f;
uv[
t + 5] = 1.f;
144 uv[
t + 6] = 0.5f;
uv[
t + 7] = 0.f;
146 const uint32_t base = uint32_t(v0);
147 idx[i * 6 + 0] = base + 0;
148 idx[i * 6 + 1] = base + 1;
149 idx[i * 6 + 2] = base + 2;
150 idx[i * 6 + 3] = base + 0;
151 idx[i * 6 + 4] = base + 2;
152 idx[i * 6 + 5] = base + 3;
155 return gfx->newMeshFromArrays(
pos.data(), nrm.data(),
uv.data(), vertCount,
idx.data(),
160 float x = 0,
y = 0,
z = 0;
163void displacePath(std::vector<Pt> &
path, Lcg &rng,
float amount) {
164 std::vector<Pt> refined;
165 refined.reserve(
path.size() * 2 - 1);
166 for (
size_t i = 0; i + 1 <
path.size(); ++i) {
167 const Pt &
a =
path[i];
168 const Pt &
b =
path[i + 1];
169 refined.push_back(
a);
170 refined.push_back({(
a.x +
b.x) * 0.5f + rng.range(-amount, amount),
172 (
a.z +
b.z) * 0.5f + rng.range(-amount, amount)});
174 refined.push_back(
path.back());
180graphics::Mesh *buildBoltMesh(graphics::Graphics *gfx, Lcg &rng, Pt
top, Pt ground) {
181 std::vector<Pt> pts{
top, ground};
182 float displacement = 3.2f;
184 displacePath(pts, rng, displacement);
185 displacement *= 0.48f;
188 std::vector<std::vector<Pt>>
paths{pts};
189 const int branchStarts[] = {7, 12, 18, 23};
190 for (
int start : branchStarts) {
191 if (
start >=
int(pts.size()) - 2)
continue;
193 const float side = (rng.unit() < 0.5f) ? -1.f : 1.f;
195 origin.y - rng.range(2.5f, 5.5f),
196 origin.z + rng.range(-3.5f, 3.5f)};
197 if (
tip.y < 0.5f)
tip.y = 0.5f;
199 float branchDisp = 1.1f;
201 displacePath(branch, rng, branchDisp);
204 paths.push_back(branch);
208 std::vector<float> allUv;
209 auto emitStrip = [&](
const std::vector<Pt> &
path,
float wTop,
float wBottom,
int plane) {
210 const int n = int(
path.size()) - 1;
211 for (
int i = 0; i <
n; ++i) {
213 float sx = plane == 0 ? 1.f : 0.f;
214 float sz = plane == 0 ? 0.f : 1.f;
215 float w = wBottom + (wTop - wBottom) * (
float(i) / float(
n));
216 Pt p0 = {
a.x +
sx *
w,
a.y,
a.z +
sz *
w};
217 Pt p1 = {
a.x -
sx *
w,
a.y,
a.z -
sz *
w};
218 Pt p2 = {
b.x -
sx *
w,
b.y,
b.z -
sz *
w};
219 Pt p3 = {
b.x +
sx *
w,
b.y,
b.z +
sz *
w};
224 allUv.insert(allUv.end(), {-1.f, float(i) /
n, 1.f, float(i) /
n,
225 1.f, float(i + 1) /
n, -1.f, float(i + 1) /
n});
229 const float wMain = 0.20f;
230 for (
size_t p = 0;
p <
paths.size(); ++
p) {
231 const float scale =
p == 0 ? 1.f : 0.55f;
236 const int vertCount = int(all.size());
237 const int idxCount = vertCount / 4 * 6;
238 std::vector<float>
pos(vertCount * 3);
239 std::vector<float> nrm(vertCount * 3, 0.f);
240 std::vector<float>
uv(vertCount * 2, 0.f);
241 std::vector<uint32_t>
idx(idxCount);
243 for (
int i = 0; i < vertCount; ++i) {
244 pos[i * 3 + 0] = all[i].x;
245 pos[i * 3 + 1] = all[i].y;
246 pos[i * 3 + 2] = all[i].z;
247 nrm[i * 3 + 1] = 1.f;
248 uv[i * 2 + 0] = allUv[i * 2 + 0];
249 uv[i * 2 + 1] = allUv[i * 2 + 1];
251 for (
int q = 0;
q < vertCount / 4; ++
q) {
252 const uint32_t base = uint32_t(
q * 4);
253 idx[
q * 6 + 0] = base + 0;
254 idx[
q * 6 + 1] = base + 1;
255 idx[
q * 6 + 2] = base + 2;
256 idx[
q * 6 + 3] = base + 0;
257 idx[
q * 6 + 4] = base + 2;
258 idx[
q * 6 + 5] = base + 3;
261 return gfx->newMeshFromArrays(
pos.data(), nrm.data(),
uv.data(), vertCount,
idx.data(),
305 std::vector<graphics::Renderable3D *>
bolts;
316const char *
const Weather::kPresetNames[] = {
"clear",
"drizzle",
"rain",
"storm",
"snow",
"fog",
"wind",
"blizzard"};
329 float speed,
float length,
float width,
float intensity,
330 float fogR,
float fogG,
float fogB,
float fogDensity,
float flash) {
337 mat->
setFloat(
"uIntensity", intensity);
341 mat->
setFloat(
"uFogDensity", fogDensity);
347 shader->declareFloat(
"uTime");
348 shader->declareFloat(
"uWindX");
349 shader->declareFloat(
"uWindZ");
350 shader->declareFloat(
"uSpeed");
351 shader->declareFloat(
"uLength");
352 shader->declareFloat(
"uWidth");
353 shader->declareFloat(
"uIntensity");
354 shader->declareFloat(
"uFogR");
355 shader->declareFloat(
"uFogG");
356 shader->declareFloat(
"uFogB");
357 shader->declareFloat(
"uFogDensity");
358 shader->declareFloat(
"uFlash");
359 shader->declareFloat(
"uKind");
360 shader->declareFloat(
"uWindOffsetX");
361 shader->declareFloat(
"uWindOffsetZ");
366 if (impl_->
built)
return;
372 std::vector<uint8_t> rainRgba, snowRgba;
373 genRainTexture(rainRgba);
374 genSnowTexture(snowRgba);
379 std::vector<uint32_t> wv(weather_vert_spv, weather_vert_spv + weather_vert_spv_count);
380 std::vector<uint32_t> wf(weather_frag_spv, weather_frag_spv + weather_frag_spv_count);
381 std::vector<uint32_t> bv(bolt_vert_spv, bolt_vert_spv + bolt_vert_spv_count);
382 std::vector<uint32_t> bf(bolt_frag_spv, bolt_frag_spv + bolt_frag_spv_count);
394 declareWeatherParams(weatherVert);
395 declareWeatherParams(boltShader);
398 graphics::Mesh *rainMesh = buildFieldMesh(gfx, impl_->
rng, kRainCount, 0.82f, 0.024f);
399 impl_->
rain = graphics::Renderable3D::create();
414 graphics::Mesh *snowMesh = buildFieldMesh(gfx, impl_->
rng, kSnowCount, 0.22f, 0.10f);
415 impl_->
snow = graphics::Renderable3D::create();
430 for (
int i = 0; i < kBoltCount; ++i) {
431 Pt
top{impl_->
rng.range(-4.f, 4.f), kBoxY, impl_->
rng.range(-4.f, 4.f)};
432 Pt ground{impl_->
rng.range(-3.f, 3.f), 0.f, impl_->
rng.range(-3.f, 3.f)};
441 mm->
setTint(1.0f, 1.0f, 1.0f, 1.0f);
444 b->setVisible(
false);
445 impl_->
bolts.push_back(
b);
449 pushWeatherParams(impl_->
rainMat, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
450 pushWeatherParams(impl_->
snowMat, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
462 "invalid Pcg weather photo-mode assignment",
a.field,{},
"weather.photoMode"));};
464 if(
a.field==
"m_pcgWeatherEnabled"){
auto*
v=std::get_if<bool>(&
a.value);
if(!
v)
return bad();impl_->
pcgWeatherEnabled=*
v;}
465 else if(
a.field==
"m_pcgWeatherRain"){
auto*
v=std::get_if<bool>(&
a.value);
if(!
v)
return bad();impl_->
pcgRain=*
v;}
466 else if(
a.field==
"m_pcgWeatherSnow"){
auto*
v=std::get_if<bool>(&
a.value);
if(!
v)
return bad();impl_->
pcgSnow=*
v;}
467 else if(
a.field==
"m_pcgWindSettingsOverride"){
auto*
v=std::get_if<bool>(&
a.value);
if(!
v)
return bad();impl_->
pcgWindOverride=*
v;}
468 else if(
a.field==
"m_pcgWindDirection"){
auto*
v=std::get_if<float>(&
a.value);
if(!
v||!std::isfinite(*
v))
return bad();impl_->
windDirDeg=*
v;}
469 else if(
a.field==
"m_pcgWindSpeed"){
auto*
v=std::get_if<float>(&
a.value);
if(!
v||!std::isfinite(*
v)||*
v<0)
return bad();impl_->
windSpeed=*
v;}
500 if(!std::isfinite(
x)||!std::isfinite(
y)||!std::isfinite(
z))
502 "Snow wind must be finite",
"weather.snowWind"));
527 if (!std::isfinite(
x) || !std::isfinite(
y) || !std::isfinite(
z))
547 if (!impl_->
built || impl_->
bolts.empty())
return;
583 return 0.35f + (1.f - cloudiness) * 0.55f;
592 if (!impl_->
gfx)
return;
602 const float rad = impl_->
windDirDeg * 0.0174532925f;
603 const float windX = -std::sin(rad) * impl_->
windSpeed;
604 const float windZ = std::cos(rad) * impl_->
windSpeed;
615 const float fogR = impl_->
fogR, fogG = impl_->
fogG, fogB = impl_->
fogB;
620 const bool windOn = impl_->
preset == 6;
624 impl_->
rain->
setVisible(rainOn && intensity > 0.01f && !suppressRain);
626 const float speed = windOn ? 0.15f : 18.f;
628 pushWeatherParams(impl_->
rainMat,
time, windX, windZ, speed, windOn ? 9.0f : 0.65f, windOn ? 1.1f : 0.045f,
629 windOn ? intensity * std::min(1.f, impl_->
windSpeed / 8.f) * 0.22f : intensity, fogR, fogG,
638 impl_->
snow->
setVisible(snowOn && intensity > 0.01f && !suppressSnow);
662 }
else if (impl_->
boltLife < 0.095f) {
664 }
else if (impl_->
boltLife < 0.19f) {
665 f = 0.72f * (1.f - (impl_->
boltLife - 0.095f) / 0.095f);
667 f = std::max(0.f, 0.22f * (1.f - (impl_->
boltLife - 0.19f) / 0.31f));
669 impl_->
flash = std::clamp(
f, 0.f, 1.f);
672 impl_->
bolts[bi]->setVisible(impl_->
flash > 0.02f);
673 pushWeatherParams(impl_->
boltMats[bi],
time, windX, windZ, 0.f, 0.f, 0.f, 1.f, fogR, fogG,
674 fogB, fogD, impl_->
flash);
677 impl_->
bolts[bi]->setVisible(
false);
682 impl_->
flash *= std::max(0.f, 1.f - dt * 8.f);
688 const float dark = 1.f - 0.35f * cloudiness;
689 const float skyFlash = impl_->
flash * 0.55f;
691 std::min(1.f, impl_->
skyR * dark + skyFlash * 0.68f),
692 std::min(1.f, impl_->
skyG * dark + skyFlash * 0.78f),
693 std::min(1.f, impl_->
skyB * dark + skyFlash), 1.f);
694 const float flashLight = impl_->
flash * 1.35f;
696 impl_->
sunIntensity * (1.f - 0.35f * cloudiness) + flashLight * 0.72f,
697 impl_->
sunIntensity * (1.f - 0.35f * cloudiness) * 0.95f + flashLight * 0.84f,
698 impl_->
sunIntensity * (1.f - 0.35f * cloudiness) * 0.88f + flashLight);
706void Weather::expose(ssq::Table &table) {
707 auto cls = table.addClass(
name, Weather::create,
false);
711 float x,
float y,
float z,
float sx,
float sy,
float sz,
int mode,
int insideReverb,
int outsideReverb) {
712 return eve::script::projectResult(vm,self->configureBox(x,y,z,sx,sy,sz,mode,insideReverb,outsideReverb));
715 float x,
float y,
float z,
float radius,
int mode,
int insideReverb,
int outsideReverb) {
716 return eve::script::projectResult(vm,self->configureSphere(x,y,z,radius,mode,insideReverb,outsideReverb));
721 auto settings = table.addClass(
"ThunderStrikeSettings", ssq::Class::Ctor<ThunderStrikeSettings()>());
726 auto state = table.addClass(
"ThunderStrikeState", ssq::Class::Ctor<ThunderStrikeState()>());
729 table.addFunc(
"triggerThunderStrike", [
vm=table.getHandle()](ThunderStrikeState* state,
730 const ThunderStrikeSettings*
settings,
float x,
float y,
float z, std::uint32_t
seed) {
731 auto result=state&&settings?triggerThunderStrike(*state,*settings,x,y,z,seed)
732 :Result<ThunderStrikeReceipt>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument,
"state and settings required"));
733 return eve::script::projectResult(vm,std::move(result),[](const ThunderStrikeReceipt& value) {
734 return Value::Object{{
"x",value.x},{
"y",value.y},{
"z",value.z},{
"intensity",value.intensity},
735 {
"radius",value.radius},{
"volume",value.volume},{
"audioClipIndex",value.audioClipIndex}};
738 table.addFunc(
"advanceThunderStrike", [
vm=table.getHandle()](ThunderStrikeState*
state,
float dt) {
745void Weather::expose(ssq::Class &
cls) {
746 cls.addFunc(
"getName", &Weather::getName);
747 cls.addFunc(
"init", &Weather::init);
748 cls.addFunc(
"update", &Weather::update);
749 cls.addFunc(
"setPreset", &Weather::setPreset);
750 cls.addFunc(
"getPreset", &Weather::getPreset);
751 cls.addFunc(
"setIntensity", &Weather::setIntensity);
752 cls.addFunc(
"getIntensity", &Weather::getIntensity);
753 cls.addFunc(
"setWindSpeed", &Weather::setWindSpeed);
754 cls.addFunc(
"getWindSpeed", &Weather::getWindSpeed);
755 cls.addFunc(
"setWindDirection", &Weather::setWindDirection);
756 cls.addFunc(
"getWindDirection", &Weather::getWindDirection);
757 cls.addFunc(
"setSnowWind",[
vm=
cls.getHandle()](
Weather* self,
float x,
float y,
float z){
758 return eve::script::projectResult(vm,self->setSnowWind(x,y,z));
760 cls.addFunc(
"clearSnowWind",&Weather::clearSnowWind);
761 cls.addFunc(
"hasSnowWind",&Weather::hasSnowWind);
762 cls.addFunc(
"getSnowWindX",&Weather::getSnowWindX);
763 cls.addFunc(
"getSnowWindY",&Weather::getSnowWindY);
764 cls.addFunc(
"getSnowWindZ",&Weather::getSnowWindZ);
766 const PcgInteriorWeatherVolume*
volume,
float x,
float y,
float z) {
767 auto result = volume ? self->applyInteriorVolume(*volume,x,y,z) :
768 Result<PcgInteriorWeatherTransition>::failure(Diagnostic::error(
769 DiagnosticCode::InvalidArgument,
"interior volume required",
"weather.interiorVolume"));
770 return eve::script::projectResult(vm,std::move(result),[](PcgInteriorWeatherTransition value) {
771 return static_cast<int>(value);
774 cls.addFunc(
"setInteriorVolumeState", [
vm=
cls.getHandle()](
Weather* self,
780 return static_cast<int>(
value);
783 cls.addFunc(
"clearInteriorWeather",&Weather::clearInteriorWeather);
784 cls.addFunc(
"isInsideInteriorWeather",&Weather::isInsideInteriorWeather);
785 cls.addFunc(
"isInteriorWeatherCollisionRequested",&Weather::isInteriorWeatherCollisionRequested);
786 cls.addFunc(
"getCurrentWeatherReverbPreset",&Weather::getCurrentWeatherReverbPreset);
787 cls.addFunc(
"setLightningEnabled", &Weather::setLightningEnabled);
788 cls.addFunc(
"isLightningEnabled", &Weather::isLightningEnabled);
789 cls.addFunc(
"strike", &Weather::strike);
790 cls.addFunc(
"getFlash", &Weather::getFlash);
791 cls.addFunc(
"setSkyColor", &Weather::setSkyColor);
792 cls.addFunc(
"getSkyColorR", &Weather::getSkyColorR);
793 cls.addFunc(
"getSkyColorG", &Weather::getSkyColorG);
794 cls.addFunc(
"getSkyColorB", &Weather::getSkyColorB);
795 cls.addFunc(
"setSunIntensity", &Weather::setSunIntensity);
796 cls.addFunc(
"getSunIntensity", &Weather::getSunIntensity);
797 cls.addFunc(
"setFogColor", &Weather::setFogColor);
798 cls.addFunc(
"getFogColorR", &Weather::getFogColorR);
799 cls.addFunc(
"getFogColorG", &Weather::getFogColorG);
800 cls.addFunc(
"getFogColorB", &Weather::getFogColorB);
801 cls.addFunc(
"setFogDensity", &Weather::setFogDensity);
802 cls.addFunc(
"getFogDensity", &Weather::getFogDensity);
803 cls.addFunc(
"setEnvironmentEnabled", &Weather::setEnvironmentEnabled);
804 cls.addFunc(
"isEnvironmentEnabled", &Weather::isEnvironmentEnabled);
805 cls.addFunc(
"getAmbientBrightness", &Weather::getAmbientBrightness);
std::array< double, 10 > q
std::array< float, 3 > scale
#define Module_IMPL(ModuleName, newExpr)
The single Squirrel projection for common Result, Status and Value.
TerrainThermalSettings settings
std::map< std::string, std::string > paths
std::vector< char > inside
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.
Move-only operation result carrying either a value or Status.
static Result success(T value)
Construct a successful result owning value.
static Result failure(Status status)
Construct a failed result from a structured status.
virtual std::string getBackendName() const =0
Renderer backend id used by sibling modules (e.g. Gpgpu).
virtual void setDirectionalLight(float dx, float dy, float dz, float r=1.f, float g=1.f, float b=1.f)
Sets the directional light.
virtual Shader * newMeshShaderFromSpv(const std::vector< uint32_t > &vertSpv, const std::vector< uint32_t > &fragSpv)=0
Create a Mesh3D custom shader (MeshVertex + Frame UBO + albedo). Empty vert → default mesh3d....
virtual void setBackgroundColorRGBA(float r, float g, float b, float a=1.f)
Sets the background color rgba.
virtual Texture * newTexture(int width, int height, const uint8_t *rgba, bool repeatU=false, bool repeatV=false)=0
Creates a texture. @ownership Caller deletes unless documented otherwise.
Material * newMaterial()
Create a Material asset (shading model + textures + PBR knobs). Caller owns Material*; not tracked by...
virtual Shader * newMeshShaderFromWgsl(const std::string &vertWgsl, const std::string &fragWgsl)=0
Create a Mesh3D custom shader from WGSL source (WebGPU backend). The WGSL must declare the engine's F...
Packages shading method + surface parameters into one attachable asset.
void setAlbedoTexture(Texture *texture)
Set the borrowed material texture. @ownership Graphics factory owns the resource. @lifetime Keep aliv...
void setCastShadow(bool cast)
Sets the cast shadow.
void setCastOcclusion(bool cast)
Sets the cast occlusion.
void setReceiveShadow(bool receive)
Sets the receive shadow.
void setReceiveLight(bool receive)
Sets the receive light.
void setShadingModel(const std::string &model)
"pbr" | "unlit" | "hair" | "custom" (unknown → pbr).
void setTint(float r, float g, float b, float a=1.f)
Sets the tint.
void setFloat(const std::string &name, float value)
Sets the float.
void setShader(Shader *shader)
Set an optional Mesh3D / hair shader; nullptr selects the built-in shading path.
GPU mesh handle (+ optional CPU morph targets).
EVENGINE_API_BACKENDS public API.
void setMaterial(Material *material)
Attach a Material that packages shading method + surface params.
void setVisible(bool visible)
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Caller-owned, immutable-after-configuration Pcg interior-weather volume. @ownership This value owns a...
bool contains(float x, float y, float z) const noexcept
Return whether a finite world-space position lies inside, including the boundary.
Weather module — real-time precipitation / lightning / wind system.
static const char *const kPresetNames[]
void setSunIntensity(float v)
Sets the sun intensity.
float getFogColorB() const
Returns the fog color b.
void clearInteriorWeather()
Clear interior state and restore the last sampled exterior reverb preset.
static const int kPresetCount
float getFogDensity() const
Returns the fog density.
void setWindSpeed(float v)
Sets the wind speed.
float getSnowWindY() const
Returns the snow wind y.
void init(graphics::Graphics *gfx)
Idempotent; builds meshes/shaders on first call.
Result< void > setSnowWind(float x, float y, float z)
Override snow world velocity exactly as Pcg SnowWindDir.
void setLightningEnabled(bool on)
Sets the lightning enabled.
void setIntensity(float v)
Sets the intensity.
bool getPcgWindOverride() const
Return whether photo mode overrides the captured wind.
float getFogColorG() const
Returns the fog color g.
void strike()
Force a bolt strike this frame (useful for manual testing).
void setSkyColor(float r, float g, float b)
Sets the sky color.
float getWindDirection() const
Returns the wind direction.
void clearSnowWind()
Return to horizontal wind plus the native default fall speed.
bool getPcgSnowEnabled() const
Return Pcg's independent snow playback state.
Result< PcgInteriorWeatherTransition > setInteriorVolumeState(const PcgInteriorWeatherVolume &volume, bool inside)
Apply a trigger-driven enter/exit event without retaining the volume.
void setFogDensity(float v)
Sets the fog density.
std::string getPreset() const
Returns the preset.
void setEnvironmentEnabled(bool enabled)
Enable legacy weather-owned sky and directional lighting.
float getFogColorR() const
Returns the fog color r.
int getCurrentWeatherReverbPreset() const
Returns the current weather reverb preset.
float getSunIntensity() const
Returns the sun intensity.
float getSkyColorG() const
Returns the sky color g.
float getSkyColorB() const
Returns the sky color b.
float getSnowWindZ() const
Returns the snow wind z.
Result< PcgInteriorWeatherTransition > applyInteriorVolume(const PcgInteriorWeatherVolume &volume, float x, float y, float z)
Sample a bounds-driven interior volume and atomically apply an enter/exit transition.
bool isInteriorWeatherCollisionRequested() const
True when interior weather collision requested.
float getSnowWindX() const
Returns the snow wind x.
void setPreset(const std::string &name)
Sets the preset.
bool isLightningEnabled() const
True when lightning enabled.
float getWindSpeed() const
Returns the wind speed.
float getFlash() const
How bright the current flash is (0..1), sampled by the scene for a key light.
float getAmbientBrightness() const
Ambient multiplier that the example should feed into camera.setAmbient().
PhotoModeFieldAcceptance acceptsPhotoModeField(const PhotoModeAssignment &assignment) const noexcept override
Return whether this module owns a Pcg weather photo-mode field.
void update(float dt, graphics::Graphics *gfx)
Advance sim + push per-frame uniforms; must run before gfx.render3D().
void setFogColor(float r, float g, float b)
Sets the fog color.
bool hasSnowWind() const
Return whether a Pcg snow velocity override is active.
float getIntensity() const
Returns the intensity.
void setWindDirection(float degrees)
Wind direction in degrees; 0 = toward +Z, 90 = toward -X.
bool isInsideInteriorWeather() const
True when inside interior weather.
float getSkyColorR() const
Returns the sky color r.
bool isEnvironmentEnabled() const
True when environment enabled.
bool getPcgRainEnabled() const
Return Pcg's independent rain playback state.
bool getPcgWeatherEnabled() const
Return Pcg's master weather-enabled state.
~Weather() override
Weather.
Result< void > applyPhotoModeField(const PhotoModeAssignment &assignment) override
Atomically apply one Pcg weather field to this authoritative weather state.
constexpr HexDirection next(HexDirection d) noexcept
The next direction clockwise (NW wraps to NE).
ssq::Table projectResult(HSQUIRRELVM vm, Result< void > &&result)
Consume and project a void native Result using the common schema.
constexpr const char * kWeatherFragWgsl
constexpr const char * kWeatherVertWgsl
constexpr const char * kBoltFragWgsl
constexpr const char * kBoltVertWgsl
PcgInteriorWeatherMode
Interior precipitation policy mirrored from Pcg.
Result< void > advanceThunderStrike(ThunderStrikeState &state, float dt)
Apply Pcg's clamped Lerp(intensity,0,dt*2) decay and 0.15 stop threshold.
DiagnosticCode
Stable machine-readable diagnostic codes.
PhotoModeFieldAcceptance
Capability implemented by the composition root that routes assignments to domain owners.
One reversible field assignment in a photo-mode transaction.
graphics::Renderable3D * rain
graphics::Renderable3D * snow
graphics::Material * rainMat
PcgInteriorWeatherMode interiorMode
std::vector< graphics::Renderable3D * > bolts
std::vector< graphics::Material * > boltMats
graphics::Material * snowMat