1
2#![allow(dead_code)]
3
4mod glbuffer;
5mod glshader;
6mod glcmdbuf;
7mod gltexture;
8mod glframebuffer;
9mod buffervec;
10mod mesh;
11mod material;
12mod pipeline;
13mod meshset;
14mod common;
15
16extern crate nalgebra_glm as glm;
17
18pub mod prelude {
19 pub use crate::glbuffer::*;
20 pub use crate::glshader::*;
21 pub use crate::glcmdbuf::*;
22 pub use crate::gltexture::*;
23 pub use crate::glframebuffer::*;
24 pub use crate::buffervec::*;
25 pub use crate::mesh::*;
26 pub use crate::material::*;
27 pub use crate::pipeline::*;
28 pub use crate::meshset::*;
29 pub use crate::common::*;
30 pub use crate::derive_vertex_type;
31 pub use glm::*;
32 pub use struct_iterable::Iterable;
33 pub use glcore::*;
34 pub use half::f16;
35}
36
37pub use prelude::*;
38
39#[cfg(test)]
40mod tests {
41 use std::{
42 ffi::c_void,
43 mem::size_of_val,
44 process::ExitCode,
45 rc::Rc,
46 };
47 use super::prelude::*;
48 use glfw::*;
49
50 derive_vertex_type! {
51 pub struct MyVertex {
52 position: Vec2,
53 }
54 }
55
56 #[derive(Debug)]
57 enum AppError {
58 GLFWInitErr,
59 GLFWCreateWindowFailed,
60 GLFWErr(glfw::Error),
61 }
62
63 #[derive(Debug)]
64 struct Renderer {
65 pipeline: Rc<Pipeline<MyVertex, UnusedType, StaticMesh, MaterialLegacy>>,
66 shader: Rc<Shader>,
67 mesh: Rc<MeshWithMaterial<StaticMesh, MaterialLegacy>>,
68 }
69
70 #[derive(Debug)]
71 struct AppInstance {
72 renderer: Option<Renderer>,
73 glcore: Rc<GLCore>,
74 events: GlfwReceiver<(f64, WindowEvent)>,
75 window: PWindow,
76 glfw: Glfw,
77 }
78
79 impl Renderer {
80 fn new(glcore: Rc<GLCore>) -> Self {
81 let vertices = [
82 MyVertex{position: Vec2::new(-1.0, -1.0)},
83 MyVertex{position: Vec2::new( 1.0, -1.0)},
84 MyVertex{position: Vec2::new(-1.0, 1.0)},
85 MyVertex{position: Vec2::new( 1.0, 1.0)},
86 ];
87 let elements = [
88 0u8, 1u8, 2u8,
89 1u8, 3u8, 2u8,
90 ];
91 let vertex_buffer = Buffer::new(glcore.clone(), BufferTarget::ArrayBuffer, size_of_val(&vertices), BufferUsage::StaticDraw, vertices.as_ptr() as *const c_void);
92 let element_buffer = Buffer::new(glcore.clone(), BufferTarget::ElementArrayBuffer, size_of_val(&elements), BufferUsage::StaticDraw, elements.as_ptr() as *const c_void);
93 let element_buffer = ElementBuffer{buffer: element_buffer, element_type: ElementType::U8};
94 let mesh = StaticMesh::new(PrimitiveMode::Triangles, vertex_buffer, vertices.len(), Some(element_buffer), None, 0, None);
95 let mesh = Rc::new(MeshWithMaterial::new(mesh, Rc::new(MaterialLegacy::default())));
96 let shader = Rc::new(Shader::new(glcore.clone(),
97 Some("
98#version 330\n
99
100in vec2 position;
101
102void main()
103{
104 gl_Position = vec4(position, 0.0, 1.0);
105}
106 "),
107 None,
108 Some("
109#version 330\n
110
111out vec4 Color;
112
113void main()
114{
115 Color = vec4(0.0, 0.0, 0.5, 1.0);
116}
117 ")
118 ).unwrap());
119 let pipeline = Rc::new(Pipeline::new(glcore.clone(), mesh.clone(), shader.clone()));
120 Self {
121 mesh,
122 shader,
123 pipeline,
124 }
125 }
126
127 fn render(&self, glcore: &GLCore) {
128 glcore.glClearColor(0.0, 0.3, 0.5, 1.0);
129 glcore.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
130
131 let p_bind = self.pipeline.bind();
132 p_bind.draw(None);
133 p_bind.unbind();
134 }
135 }
136
137 impl AppInstance {
138 pub fn new() -> Result<Self, AppError> {
139 let mut glfw = match glfw::init_no_callbacks() {
140 Ok(glfw) => glfw,
141 Err(_) => return Err(AppError::GLFWInitErr), };
143 let (mut window, events) = glfw.create_window(1024, 768, "GLFW Window", glfw::WindowMode::Windowed).ok_or(AppError::GLFWCreateWindowFailed)?;
144 window.set_key_polling(true);
145 window.make_current();
146 glfw.set_swap_interval(SwapInterval::Adaptive);
147 let glcore = Rc::new(GLCore::new(|proc_name|window.get_proc_address(proc_name)));
148 let renderer = Some(Renderer::new(glcore.clone()));
149 Ok(Self {
150 renderer,
151 glcore,
152 events,
153 window,
154 glfw,
155 })
156 }
157
158 pub fn run(&mut self, timeout: Option<f64>) -> ExitCode {
159 let start_debug_time = self.glfw.get_time();
160 while !self.window.should_close() {
161 let time_cur_frame = self.glfw.get_time();
162
163 if let Some(renderer) = self.renderer.as_ref() {
164 renderer.render(&self.glcore);
165 self.window.swap_buffers();
166 }
167
168 self.glfw.poll_events();
169 for (_, event) in glfw::flush_messages(&self.events) {
170 match event {
171 glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
172 self.window.set_should_close(true)
173 }
174 _ => {}
175 }
176 }
177
178 if let Some(timeout) = timeout {
179 if time_cur_frame - start_debug_time >= timeout {
180 self.window.set_should_close(true)
181 }
182 }
183 }
184
185 ExitCode::from(0)
186 }
187 }
188
189 #[test]
190 fn test_glfw() -> ExitCode {
191 const DEBUG_TIME: f64 = 10.0;
192 let mut test_app = match AppInstance::new() {
193 Ok(app) => app,
194 Err(e) => {
195 eprintln!("GLFW App Initialize failed: {:?}", e);
196 return ExitCode::from(2)
197 }
198 };
199 test_app.run(Some(DEBUG_TIME))
200 }
201}