1pub mod gbuffer;
10pub mod pipeline;
11pub mod materials;
12pub mod antialiasing;
13
14pub use gbuffer::{
16 GBuffer, GBufferLayout, GBufferAttachment, GBufferAttachmentFormat,
17 GBufferDebugView, GBufferDebugChannel, GBufferStats, MrtConfig, ClearValue,
18};
19pub use pipeline::{
20 DeferredPipeline, DepthPrePass, GeometryPass, LightingPass, ForwardPass,
21 PostProcessPass, HdrFramebuffer, ExposureController, ExposureMode,
22 RenderQueue, RenderBucket, RenderItem, SortMode,
23};
24pub use materials::{
25 PbrMaterial, MaterialInstance, MaterialLibrary, MaterialSortKey,
26 InstanceData, MaterialPreset, MaterialPresets,
27};
28pub use antialiasing::{
29 AntiAliasingMode, FxaaPass, FxaaQuality, TaaPass, TaaConfig,
30 MsaaConfig, MsaaSampleCount, SharpeningPass, CasConfig,
31};
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
35pub struct TextureSlot(pub u32);
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
39pub struct FramebufferId(pub u32);
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub struct Viewport {
44 pub x: i32,
45 pub y: i32,
46 pub width: u32,
47 pub height: u32,
48}
49
50impl Viewport {
51 pub fn new(width: u32, height: u32) -> Self {
52 Self { x: 0, y: 0, width, height }
53 }
54
55 pub fn aspect_ratio(&self) -> f32 {
56 if self.height == 0 {
57 1.0
58 } else {
59 self.width as f32 / self.height as f32
60 }
61 }
62
63 pub fn pixel_count(&self) -> u64 {
64 self.width as u64 * self.height as u64
65 }
66}
67
68impl Default for Viewport {
69 fn default() -> Self {
70 Self { x: 0, y: 0, width: 1920, height: 1080 }
71 }
72}
73
74#[derive(Debug, Clone, Copy)]
76pub struct Mat4 {
77 pub cols: [[f32; 4]; 4],
78}
79
80impl Mat4 {
81 pub const IDENTITY: Self = Self {
82 cols: [
83 [1.0, 0.0, 0.0, 0.0],
84 [0.0, 1.0, 0.0, 0.0],
85 [0.0, 0.0, 1.0, 0.0],
86 [0.0, 0.0, 0.0, 1.0],
87 ],
88 };
89
90 pub fn from_cols(c0: [f32; 4], c1: [f32; 4], c2: [f32; 4], c3: [f32; 4]) -> Self {
91 Self { cols: [c0, c1, c2, c3] }
92 }
93
94 pub fn mul_mat4(&self, rhs: &Mat4) -> Mat4 {
95 let mut result = [[0.0f32; 4]; 4];
96 for col in 0..4 {
97 for row in 0..4 {
98 let mut sum = 0.0f32;
99 for k in 0..4 {
100 sum += self.cols[k][row] * rhs.cols[col][k];
101 }
102 result[col][row] = sum;
103 }
104 }
105 Mat4 { cols: result }
106 }
107
108 pub fn mul_vec4(&self, v: [f32; 4]) -> [f32; 4] {
109 let mut result = [0.0f32; 4];
110 for row in 0..4 {
111 for col in 0..4 {
112 result[row] += self.cols[col][row] * v[col];
113 }
114 }
115 result
116 }
117
118 pub fn transpose(&self) -> Mat4 {
119 let mut result = [[0.0f32; 4]; 4];
120 for i in 0..4 {
121 for j in 0..4 {
122 result[i][j] = self.cols[j][i];
123 }
124 }
125 Mat4 { cols: result }
126 }
127
128 pub fn perspective(fov_y_rad: f32, aspect: f32, near: f32, far: f32) -> Self {
129 let f = 1.0 / (fov_y_rad * 0.5).tan();
130 let nf = 1.0 / (near - far);
131 Self {
132 cols: [
133 [f / aspect, 0.0, 0.0, 0.0],
134 [0.0, f, 0.0, 0.0],
135 [0.0, 0.0, (far + near) * nf, -1.0],
136 [0.0, 0.0, 2.0 * far * near * nf, 0.0],
137 ],
138 }
139 }
140
141 pub fn look_at(eye: [f32; 3], center: [f32; 3], up: [f32; 3]) -> Self {
142 let f = vec3_normalize([
143 center[0] - eye[0],
144 center[1] - eye[1],
145 center[2] - eye[2],
146 ]);
147 let s = vec3_normalize(vec3_cross(f, up));
148 let u = vec3_cross(s, f);
149 Self {
150 cols: [
151 [s[0], u[0], -f[0], 0.0],
152 [s[1], u[1], -f[1], 0.0],
153 [s[2], u[2], -f[2], 0.0],
154 [
155 -vec3_dot(s, eye),
156 -vec3_dot(u, eye),
157 vec3_dot(f, eye),
158 1.0,
159 ],
160 ],
161 }
162 }
163}
164
165impl Default for Mat4 {
166 fn default() -> Self {
167 Self::IDENTITY
168 }
169}
170
171pub fn vec3_dot(a: [f32; 3], b: [f32; 3]) -> f32 {
173 a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
174}
175
176pub fn vec3_cross(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
177 [
178 a[1] * b[2] - a[2] * b[1],
179 a[2] * b[0] - a[0] * b[2],
180 a[0] * b[1] - a[1] * b[0],
181 ]
182}
183
184pub fn vec3_normalize(v: [f32; 3]) -> [f32; 3] {
185 let len = (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]).sqrt();
186 if len < 1e-10 {
187 [0.0, 0.0, 0.0]
188 } else {
189 [v[0] / len, v[1] / len, v[2] / len]
190 }
191}
192
193pub fn vec3_sub(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
194 [a[0] - b[0], a[1] - b[1], a[2] - b[2]]
195}
196
197pub fn vec3_add(a: [f32; 3], b: [f32; 3]) -> [f32; 3] {
198 [a[0] + b[0], a[1] + b[1], a[2] + b[2]]
199}
200
201pub fn vec3_scale(v: [f32; 3], s: f32) -> [f32; 3] {
202 [v[0] * s, v[1] * s, v[2] * s]
203}
204
205pub fn vec3_length(v: [f32; 3]) -> f32 {
206 (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]).sqrt()
207}
208
209pub fn vec3_lerp(a: [f32; 3], b: [f32; 3], t: f32) -> [f32; 3] {
210 [
211 a[0] + (b[0] - a[0]) * t,
212 a[1] + (b[1] - a[1]) * t,
213 a[2] + (b[2] - a[2]) * t,
214 ]
215}
216
217pub fn clampf(x: f32, min: f32, max: f32) -> f32 {
219 if x < min { min } else if x > max { max } else { x }
220}
221
222pub fn lerpf(a: f32, b: f32, t: f32) -> f32 {
224 a + (b - a) * t
225}
226
227pub fn saturate(x: f32) -> f32 {
229 clampf(x, 0.0, 1.0)
230}
231
232pub fn smoothstep(edge0: f32, edge1: f32, x: f32) -> f32 {
234 let t = saturate((x - edge0) / (edge1 - edge0));
235 t * t * (3.0 - 2.0 * t)
236}