globject_rs/
lib.rs

1
2#![allow(dead_code)]
3
4/// The most basic OpenGL Buffer Object wrapping
5pub mod glbuffer;
6
7/// The most basic OpenGL Shader Program Object wrapping
8pub mod glshader;
9
10/// Definitions of `DrawArrayCommand`, `DrawElementsCommand` and `DispatchIndirectCommand`
11pub mod glcmdbuf;
12
13/// The most basic OpenGL Texture Object wrapping
14pub mod gltexture;
15
16/// The most basic OpenGL Framebuffer Object wrapping
17pub mod glframebuffer;
18
19/// An upper layer wrapping for `Buffer`, the `BufferVec` allows editing the buffer items easier than just to use the `Buffer`
20pub mod buffervec;
21
22/// An upper layer wrapping for `Mesh`, utilizing the trait `BufferVec` as the `Mesh` generic type of the vertex buffer, element buffer, instance buffer, and command buffer
23pub mod mesh;
24
25/// The material module provides `MaterialLegacy`, `MaterialPbr`, and the trait `Material`
26pub mod material;
27
28/// The most basic OpenGL Vertex Array Object that manages the pipeline from the data source in the array buffer to the shader attrib inputs
29pub mod pipeline;
30
31/// The mesh set for the complex mesh, each mesh subset has its name and material.
32pub mod meshset;
33
34/// The common module is to provide some miscellous utilities
35pub mod common;
36
37extern crate nalgebra_glm as glm;
38
39/// The prelude module provides all of the things you need to use
40pub mod prelude {
41	pub use crate::glbuffer::*;
42	pub use crate::glshader::*;
43	pub use crate::glcmdbuf::*;
44	pub use crate::gltexture::*;
45	pub use crate::glframebuffer::*;
46	pub use crate::buffervec::*;
47	pub use crate::mesh::*;
48	pub use crate::material::*;
49	pub use crate::pipeline::*;
50	pub use crate::meshset::*;
51	pub use crate::common::*;
52	pub use crate::derive_vertex_type;
53	pub use glm::*;
54	pub use struct_iterable::Iterable;
55	pub use glcore::*;
56	pub use half::f16;
57}
58
59pub use prelude::*;
60
61#[cfg(test)]
62mod tests {
63	use std::{
64		ffi::c_void,
65		mem::size_of_val,
66		process::ExitCode,
67		rc::Rc,
68	};
69	use super::prelude::*;
70	use glfw::*;
71
72	derive_vertex_type! {
73		pub struct MyVertex {
74			position: Vec2,
75		}
76	}
77
78	#[derive(Debug)]
79	enum AppError {
80		GLFWInitErr,
81		GLFWCreateWindowFailed,
82		GLFWErr(glfw::Error),
83	}
84
85	#[derive(Debug)]
86	struct Renderer {
87		pipeline: Rc<Pipeline<MyVertex, UnusedType>>,
88		shader: Rc<Shader>,
89		mesh: Rc<dyn GenericMeshWithMaterial>,
90	}
91
92	#[derive(Debug)]
93	struct AppInstance {
94		renderer: Option<Renderer>,
95		glcore: Rc<GLCore>,
96		events: GlfwReceiver<(f64, WindowEvent)>,
97		window: PWindow,
98		glfw: Glfw,
99	}
100
101	impl Renderer {
102		fn new(glcore: Rc<GLCore>) -> Self {
103			let vertices = [
104				MyVertex{position: Vec2::new(-1.0, -1.0)},
105				MyVertex{position: Vec2::new( 1.0, -1.0)},
106				MyVertex{position: Vec2::new(-1.0,  1.0)},
107				MyVertex{position: Vec2::new( 1.0,  1.0)},
108			];
109			let elements = [
110				0u8, 1u8, 2u8,
111				1u8, 3u8, 2u8,
112			];
113			let vertex_buffer = Buffer::new(glcore.clone(), BufferTarget::ArrayBuffer, size_of_val(&vertices), BufferUsage::StaticDraw, vertices.as_ptr() as *const c_void);
114			let mut vertex_buffer = BufferVecStatic::<MyVertex>::new(glcore.clone(), vertex_buffer);
115			vertex_buffer.resize(4, MyVertex::default());
116			let element_buffer = Buffer::new(glcore.clone(), BufferTarget::ElementArrayBuffer, size_of_val(&elements), BufferUsage::StaticDraw, elements.as_ptr() as *const c_void);
117			let mut element_buffer = BufferVecStatic::<u8>::new(glcore.clone(), element_buffer);
118			element_buffer.resize(6, 0u8);
119			let mesh = StaticMesh::<MyVertex, u8, UnusedType, UnusedType>::new(PrimitiveMode::Triangles, vertex_buffer, Some(element_buffer), None, None);
120			let mesh = Rc::new(MeshWithMaterial::new(mesh, Rc::new(MaterialLegacy::default())));
121			let mesh: Rc<dyn GenericMeshWithMaterial> = mesh;
122			let shader = Rc::new(Shader::new(glcore.clone(),
123				Some("
124#version 330\n
125
126in vec2 position;
127
128void main()
129{
130	gl_Position = vec4(position, 0.0, 1.0);
131}
132				"),
133				None,
134				Some("
135#version 330\n
136
137out vec4 Color;
138
139void main()
140{
141	Color = vec4(0.0, 0.0, 0.5, 1.0);
142}
143				")
144			).unwrap());
145			let pipeline = Rc::new(Pipeline::new(glcore.clone(), mesh.clone(), shader.clone()));
146			Self {
147				mesh,
148				shader,
149				pipeline,
150			}
151		}
152
153		fn render(&self, glcore: &GLCore) {
154			glcore.glClearColor(0.0, 0.3, 0.5, 1.0);
155			glcore.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
156
157			let p_bind = self.pipeline.bind();
158			p_bind.draw(None);
159			p_bind.unbind();
160		}
161	}
162
163	impl AppInstance {
164		pub fn new() -> Result<Self, AppError> {
165			let mut glfw = match glfw::init_no_callbacks() {
166				Ok(glfw) => glfw,
167				Err(_) => return Err(AppError::GLFWInitErr), // Due to doc, won't return `glfw::InitError::AlreadyInitialized`
168			};
169			let (mut window, events) = glfw.create_window(1024, 768, "GLFW Window", glfw::WindowMode::Windowed).ok_or(AppError::GLFWCreateWindowFailed)?;
170			window.set_key_polling(true);
171			window.make_current();
172			glfw.set_swap_interval(SwapInterval::Adaptive);
173			let glcore = Rc::new(GLCore::new(|proc_name|window.get_proc_address(proc_name)));
174			let renderer = Some(Renderer::new(glcore.clone()));
175			Ok(Self {
176				renderer,
177				glcore,
178				events,
179				window,
180				glfw,
181			})
182		}
183
184		pub fn run(&mut self, timeout: Option<f64>) -> ExitCode {
185			let start_debug_time = self.glfw.get_time();
186			while !self.window.should_close() {
187				let time_cur_frame = self.glfw.get_time();
188
189				if let Some(renderer) = self.renderer.as_ref() {
190					renderer.render(&self.glcore);
191					self.window.swap_buffers();
192				}
193
194				self.glfw.poll_events();
195				for (_, event) in glfw::flush_messages(&self.events) {
196					match event {
197						glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
198							self.window.set_should_close(true)
199						}
200						_ => {}
201					}
202				}
203
204				if let Some(timeout) = timeout {
205					if time_cur_frame - start_debug_time >= timeout {
206						self.window.set_should_close(true)
207					}
208				}
209			}
210
211			ExitCode::from(0)
212		}
213	}
214
215	#[test]
216	fn test_glfw() -> ExitCode {
217		const DEBUG_TIME: f64 = 10.0;
218		let mut test_app = match AppInstance::new() {
219			Ok(app) => app,
220			Err(e) => {
221				eprintln!("GLFW App Initialize failed: {:?}", e);
222				return ExitCode::from(2)
223			}
224		};
225		test_app.run(Some(DEBUG_TIME))
226	}
227}