globject_rs/
lib.rs

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), // Due to doc, won't return `glfw::InitError::AlreadyInitialized`
142			};
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}