Skip to main content

ling/gfx/
mod.rs

1// src/gfx/mod.rs — unified graphics state + sub-modules.
2//
3// Sub-modules
4//   raster  — pixel-level fill_triangle / draw_line  (native only)
5//   camera  — Camera3D: rotation storage + world→screen projection
6//   light   — Light struct + cel-shading quantiser
7//   depth   — DepthQueue: deferred draw accumulator
8//   vtex    — vector texture primitives
9//   webgl   — WebGL2 backend (wasm32 only)
10
11#[cfg(not(target_arch = "wasm32"))]
12pub mod raster;
13pub mod camera;
14pub mod light;
15pub mod depth;
16pub mod vtex;
17pub mod shapes;
18#[cfg(target_arch = "wasm32")]
19pub mod webgl;
20#[cfg(target_arch = "wasm32")]
21pub mod audio_web;
22
23pub use camera::Camera3D;
24pub use light::Light;
25pub use depth::DepthQueue;
26
27// ─── Native GfxState (minifb window + software framebuffer) ──────────────────
28
29#[cfg(not(target_arch = "wasm32"))]
30pub struct GfxState {
31    pub window:      Option<minifb::Window>,
32    pub buffer:      Vec<u32>,
33    pub width:       usize,
34    pub height:      usize,
35    /// Current pen colour (0x00RRGGBB) set by `สีดินสอ` / `set_color`.
36    pub color:       u32,
37    /// 3-D camera — set once per frame with `set_camera`.
38    pub camera:      Camera3D,
39    /// Active point lights for this frame — cleared by `clear_lights`.
40    pub lights:      Vec<Light>,
41    /// Ambient fill level [0..1].  Default 0.15.
42    pub ambient:     f32,
43    /// Depth-sorted draw queue — flushed by `แสดงผล` / `present`.
44    pub depth_queue: DepthQueue,
45    /// Mouse position delta since last frame (pixels).
46    pub mouse_dx: f32, pub mouse_dy: f32,
47    /// Previous mouse position for delta computation; NaN = no prior sample.
48    pub last_mx: f32, pub last_my: f32,
49    /// When true: cursor is hidden and reset to center every frame for infinite rotation.
50    pub mouse_captured: bool,
51    /// Shading mode for 3-D shape meshes: 0 flat · 1 cel · 2 holo (default).
52    pub shade_mode: u8,
53    /// Tunable cel/holo parameters (bands, shadow tint, rim, …).
54    pub shade: ling_graphics::shading::ShadeParams,
55    /// Blend mode for pixel writes: 0 = normal (overwrite), 1 = additive.
56    pub blend: u8,
57}
58
59#[cfg(not(target_arch = "wasm32"))]
60impl GfxState {
61    pub fn new() -> Self {
62        Self {
63            window:      None,
64            buffer:      Vec::new(),
65            width:       0,
66            height:      0,
67            color:       0x00FF_FFFF,
68            camera:      Camera3D::default(),
69            lights:      Vec::new(),
70            ambient:     0.15,
71            depth_queue: DepthQueue::default(),
72            mouse_dx:       0.0,
73            mouse_dy:       0.0,
74            last_mx:        f32::NAN,
75            last_my:        f32::NAN,
76            mouse_captured: false,
77            shade_mode:     2, // holographic cel by default
78            shade:          ling_graphics::shading::ShadeParams::default(),
79            blend:          0, // normal (overwrite) by default
80        }
81    }
82
83    pub fn sync_projection(&mut self) {
84        self.camera.cx    = self.width  as f32 / 2.0;
85        self.camera.cy    = self.height as f32 / 2.0;
86        self.camera.focal = self.height as f32;
87        self.camera.zdist = 5.0;
88    }
89}
90
91// ─── WASM GfxState (no window, no software framebuffer) ──────────────────────
92
93#[cfg(target_arch = "wasm32")]
94pub struct GfxState {
95    pub width:       usize,
96    pub height:      usize,
97    /// Current pen colour (0x00RRGGBB).
98    pub color:       u32,
99    /// Fill / clear colour components [0..1].
100    pub fill_r:      f32,
101    pub fill_g:      f32,
102    pub fill_b:      f32,
103    pub camera:      Camera3D,
104    pub lights:      Vec<Light>,
105    pub ambient:     f32,
106    /// Accumulates projected screen-space draw calls; flushed to WebGL by present().
107    pub depth_queue: DepthQueue,
108    pub shade_mode:  u8,
109    pub shade:       ling_graphics::shading::ShadeParams,
110}
111
112#[cfg(target_arch = "wasm32")]
113impl GfxState {
114    pub fn new() -> Self {
115        Self {
116            width:       800,
117            height:      600,
118            color:       0x00FF_FFFF,
119            fill_r:      0.0,
120            fill_g:      0.0,
121            fill_b:      0.0,
122            camera:      Camera3D::default(),
123            lights:      Vec::new(),
124            ambient:     0.15,
125            depth_queue: DepthQueue::default(),
126            shade_mode:  2,
127            shade:       ling_graphics::shading::ShadeParams::default(),
128        }
129    }
130
131    pub fn sync_projection(&mut self) {
132        self.camera.cx    = self.width  as f32 / 2.0;
133        self.camera.cy    = self.height as f32 / 2.0;
134        self.camera.focal = self.height as f32;
135        self.camera.zdist = 5.0;
136    }
137}