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 }
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( "#version 330\n
136
137#define LINEAR_ROTATION\n
138
139#define WEIGHT (3.0 / iResolution.x)\n
140const vec3 RED = vec3(1.0,0.0,0.0);
141const vec3 GREEN = vec3(0.0,1.0,0.0);
142const vec3 BLUE = vec3(0.0,0.8,1.0);
143const vec3 WHITE = vec3(1.0,1.0,0.97);
144const vec3 YELLOW = vec3(1.0,1.0,0.0);
145
146uniform vec3 iResolution;
147uniform float iTime;
148
149vec2 fragCoord = gl_FragCoord.xy;
150out vec4 Color;
151
152/* rasterize functions */
153float line(vec2 p, vec2 p0, vec2 p1, float w) {
154 vec2 d = p1 - p0;
155 float t = clamp(dot(d,p-p0) / dot(d,d), 0.0,1.0);
156 vec2 proj = p0 + d * t;
157 float dist = length(p - proj);
158 dist = 1.0/dist*WEIGHT*w;
159 return min(dist*dist,1.0);
160}
161float circle(vec2 p, vec2 c, float r, float w) {
162 float dist = abs(length(p - c)) + r;
163 dist = 1.0/dist*WEIGHT*w;
164 return min(dist*dist,1.0);
165}
166
167/* matrices */
168mat4 getRotMatrix(vec3 a) {
169 vec3 s = sin(a);
170 vec3 c = cos(a);
171 mat4 ret;
172 ret[0] = vec4(c.y*c.z,c.y*s.z,-s.y,0.0);
173 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);
174 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);
175 ret[3] = vec4(0.0,0.0,0.0,1.0);
176 return ret;
177}
178mat4 getPosMatrix(vec3 p) {
179 mat4 ret;
180 ret[0] = vec4(1.0,0.0,0.0,p.x);
181 ret[1] = vec4(0.0,1.0,0.0,p.y);
182 ret[2] = vec4(0.0,0.0,1.0,p.z);
183 ret[3] = vec4(0.0,0.0,0.0,1.0);
184 return ret;
185}
186
187/* utils */
188vec3 mix3(vec3 a, vec3 b, vec3 c, float t) {
189 if(t>0.5) return mix(b,c,t*2.0-1.0);
190 else return mix(a,b,t*2.0);
191}
192vec3 fragment(vec3 p) {
193 float t = sin(p.x*0.8+iTime*0.5)*0.5+0.5;
194 float fog = min(pow(p.z,3.0)*400.0,1.0);
195 return mix3(RED,GREEN,BLUE,t) * fog;
196}
197
198void main() {
199 vec2 uv = fragCoord.xy / iResolution.xy;
200 uv = uv * 2.0 - 1.0;
201 uv.x *= iResolution.x / iResolution.y;
202 /* uv = uv * (1.0 + pow(length(uv)*0.4,0.5)) * 0.6; */
203
204 float line_width = 0.4;
205 float time = iTime * 0.31415;
206 vec3 c = vec3(mix(vec3(0.19,0.13,0.1),vec3(1.0), 0.5*pow(length(uv)*0.5,2.0)));
207 mat4 cam = getPosMatrix(vec3(0.0,0.0,10.0));
208
209#ifdef LINEAR_ROTATION
210 mat4 rot = getRotMatrix(vec3(time,time*0.86,time*0.473));
211#else
212 float p = 0.08;
213 mat4 rot = getRotMatrix(vec3(time +sin(time*30.0)*p,
214 time*0.860 +sin(time*20.0)*p*1.24,
215 time*0.473 +sin(time*10.0)*p));
216#endif
217
218 vec3 instances[18];
219 instances[0] = vec3( 0.0, 0.0,-1.0);
220 instances[1] = vec3(-1.0, 0.0,-1.0);
221 instances[2] = vec3( 1.0, 0.0,-1.0);
222 instances[3] = vec3( 0.0, 1.0,-1.0);
223 instances[4] = vec3( 0.0,-1.0,-1.0);
224 instances[5] = vec3(-1.0, 0.0, 0.0);
225 instances[6] = vec3( 1.0, 0.0, 0.0);
226 instances[7] = vec3( 0.0, 1.0, 0.0);
227 instances[8] = vec3( 0.0,-1.0, 0.0);
228 instances[9] = vec3(-1.0,-1.0, 0.0);
229 instances[10] = vec3( 1.0, 1.0, 0.0);
230 instances[11] = vec3(-1.0, 1.0, 0.0);
231 instances[12] = vec3( 1.0,-1.0, 0.0);
232 instances[13] = vec3( 0.0, 0.0, 1.0);
233 instances[14] = vec3(-1.0, 0.0, 1.0);
234 instances[15] = vec3( 1.0, 0.0, 1.0);
235 instances[16] = vec3( 0.0, 1.0, 1.0);
236 instances[17] = vec3( 0.0,-1.0, 1.0);
237
238 /* box pipeline */
239 for(int dip = 0; dip < 18; dip++) {
240
241 /* input assembly */
242 vec3 vert[8];
243 vert[0] = vec3(-1.0,-1.0, 1.0);
244 vert[1] = vec3(-1.0, 1.0, 1.0);
245 vert[2] = vec3( 1.0, 1.0, 1.0);
246 vert[3] = vec3( 1.0,-1.0, 1.0);
247 vert[4] = vec3(-1.0,-1.0,-1.0);
248 vert[5] = vec3(-1.0, 1.0,-1.0);
249 vert[6] = vec3( 1.0, 1.0,-1.0);
250 vert[7] = vec3( 1.0,-1.0,-1.0);
251
252 /* vertex processing */
253 mat4 pos = getPosMatrix(instances[dip] * 4.0);
254 mat4 mat = pos * rot * cam;
255
256 for(int i = 0; i < 8; i++) {
257
258 /* transform */
259 vert[i] = (vec4(vert[i],1.0) * mat).xyz;
260
261 /* perspective */
262 vert[i].z = 1.0 / vert[i].z;
263 vert[i].xy *= vert[i].z;
264 }
265
266 /* primitive assembly and rasterize */
267 float i;
268 i = line(uv,vert[0].xy,vert[1].xy,line_width);
269 i += line(uv,vert[1].xy,vert[2].xy,line_width);
270 i += line(uv,vert[2].xy,vert[3].xy,line_width);
271 i += line(uv,vert[3].xy,vert[0].xy,line_width);
272 i += line(uv,vert[4].xy,vert[5].xy,line_width);
273 i += line(uv,vert[5].xy,vert[6].xy,line_width);
274 i += line(uv,vert[6].xy,vert[7].xy,line_width);
275 i += line(uv,vert[7].xy,vert[4].xy,line_width);
276 i += line(uv,vert[0].xy,vert[4].xy,line_width);
277 i += line(uv,vert[1].xy,vert[5].xy,line_width);
278 i += line(uv,vert[2].xy,vert[6].xy,line_width);
279 i += line(uv,vert[3].xy,vert[7].xy,line_width);
280 c += fragment(vert[0]) * min(i,1.0);
281 }
282
283 instances[0] = vec3(-1.0, 1.0,-1.0);
284 instances[1] = vec3( 1.0, 1.0,-1.0);
285 instances[2] = vec3(-1.0,-1.0,-1.0);
286 instances[3] = vec3( 1.0,-1.0,-1.0);
287 instances[4] = vec3(-1.0, 1.0, 1.0);
288 instances[5] = vec3( 1.0, 1.0, 1.0);
289 instances[6] = vec3(-1.0,-1.0, 1.0);
290 instances[7] = vec3( 1.0,-1.0, 1.0);
291
292 /* cicle pipeline */
293 for(int dip = 0; dip < 8; dip++) {
294
295 /* input assembly */
296 vec3 vert = vec3(0.0);
297
298 /* vertex processing */
299 mat4 pos = getPosMatrix(instances[dip] * 4.0);
300 mat4 mat = pos * rot * cam;
301
302 /* transform */
303 vert = (vec4(vert,1.0) * mat).xyz;
304
305 /* perspective */
306 vert.z = 1.0 / vert.z;
307 vert.xy *= vert.z;
308
309 /* rasterize */
310 c += fragment(vert) * circle(uv,vert.xy,-vert.z,line_width);
311 }
312
313 /* fragment */
314 Color = vec4(c, 1.0);
315}
316 ")
317 ).unwrap());
318 let pipeline = Rc::new(Pipeline::new(glcore.clone(), mesh.clone(), shader.clone()));
319 Self {
320 mesh,
321 shader,
322 pipeline,
323 }
324 }
325
326 fn render(&self, glcore: &GLCore, frame_time: f64, width: u32, height: u32) {
327 glcore.glViewport(0, 0, width as i32, height as i32);
328 glcore.glClearColor(0.0, 0.3, 0.5, 1.0);
329 glcore.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
330
331 let shader = self.shader.use_program();
332 let time = frame_time as f32;
333 let _ = shader.set_uniform("iResolution", &Vec3::new(width as f32, height as f32, 0.0));
334 let _ = shader.set_uniform("iTime", &time);
335 shader.unuse();
336
337 let p_bind = self.pipeline.bind();
338 p_bind.draw(None);
339 p_bind.unbind();
340 }
341 }
342
343 impl AppInstance {
344 pub fn new() -> Result<Self, AppError> {
345 let mut glfw = match glfw::init_no_callbacks() {
346 Ok(glfw) => glfw,
347 Err(_) => return Err(AppError::GLFWInitErr), };
349 let (mut window, events) = glfw.create_window(1024, 768, "GLFW Window", glfw::WindowMode::Windowed).ok_or(AppError::GLFWCreateWindowFailed)?;
350 window.set_key_polling(true);
351 window.make_current();
352 glfw.set_swap_interval(SwapInterval::Adaptive);
353 let glcore = Rc::new(GLCore::new(|proc_name|window.get_proc_address(proc_name)));
354 let renderer = Some(Renderer::new(glcore.clone()));
355 Ok(Self {
356 renderer,
357 glcore,
358 events,
359 window,
360 glfw,
361 })
362 }
363
364 pub fn run(&mut self, timeout: Option<f64>) -> ExitCode {
365 let start_debug_time = self.glfw.get_time();
366 while !self.window.should_close() {
367 let time_cur_frame = self.glfw.get_time();
368
369 if let Some(renderer) = self.renderer.as_ref() {
370 let (width, height) = self.window.get_framebuffer_size();
371 renderer.render(&self.glcore, time_cur_frame, width as u32, height as u32);
372 self.window.swap_buffers();
373 }
374
375 self.glfw.poll_events();
376 for (_, event) in glfw::flush_messages(&self.events) {
377 match event {
378 glfw::WindowEvent::Key(Key::Escape, _, Action::Press, _) => {
379 self.window.set_should_close(true)
380 }
381 _ => {}
382 }
383 }
384
385 if let Some(timeout) = timeout {
386 if time_cur_frame - start_debug_time >= timeout {
387 self.window.set_should_close(true)
388 }
389 }
390 }
391
392 ExitCode::from(0)
393 }
394 }
395
396 #[test]
397 fn test_glfw() -> ExitCode {
398 const DEBUG_TIME: f64 = 10.0;
399 let mut test_app = match AppInstance::new() {
400 Ok(app) => app,
401 Err(e) => {
402 eprintln!("GLFW App Initialize failed: {:?}", e);
403 return ExitCode::from(2)
404 }
405 };
406 test_app.run(Some(DEBUG_TIME))
407 }
408}