#[macro_use] extern crate glium; use glium::Surface; #[path = "../book/tuto-07-teapot.rs"] mod teapot; mod support; use support::view_matrix; fn main() { let event_loop = glium::winit::event_loop::EventLoop::builder() .build() .expect("event loop building"); let (window, display) = glium::backend::glutin::SimpleWindowBuilder::new() .with_title("Glium tutorial #13") .build(&event_loop); let positions = glium::VertexBuffer::new(&display, &teapot::VERTICES).unwrap(); let normals = glium::VertexBuffer::new(&display, &teapot::NORMALS).unwrap(); let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &teapot::INDICES).unwrap(); let vertex_shader_src = r#" #version 150 in vec3 position; in vec3 normal; out vec3 v_normal; out vec3 v_position; uniform mat4 perspective; uniform mat4 view; uniform mat4 model; void main() { mat4 modelview = view * model; v_normal = transpose(inverse(mat3(modelview))) * normal; gl_Position = perspective * modelview * vec4(position, 1.0); v_position = gl_Position.xyz / gl_Position.w; } "#; let fragment_shader_src = r#" #version 150 in vec3 v_normal; in vec3 v_position; out vec4 color; uniform vec3 u_light; const vec3 ambient_color = vec3(0.2, 0.0, 0.0); const vec3 diffuse_color = vec3(0.6, 0.0, 0.0); const vec3 specular_color = vec3(1.0, 1.0, 1.0); void main() { float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0); vec3 camera_dir = normalize(-v_position); vec3 half_direction = normalize(normalize(u_light) + camera_dir); float specular = pow(max(dot(half_direction, normalize(v_normal)), 0.0), 16.0); color = vec4(ambient_color + diffuse * diffuse_color + specular * specular_color, 1.0); } "#; let program = glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None).unwrap(); #[allow(deprecated)] event_loop.run(move |ev, window_target| { match ev { glium::winit::event::Event::WindowEvent { event, .. } => match event { glium::winit::event::WindowEvent::CloseRequested => { window_target.exit(); }, // We now need to render everyting in response to a RedrawRequested event due to the animation glium::winit::event::WindowEvent::RedrawRequested => { let mut target = display.draw(); target.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0); let model = [ [0.01, 0.0, 0.0, 0.0], [0.0, 0.01, 0.0, 0.0], [0.0, 0.0, 0.01, 0.0], [0.0, 0.0, 2.0, 1.0f32] ]; let view = view_matrix(&[2.0, 1.0, 1.0], &[-2.0, -1.0, 1.0], &[0.0, 1.0, 0.0]); let perspective = { let (width, height) = target.get_dimensions(); let aspect_ratio = height as f32 / width as f32; let fov: f32 = 3.141592 / 3.0; let zfar = 1024.0; let znear = 0.1; let f = 1.0 / (fov / 2.0).tan(); [ [f * aspect_ratio , 0.0, 0.0 , 0.0], [ 0.0 , f , 0.0 , 0.0], [ 0.0 , 0.0, (zfar+znear)/(zfar-znear) , 1.0], [ 0.0 , 0.0, -(2.0*zfar*znear)/(zfar-znear), 0.0], ] }; let light = [1.4, 0.4, -0.7f32]; let params = glium::DrawParameters { depth: glium::Depth { test: glium::draw_parameters::DepthTest::IfLess, write: true, .. Default::default() }, //backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockWise, .. Default::default() }; target.draw((&positions, &normals), &indices, &program, &uniform! { model: model, view: view, perspective: perspective, u_light: light }, ¶ms).unwrap(); target.finish().unwrap(); }, // Because glium doesn't know about windows we need to resize the display // when the window's size has changed. glium::winit::event::WindowEvent::Resized(window_size) => { display.resize(window_size.into()); }, _ => (), }, // By requesting a redraw in response to a AboutToWait event we get continuous rendering. // For applications that only change due to user input you could remove this handler. glium::winit::event::Event::AboutToWait => { window.request_redraw(); }, _ => (), } }) .unwrap(); }