1use crate::opengl::gl_unbind_array_buffer;
2use crate::opengl::gl_draw_arrays;
3use crate::opengl::gl_unbind_element_buffer;
4use crate::opengl::gl_draw_elements;
5pub use nalgebra_glm as glm;
6
7pub mod sys;
8pub mod opengl;
9pub mod buffers;
10pub mod graphics;
11pub mod vertex;
12
13use sys::*;
14use buffers::*;
15use graphics::*;
16use vertex::*;
17use opengl::{opengl, gl};
18
19const CLIP_NEAR_DEFAULT: f32 = 0.1;
20const CLIP_FAR_DEFAULT: f32 = 1000.;
21
22pub trait Renderable {
38 fn draw(&self, renderer: &Renderer);
39}
40
41#[derive(Copy, Clone, Debug, Default)]
42struct ProjectionInfo {
43 width: f32, height: f32,
44 fov_deg: f32, clip_near: f32, clip_far: f32
45}
46
47impl ProjectionInfo {
48 pub fn aspect(&self) -> f32 { self.width / self.height }
49 pub fn fov_rad(&self) -> f32 { sys::radians(self.fov_deg) }
50
51 pub fn to_matrix(&self) -> glm::Mat4 {
52 glm::perspective(self.aspect(), self.fov_rad(), self.clip_near, self.clip_far)
53 }
54}
55
56pub struct Renderer {
57 pub camera: FlyCamera,
58
59 draw_vao: VAO,
60 quad_buffer: VertexBuffer,
61 instanced_mat_buffer: VertexBuffer,
62
63 shader: Shader,
64 instanced_shader: Shader,
65
66 default_texture: Texture,
67 projection: glm::Mat4,
68 projection_info: ProjectionInfo,
69}
70
71impl Renderer {
75
76 pub const DEFAULT_FOV: f32 = 45.;
77 pub const U_PROJECTION: &'static str = "u_projection";
78 pub const U_VIEW: &'static str = "u_view";
79 pub const U_MODEL: &'static str = "u_model";
80
81 pub fn new(width: u32, height: u32) -> Self {
82 unsafe {
83 let gl = opengl();
84 gl.Viewport(0, 0, width as i32, height as i32);
85 gl.Enable(gl::DEPTH_TEST);
86 gl.Enable(gl::BLEND);
87 gl.BlendFunc(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA);
88 };
89 let projection_info = ProjectionInfo {
90 width: width as f32, height: height as f32,
91 fov_deg: Self::DEFAULT_FOV, clip_near: 0.1, clip_far: 100.
92 };
93
94 let projection = projection_info.to_matrix();
95
96 let camera = {
97 let mut c = FlyCamera::new();
98 c.position.z = -3.;
99 c.look_direction.z = 3.;
100 c
101 };
102
103 let shader = Shader::default();
104 let instanced_shader = Shader::default_instanced();
105 let default_texture = Texture::new_blank();
106
107 let quad_buffer = VertexBuffer::new(&sys::Quad::default_verts(), DrawUsage::Dynamic);
108 let instanced_mat_buffer = VertexBuffer::zeroed::<glm::Mat4>(2, DrawUsage::Dynamic, DrawPrimitive::Triangles);
109
110 let draw_vao = VAO::new();
111
112 Renderer {
113 camera, draw_vao, quad_buffer,
114 instanced_mat_buffer, shader,
115 instanced_shader,
116 default_texture, projection,
117 projection_info
118 }
119 }
120
121 pub fn set_viewport(&mut self, rect: &Rectf) {
122 self.projection_info.width = rect.w;
123 self.projection_info.height = rect.h;
124 self.projection = self.projection_info.to_matrix();
125 unsafe { opengl().Viewport(rect.x as i32, rect.y as i32, rect.w as i32, rect.h as i32) }
126 }
127
128 pub fn set_projection(&mut self, width: f32, height: f32, fov_deg: f32) {
130 self.projection_info = ProjectionInfo {
131 width, height, fov_deg, ..self.projection_info
132 };
133 self.projection = self.projection_info.to_matrix();
134 }
135
136 pub fn begin_draw_texture(rt: &RenderTexture) {
137 FrameBuffer::apply(&rt.frame_buffer);
138 }
139 pub fn end_draw_texture() {
140 FrameBuffer::unbind();
141 }
142
143 pub fn draw<T>(&self, renderable: &T) where T: Renderable {
144 renderable.draw(self);
145 }
146
147 pub fn draw_mesh(&self, mesh: &Mesh) {
148 let shader = match mesh.shader.as_ref() {
149 Some(s) => s,
150 None => {
151 self.shader.set_uniform_matrix("u_projection", &self.projection);
152 self.shader.set_uniform_matrix("u_view", &self.camera.view());
153 self.shader.set_uniform_matrix("u_model", mesh.transform.model());
154 &self.shader
155 }
156 };
157
158 shader.apply();
159
160 self.draw_vao.set_buffer_layout(&mesh.buffer);
161
162 let texture = mesh.texture.as_ref().unwrap_or(&self.default_texture);
163 texture.apply();
164
165 if let Some(e) = mesh.indices.as_ref() {
166 self.draw_elements(&e, mesh.buffer.draw_prim);
167 } else {
168 self.draw_arrays(0, mesh.buffer.vert_count(), mesh.buffer.draw_prim);
169 }
170
171 }
172
173 pub fn draw_quad<'b, T>(&self, q: &Quad, texture: T) where T: Into<Option<&'b Texture>> {
174 let texture = texture.into().unwrap_or(&self.default_texture);
175 texture.apply();
176
177 self.draw_vao.set_buffer_layout(&self.quad_buffer);
178
179 self.quad_buffer.write(&q.verts, 0);
180
181 self.draw_arrays(0, self.quad_buffer.vert_count(), DrawPrimitive::TriangleStrip);
182 }
183
184 pub fn draw_buffer<'b, T>(&self, buffer: &VertexBuffer, first_vertex: u32, texture: T) where T: Into<Option<&'b Texture>> {
185 let texture = texture.into().unwrap_or(&self.default_texture);
186 texture.apply();
187
188 self.draw_vao.set_buffer_layout(&buffer);
189
190 self.draw_arrays(first_vertex, buffer.vert_count(), buffer.draw_prim);
191 }
193
194 pub fn draw_indexed_buffer<'b, T>(&self, buffer: &VertexBuffer, ebo: &ElementBuffer, texture: T) where T: Into<Option<&'b Texture>> {
214 let texture = texture.into().unwrap_or(&self.default_texture);
215 texture.apply();
216
217 self.draw_vao.set_buffer_layout(&buffer);
218
219 self.draw_elements(&ebo, buffer.draw_prim);
220 }
221
222 pub fn clear_black(&self) {
223 self.clear(0., 0., 0., 1.);
224 }
225
226 pub fn use_default_shader<'b, T>(&self, xform: T) where T: Into<Option<&'b Transform>> {
227 if let Some(xform) = xform.into() {
228 self.shader.set_uniform_matrix("u_projection", &self.projection);
229 self.shader.set_uniform_matrix("u_view", &self.camera.view());
230 self.shader.set_uniform_matrix("u_model", xform.model());
231 } else {
232 self.shader.set_uniform_matrix("u_projection", &glm::Mat4::identity());
233 self.shader.set_uniform_matrix("u_view", &glm::Mat4::identity());
234 self.shader.set_uniform_matrix("u_model", &glm::Mat4::identity());
235 }
236
237 self.shader.apply(); }
240
241 pub fn clear(&self, r: f32, g: f32, b: f32, a: f32) {
242 unsafe {
243 opengl().ClearColor(r, g, b, a);
244 opengl().Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
245 }
246 }
247
248 pub fn projection(&self) -> &glm::Mat4 { &self.projection }
249 pub fn view(&self) -> glm::Mat4 { self.camera.view() }
250
251 pub fn set_current(&self) {
255 self.draw_vao.apply();
256 }
257
258 fn draw_arrays(&self, start: u32, vert_count: u32, prim: DrawPrimitive) {
259 self.draw_vao.apply();
260 gl_draw_arrays(start, vert_count, prim);
261 }
262
263 fn draw_elements(&self, ebo: &ElementBuffer, prim: DrawPrimitive) {
264 self.draw_vao.apply();
265 ebo.apply();
266 gl_draw_elements(ebo.count, prim);
267 ebo.unbind();
268 }
269}
270
271
272pub struct FlyCamera {
273 pub position: glm::Vec3,
274 pub look_direction: glm::Vec3,
275 pub rotation: glm::Vec3,
276
277 pub speed: f32,
278 pub sensitivity: f32,
279}
280
281impl FlyCamera {
282
283 pub fn new() -> Self {
284 FlyCamera::default()
285 }
286
287 pub fn view(&self) -> glm::Mat4 {
288 glm::look_at(&self.position, &self.target(), &UP_VECTOR.into())
289 }
290
291 pub fn target(&self) -> glm::Vec3 {
292 self.position + self.look_direction
293 }
294
295 pub fn move_forward(&mut self, delta_time: f32) {
296 self.position += self.speed * self.look_direction * delta_time;
297 }
298
299 pub fn move_backward(&mut self, delta_time: f32) {
300 self.position -= self.speed * self.look_direction * delta_time;
301 }
302
303 pub fn move_left(&mut self, delta_time: f32) {
304 let v: glm::Vec3 = self.look_direction.cross(&UP_VECTOR.into());
305 self.position -= glm::normalize(&v) * self.speed * delta_time;
306 }
307
308 pub fn move_right(&mut self, delta_time: f32) {
309 let v = self.look_direction.cross(&UP_VECTOR.into());
310 self.position += glm::normalize(&v) * self.speed * delta_time;
311 }
312
313 pub fn look_towards(&mut self, offset: &glm::Vec3) {
314 let delta = offset * self.sensitivity;
315
316 self.rotation += glm::vec3(delta.x, delta.y, 0.);
317 self.rotation.y = sys::clamp_s(self.rotation.y, -89., 89.);
318 let frontx = f32::cos(radians(self.rotation.x)) * f32::cos(radians(self.rotation.y));
319 let fronty = f32::sin(radians(self.rotation.y));
320 let frontz = f32::sin(radians(self.rotation.x)) * f32::cos(radians(self.rotation.y));
321
322 self.look_direction = glm::normalize(&glm::vec3(frontx, fronty, frontz));
323 }
324}
325
326impl Default for FlyCamera {
327
328 fn default() -> Self {
329 let zvec = glm::vec3(0., 0., 0.);
330 FlyCamera {
331 position: zvec,
332 look_direction: zvec,
333 rotation: zvec,
334 speed: 0., sensitivity: 0.
335 }
336 }
337}