1
2#![allow(dead_code)]
3
4pub mod glbuffer;
6
7pub mod glshader;
9
10pub mod glcmdbuf;
12
13pub mod gltexture;
15
16pub mod glframebuffer;
18
19pub mod buffervec;
21
22pub mod mesh;
24
25pub mod material;
27
28pub mod pipeline;
30
31pub mod meshset;
33
34pub mod common;
36
37extern crate nalgebra_glm as glm;
38
39pub 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 GLCoreError(GLCoreError),
84 ShaderError(ShaderError),
85 PipelineError(PipelineError),
86 }
87
88 #[derive(Debug)]
89 struct Renderer {
90 pipeline: Rc<Pipeline<MyVertex, UnusedType>>,
91 shader: Rc<Shader>,
92 mesh: Rc<dyn GenericMeshWithMaterial>,
93 }
94
95 #[derive(Debug)]
96 struct AppInstance {
97 renderer: Option<Renderer>,
98 glcore: Rc<GLCore>,
99 events: GlfwReceiver<(f64, WindowEvent)>,
100 window: PWindow,
101 glfw: Glfw,
102 }
103
104 impl From<GLCoreError> for AppError {
105 fn from(val: GLCoreError) -> Self {
106 Self::GLCoreError(val)
107 }
108 }
109
110 impl From<ShaderError> for AppError {
111 fn from(val: ShaderError) -> Self {
112 Self::ShaderError(val)
113 }
114 }
115
116 impl From<PipelineError> for AppError {
117 fn from(val: PipelineError) -> Self {
118 Self::PipelineError(val)
119 }
120 }
121
122 impl Renderer {
123 fn new(glcore: Rc<GLCore>) -> Result<Self, AppError> {
124 let vertices = [
125 MyVertex{position: Vec2::new(-1.0, -1.0)},
126 MyVertex{position: Vec2::new( 1.0, -1.0)},
127 MyVertex{position: Vec2::new(-1.0, 1.0)},
128 MyVertex{position: Vec2::new( 1.0, 1.0)},
129 ];
130 let elements = [
131 0u8, 1u8, 2u8,
132 1u8, 3u8, 2u8,
133 ];
134 let vertex_buffer = Buffer::new(glcore.clone(), BufferTarget::ArrayBuffer, size_of_val(&vertices), BufferUsage::StaticDraw, vertices.as_ptr() as *const c_void)?;
135 let mut vertex_buffer = BufferVecStatic::<MyVertex>::new(glcore.clone(), vertex_buffer);
136 vertex_buffer.resize(4, MyVertex::default())?;
137 let element_buffer = Buffer::new(glcore.clone(), BufferTarget::ElementArrayBuffer, size_of_val(&elements), BufferUsage::StaticDraw, elements.as_ptr() as *const c_void)?;
138 let mut element_buffer = BufferVecStatic::<u8>::new(glcore.clone(), element_buffer);
139 element_buffer.resize(6, 0u8)?;
140 let mesh = StaticMesh::<MyVertex, u8, UnusedType, UnusedType>::new(PrimitiveMode::Triangles, vertex_buffer, Some(element_buffer), None, None);
141 let mesh = Rc::new(MeshWithMaterial::new(mesh, Rc::new(MaterialLegacy::default())));
142 let mesh: Rc<dyn GenericMeshWithMaterial> = mesh;
143 let shader = Rc::new(Shader::new(glcore.clone(),
144 Some("
145#version 330\n
146
147in vec2 position;
148
149void main()
150{
151 gl_Position = vec4(position, 0.0, 1.0);
152}
153 "),
154 None,
155 Some( "#version 330\n
157
158#define LINEAR_ROTATION\n
159
160#define WEIGHT (3.0 / iResolution.x)\n
161const vec3 RED = vec3(1.0,0.0,0.0);
162const vec3 GREEN = vec3(0.0,1.0,0.0);
163const vec3 BLUE = vec3(0.0,0.8,1.0);
164const vec3 WHITE = vec3(1.0,1.0,0.97);
165const vec3 YELLOW = vec3(1.0,1.0,0.0);
166
167uniform vec3 iResolution;
168uniform float iTime;
169
170vec2 fragCoord = gl_FragCoord.xy;
171out vec4 Color;
172
173/* rasterize functions */
174float line(vec2 p, vec2 p0, vec2 p1, float w) {
175 vec2 d = p1 - p0;
176 float t = clamp(dot(d,p-p0) / dot(d,d), 0.0,1.0);
177 vec2 proj = p0 + d * t;
178 float dist = length(p - proj);
179 dist = 1.0/dist*WEIGHT*w;
180 return min(dist*dist,1.0);
181}
182float circle(vec2 p, vec2 c, float r, float w) {
183 float dist = abs(length(p - c)) + r;
184 dist = 1.0/dist*WEIGHT*w;
185 return min(dist*dist,1.0);
186}
187
188/* matrices */
189mat4 getRotMatrix(vec3 a) {
190 vec3 s = sin(a);
191 vec3 c = cos(a);
192 mat4 ret;
193 ret[0] = vec4(c.y*c.z,c.y*s.z,-s.y,0.0);
194 ret[1] = vec4(s.x*s.y*c.z-c.x*s.z,s.x*s.y*s.z+c.x*c.z,s.x*c.y,0.0);
195 ret[2] = vec4(c.x*s.y*c.z+s.x*s.z,c.x*s.y*s.z-s.x*c.z,c.x*c.y,0.0);
196 ret[3] = vec4(0.0,0.0,0.0,1.0);
197 return ret;
198}
199mat4 getPosMatrix(vec3 p) {
200 mat4 ret;
201 ret[0] = vec4(1.0,0.0,0.0,p.x);
202 ret[1] = vec4(0.0,1.0,0.0,p.y);
203 ret[2] = vec4(0.0,0.0,1.0,p.z);
204 ret[3] = vec4(0.0,0.0,0.0,1.0);
205 return ret;
206}
207
208/* utils */
209vec3 mix3(vec3 a, vec3 b, vec3 c, float t) {
210 if(t>0.5) return mix(b,c,t*2.0-1.0);
211 else return mix(a,b,t*2.0);
212}
213vec3 fragment(vec3 p) {
214 float t = sin(p.x*0.8+iTime*0.5)*0.5+0.5;
215 float fog = min(pow(p.z,3.0)*400.0,1.0);
216 return mix3(RED,GREEN,BLUE,t) * fog;
217}
218
219void main() {
220 vec2 uv = fragCoord.xy / iResolution.xy;
221 uv = uv * 2.0 - 1.0;
222 uv.x *= iResolution.x / iResolution.y;
223 /* uv = uv * (1.0 + pow(length(uv)*0.4,0.5)) * 0.6; */
224
225 float line_width = 0.4;
226 float time = iTime * 0.31415;
227 vec3 c = vec3(mix(vec3(0.19,0.13,0.1),vec3(1.0), 0.5*pow(length(uv)*0.5,2.0)));
228 mat4 cam = getPosMatrix(vec3(0.0,0.0,10.0));
229
230#ifdef LINEAR_ROTATION
231 mat4 rot = getRotMatrix(vec3(time,time*0.86,time*0.473));
232#else
233 float p = 0.08;
234 mat4 rot = getRotMatrix(vec3(time +sin(time*30.0)*p,
235 time*0.860 +sin(time*20.0)*p*1.24,
236 time*0.473 +sin(time*10.0)*p));
237#endif
238
239 vec3 instances[18];
240 instances[0] = vec3( 0.0, 0.0,-1.0);
241 instances[1] = vec3(-1.0, 0.0,-1.0);
242 instances[2] = vec3( 1.0, 0.0,-1.0);
243 instances[3] = vec3( 0.0, 1.0,-1.0);
244 instances[4] = vec3( 0.0,-1.0,-1.0);
245 instances[5] = vec3(-1.0, 0.0, 0.0);
246 instances[6] = vec3( 1.0, 0.0, 0.0);
247 instances[7] = vec3( 0.0, 1.0, 0.0);
248 instances[8] = vec3( 0.0,-1.0, 0.0);
249 instances[9] = vec3(-1.0,-1.0, 0.0);
250 instances[10] = vec3( 1.0, 1.0, 0.0);
251 instances[11] = vec3(-1.0, 1.0, 0.0);
252 instances[12] = vec3( 1.0,-1.0, 0.0);
253 instances[13] = vec3( 0.0, 0.0, 1.0);
254 instances[14] = vec3(-1.0, 0.0, 1.0);
255 instances[15] = vec3( 1.0, 0.0, 1.0);
256 instances[16] = vec3( 0.0, 1.0, 1.0);
257 instances[17] = vec3( 0.0,-1.0, 1.0);
258
259 /* box pipeline */
260 for(int dip = 0; dip < 18; dip++) {
261
262 /* input assembly */
263 vec3 vert[8];
264 vert[0] = vec3(-1.0,-1.0, 1.0);
265 vert[1] = vec3(-1.0, 1.0, 1.0);
266 vert[2] = vec3( 1.0, 1.0, 1.0);
267 vert[3] = vec3( 1.0,-1.0, 1.0);
268 vert[4] = vec3(-1.0,-1.0,-1.0);
269 vert[5] = vec3(-1.0, 1.0,-1.0);
270 vert[6] = vec3( 1.0, 1.0,-1.0);
271 vert[7] = vec3( 1.0,-1.0,-1.0);
272
273 /* vertex processing */
274 mat4 pos = getPosMatrix(instances[dip] * 4.0);
275 mat4 mat = pos * rot * cam;
276
277 for(int i = 0; i < 8; i++) {
278
279 /* transform */
280 vert[i] = (vec4(vert[i],1.0) * mat).xyz;
281
282 /* perspective */
283 vert[i].z = 1.0 / vert[i].z;
284 vert[i].xy *= vert[i].z;
285 }
286
287 /* primitive assembly and rasterize */
288 float i;
289 i = line(uv,vert[0].xy,vert[1].xy,line_width);
290 i += line(uv,vert[1].xy,vert[2].xy,line_width);
291 i += line(uv,vert[2].xy,vert[3].xy,line_width);
292 i += line(uv,vert[3].xy,vert[0].xy,line_width);
293 i += line(uv,vert[4].xy,vert[5].xy,line_width);
294 i += line(uv,vert[5].xy,vert[6].xy,line_width);
295 i += line(uv,vert[6].xy,vert[7].xy,line_width);
296 i += line(uv,vert[7].xy,vert[4].xy,line_width);
297 i += line(uv,vert[0].xy,vert[4].xy,line_width);
298 i += line(uv,vert[1].xy,vert[5].xy,line_width);
299 i += line(uv,vert[2].xy,vert[6].xy,line_width);
300 i += line(uv,vert[3].xy,vert[7].xy,line_width);
301 c += fragment(vert[0]) * min(i,1.0);
302 }
303
304 instances[0] = vec3(-1.0, 1.0,-1.0);
305 instances[1] = vec3( 1.0, 1.0,-1.0);
306 instances[2] = vec3(-1.0,-1.0,-1.0);
307 instances[3] = vec3( 1.0,-1.0,-1.0);
308 instances[4] = vec3(-1.0, 1.0, 1.0);
309 instances[5] = vec3( 1.0, 1.0, 1.0);
310 instances[6] = vec3(-1.0,-1.0, 1.0);
311 instances[7] = vec3( 1.0,-1.0, 1.0);
312
313 /* cicle pipeline */
314 for(int dip = 0; dip < 8; dip++) {
315
316 /* input assembly */
317 vec3 vert = vec3(0.0);
318
319 /* vertex processing */
320 mat4 pos = getPosMatrix(instances[dip] * 4.0);
321 mat4 mat = pos * rot * cam;
322
323 /* transform */
324 vert = (vec4(vert,1.0) * mat).xyz;
325
326 /* perspective */
327 vert.z = 1.0 / vert.z;
328 vert.xy *= vert.z;
329
330 /* rasterize */
331 c += fragment(vert) * circle(uv,vert.xy,-vert.z,line_width);
332 }
333
334 /* fragment */
335 Color = vec4(c, 1.0);
336}
337 ")
338 )?);
339 let pipeline = Rc::new(Pipeline::new(glcore.clone(), mesh.clone(), shader.clone())?);
340 Ok(Self {
341 mesh,
342 shader,
343 pipeline,
344 })
345 }
346
347 fn render(&self, glcore: &GLCore, frame_time: f64, width: u32, height: u32) -> Result<(), AppError> {
348 glcore.glViewport(0, 0, width as i32, height as i32)?;
349 glcore.glClearColor(0.0, 0.3, 0.5, 1.0)?;
350 glcore.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)?;
351
352 let shader = self.shader.use_program()?;
353 let time = frame_time as f32;
354 let _ = shader.set_uniform("iResolution", &Vec3::new(width as f32, height as f32, 0.0));
355 let _ = shader.set_uniform("iTime", &time);
356 shader.unuse();
357
358 let p_bind = self.pipeline.bind()?;
359 p_bind.draw(None)?;
360 p_bind.unbind();
361 Ok(())
362 }
363 }
364
365 impl AppInstance {
366 pub fn new() -> Result<Self, AppError> {
367 let mut glfw = match glfw::init_no_callbacks() {
368 Ok(glfw) => glfw,
369 Err(_) => return Err(AppError::GLFWInitErr), };
371 let (mut window, events) = glfw.create_window(1024, 768, "GLFW Window", glfw::WindowMode::Windowed).ok_or(AppError::GLFWCreateWindowFailed)?;
372 window.set_key_polling(true);
373 window.make_current();
374 glfw.set_swap_interval(SwapInterval::Adaptive);
375 let glcore = Rc::new(GLCore::new(|proc_name|window.get_proc_address(proc_name))?);
376 let renderer = Some(Renderer::new(glcore.clone())?);
377 Ok(Self {
378 renderer,
379 glcore,
380 events,
381 window,
382 glfw,
383 })
384 }
385
386 pub fn run(&mut self, timeout: Option<f64>) -> ExitCode {
387 let start_debug_time = self.glfw.get_time();
388 while !self.window.should_close() {
389 let time_cur_frame = self.glfw.get_time();
390
391 if let Some(renderer) = self.renderer.as_ref() {
392 let (width, height) = self.window.get_framebuffer_size();
393 renderer.render(&self.glcore, time_cur_frame, width as u32, height as u32).unwrap();
394 self.window.swap_buffers();
395 }
396
397 self.glfw.poll_events();
398 for (_, event) in glfw::flush_messages(&self.events) {
399 match event {
400 glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
401 self.window.set_should_close(true)
402 }
403 _ => {}
404 }
405 }
406
407 if let Some(timeout) = timeout {
408 if time_cur_frame - start_debug_time >= timeout {
409 self.window.set_should_close(true)
410 }
411 }
412 }
413
414 ExitCode::from(0)
415 }
416 }
417
418 #[test]
419 fn test_glfw() -> ExitCode {
420 const DEBUG_TIME: f64 = 10.0;
421 let mut test_app = match AppInstance::new() {
422 Ok(app) => app,
423 Err(e) => {
424 eprintln!("GLFW App Initialize failed: {:?}", e);
425 return ExitCode::from(2)
426 }
427 };
428 test_app.run(Some(DEBUG_TIME))
429 }
430}