gioser

tawasuyu/llimphi

Sovereign retained-mode GPU UI framework in Rust (wgpu+vello+taffy+parley), Elm loop, 40+ widgets.

Rust 484Markdown 258TOML 131RON 38118 Definitions

⎇ main llimphi-voxel/src/cielo.rs Rust · 88 lines · 3.2 KB History Who touched what raw

chore: refresco desde el monorepo — 132 miembros, 79 widgets, la galería vuelve y licencia dual d8edd9a9c · Sergio ·

1//! **Cielo de noche**: estrellas, luna y la luz que dan.
2//!
3//! Vive en la escena y no en el sello de quien filma porque **que sea de noche
4//! lo dice el cuento**: «la princesa vio una estrella» no se puede filmar a
5//! pleno sol, la ruede la marca que la ruede. El sello sigue decidiendo la luz
6//! de día; una escena con cielo de noche la reemplaza por la suya.
7//!
8//! De noche la dirección del sol pasa a ser la de **la luna** (el shader dibuja
9//! el disco pálido ahí y de ahí viene la luz directa, fría y tenue). Por defecto
10//! cae donde mira el plano de contraluz ([`SCENE_SUN`](crate::SCENE_SUN)), así
11//! que ese plano la encuadra.
12
13use llimphi_3d::glam::Vec3;
14use llimphi_3d::{Atmosphere, NightSky, PointLight};
15use serde::{Deserialize, Serialize};
16
17/// El cielo de una escena de noche.
18#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
19pub struct Cielo {
20    /// Color del cielo arriba.
21    pub cenit: [u8; 3],
22    /// Color del cielo en el horizonte; también el de la bruma.
23    pub horizonte: [u8; 3],
24    /// Cuántas estrellas, `0..1`.
25    pub estrellas: f32,
26    /// Dirección **hacia** la luna, sin normalizar. De ahí viene la luz.
27    pub luna: [f32; 3],
28    /// Radio de la luna en radianes; `0` = noche sin luna (la luz igual viene
29    /// de esa dirección, pero no se dibuja el disco).
30    pub luna_radio: f32,
31}
32
33impl Default for Cielo {
34    fn default() -> Self {
35        Self::noche()
36    }
37}
38
39/// La luz que da una pieza de utilería con luz propia, de noche: alcance en
40/// metros (= voxels).
41pub const ALCANCE_LUZ_PROPIA: f32 = 7.0;
42
43impl Cielo {
44    /// Una noche de cuento: azul profundo arriba, horizonte apenas más claro,
45    /// muchas estrellas y una luna grande — se dibuja, no se fotografía.
46    pub fn noche() -> Self {
47        Self {
48            cenit: [12, 18, 46],
49            horizonte: [40, 50, 92],
50            estrellas: 0.8,
51            luna: crate::SCENE_SUN,
52            luna_radio: 0.06,
53        }
54    }
55
56    /// Lo que el renderer necesita para pintarla.
57    pub fn night_sky(&self) -> NightSky {
58        NightSky {
59            amount: 1.0,
60            stars: self.estrellas.clamp(0.0, 1.0),
61            moon: self.luna_radio.max(0.0),
62        }
63    }
64
65    /// La atmósfera de esta noche, con la bruma y los haces que ya traía quien
66    /// filma (son del aire, no de la hora).
67    pub fn atmosfera(&self, fog_density: f32, god_rays: f32) -> Atmosphere {
68        Atmosphere { sky_zenith: self.cenit, sky_horizon: self.horizonte, fog_density, god_rays }
69    }
70
71    /// El color con que limpiar el cuadro antes de componer.
72    pub fn fondo(&self) -> [u8; 4] {
73        [self.horizonte[0], self.horizonte[1], self.horizonte[2], 255]
74    }
75}
76
77/// La luz puntual que da una pieza con luz propia, centrada en ella. `centro`
78/// en coords de grilla; `color` el de la pieza (se normaliza al canal más alto:
79/// lo que alumbra es el tono, no el exceso que la marca como luminosa).
80pub fn luz_de(centro: Vec3, color: [f32; 3], alcance: f32) -> PointLight {
81    let m = color[0].max(color[1]).max(color[2]).max(1e-3);
82    PointLight {
83        pos: centro.to_array(),
84        color: [color[0] / m * 1.1, color[1] / m * 1.1, color[2] / m * 1.1],
85        range: alcance,
86        radius: 0.0,
87    }
88}