#[macro_use] extern crate glium; use glium::Surface; use glium::index::PrimitiveType; mod support; #[test] fn multiple_buffers_source() { let display = support::build_display(); let buffer1 = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [ 1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [ 1.0, -1.0] }, ] ).unwrap() }; let buffer2 = { #[derive(Copy, Clone)] struct Vertex { color: [f32; 3], } implement_vertex!(Vertex, color); glium::VertexBuffer::new(&display, &[ Vertex { color: [1.0, 0.0, 0.0] }, Vertex { color: [1.0, 0.0, 0.0] }, Vertex { color: [1.0, 0.0, 0.0] }, Vertex { color: [1.0, 0.0, 0.0] }, ] ).unwrap() }; let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u16, 1, 2, 3]).unwrap(); let program = program!(&display, 110 => { vertex: " #version 110 attribute vec2 position; attribute vec3 color; varying vec3 v_color; void main() { gl_Position = vec4(position, 0.0, 1.0); v_color = color; } ", fragment: " #version 110 varying vec3 v_color; void main() { gl_FragColor = vec4(v_color, 1.0); } ", }, 100 => { vertex: " #version 100 attribute lowp vec2 position; attribute lowp vec3 color; varying lowp vec3 v_color; void main() { gl_Position = vec4(position, 0.0, 1.0); v_color = color; } ", fragment: " #version 100 varying lowp vec3 v_color; void main() { gl_FragColor = vec4(v_color, 1.0); } ", }).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw((&buffer1, &buffer2), &index_buffer, &program, &uniform!{}, &Default::default()).unwrap(); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn slice_draw_indices() { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); let display = support::build_display(); let program = program!(&display, 110 => { vertex: " #version 110 attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } ", }, 100 => { vertex: " #version 100 attribute lowp vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } ", }).unwrap(); let vb = glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] }, ]).unwrap(); let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList, &[0u16, 1, 2]).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(vb.slice(1 .. 4).unwrap(), &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default()).unwrap(); let data: Vec> = texture.read(); assert_eq!(data.last().unwrap()[0], (0, 0, 0, 0)); assert_eq!(data[0].last().unwrap(), &(255, 0, 0, 255)); display.assert_no_error(None); } #[test] fn slice_draw_noindices() { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); let display = support::build_display(); let program = program!(&display, 110 => { vertex: " #version 110 attribute vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } ", }, 100 => { vertex: " #version 100 attribute lowp vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } ", }).unwrap(); let vb = glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] }, ]).unwrap(); let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(vb.slice(1 .. 4).unwrap(), &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default()).unwrap(); let data: Vec> = texture.read(); assert_eq!(data.last().unwrap()[0], (0, 0, 0, 0)); assert_eq!(data[0].last().unwrap(), &(255, 0, 0, 255)); display.assert_no_error(None); } #[test] fn slice_draw_multiple() { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); #[derive(Copy, Clone)] struct Vertex2 { position2: [f32; 2], } implement_vertex!(Vertex2, position2); let display = support::build_display(); let program = program!(&display, 110 => { vertex: " #version 110 attribute vec2 position; attribute vec2 position2; void main() { if (position != position2) { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); } else { gl_Position = vec4(position, 0.0, 1.0); } } ", fragment: " #version 110 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } ", }, 100 => { vertex: " #version 100 attribute lowp vec2 position; attribute lowp vec2 position2; void main() { if (position != position2) { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); } else { gl_Position = vec4(position, 0.0, 1.0); } } ", fragment: " #version 100 void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } ", }).unwrap(); // the 3 last elements will be drawn let vb1 = glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [-1.0, 1.0] }, Vertex { position: [-1.0, 1.0] }, Vertex { position: [1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [1.0, -1.0] }, ]).unwrap(); // the 3 last elements will be drawn let vb2 = glium::VertexBuffer::new(&display, &[ Vertex2 { position2: [-1.0, 1.0] }, Vertex2 { position2: [-1.0, 1.0] }, Vertex2 { position2: [-1.0, 1.0] }, Vertex2 { position2: [-1.0, 1.0] }, Vertex2 { position2: [-1.0, 1.0] }, Vertex2 { position2: [1.0, 1.0] }, Vertex2 { position2: [-1.0, -1.0] }, Vertex2 { position2: [1.0, -1.0] }, ]).unwrap(); let indices = glium::IndexBuffer::new(&display, PrimitiveType::TrianglesList, &[2u16, 3, 4]).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw((vb1.slice(1 .. 4).unwrap(), vb2.slice(3 .. 6).unwrap()), &indices, &program, &glium::uniforms::EmptyUniforms, &Default::default()).unwrap(); let data: Vec> = texture.read(); assert_eq!(data.last().unwrap()[0], (0, 0, 0, 0)); assert_eq!(data[0].last().unwrap(), &(255, 0, 0, 255)); display.assert_no_error(None); } #[test] fn attributes_marker() { let display = support::build_display(); let program = match glium::Program::from_source(&display, " #version 140 void main() { if (gl_VertexID == 0) { gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); } else if (gl_VertexID == 1) { gl_Position = vec4(1.0, 1.0, 0.0, 1.0); } else if (gl_VertexID == 2) { gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); } else if (gl_VertexID == 3) { gl_Position = vec4(1.0, -1.0, 0.0, 1.0); } } ", " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } ", None) { Ok(p) => p, _ => return }; let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(glium::vertex::EmptyVertexAttributes { len: 4 }, &glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip), &program, &uniform!{}, &Default::default()).unwrap(); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn attributes_marker_indices() { let display = support::build_display(); let program = match glium::Program::from_source(&display, " #version 140 void main() { if (gl_VertexID == 0) { gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); } else if (gl_VertexID == 1) { gl_Position = vec4(1.0, 1.0, 0.0, 1.0); } else if (gl_VertexID == 2) { gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); } else if (gl_VertexID == 3) { gl_Position = vec4(1.0, -1.0, 0.0, 1.0); } } ", " #version 140 out vec4 color; void main() { color = vec4(1.0, 0.0, 0.0, 1.0); } ", None) { Ok(p) => p, _ => return }; let indices = glium::index::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u16, 1, 2, 3]).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw(glium::vertex::EmptyVertexAttributes { len: 4 }, &indices, &program, &uniform!{}, &Default::default()).unwrap(); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn instancing() { let display = support::build_display(); let buffer1 = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [ 1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [ 1.0, -1.0] }, ] ).unwrap() }; let buffer2 = { #[derive(Copy, Clone)] struct Vertex { color: [f32; 3], } implement_vertex!(Vertex, color); glium::vertex::VertexBuffer::new(&display, &[ Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [1.0, 0.0, 0.0] }, ] ).unwrap() }; let buffer2 = match buffer2.per_instance() { Ok(b) => b, Err(_) => return }; let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u16, 1, 2, 3]).unwrap(); let program = match glium::Program::from_source(&display, " #version 330 in vec2 position; in vec3 color; out vec3 v_color; flat out int instance; void main() { gl_Position = vec4(position, 0.0, 1.0); v_color = color; instance = gl_InstanceID; } ", " #version 330 in vec3 v_color; flat in int instance; void main() { if (instance != 3) { discard; } gl_FragColor = vec4(v_color, 1.0); } ", None) { Ok(p) => p, _ => return }; let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw((&buffer1, buffer2), &index_buffer, &program, &uniform!{}, &Default::default()).unwrap(); let data: Vec> = texture.read(); for row in data.iter() { for pixel in row.iter() { assert_eq!(pixel, &(255, 0, 0, 255)); } } display.assert_no_error(None); } #[test] fn per_instance_length_mismatch() { let display = support::build_display(); let buffer1 = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [ 1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [ 1.0, -1.0] }, ] ).unwrap() }; let buffer2 = { #[derive(Copy, Clone)] struct Vertex { color: [f32; 3], } implement_vertex!(Vertex, color); glium::vertex::VertexBuffer::new(&display, &[ Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [1.0, 0.0, 0.0] }, ] ).unwrap() }; let buffer2 = match buffer2.per_instance() { Ok(b) => b, Err(_) => return }; let buffer3 = { #[derive(Copy, Clone)] struct Vertex { color: [f32; 3], } implement_vertex!(Vertex, color); glium::vertex::VertexBuffer::new(&display, &[ Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [0.0, 0.0, 1.0] }, Vertex { color: [0.0, 0.0, 1.0] }, ] ).unwrap() }; let buffer3 = match buffer3.per_instance() { Ok(b) => b, Err(_) => return }; let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u16, 1, 2, 3]).unwrap(); let program = program!(&display, 110 => { vertex: " #version 110 void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); } ", fragment: " #version 110 void main() { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } ", }, 100 => { vertex: " #version 100 void main() { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); } ", fragment: " #version 100 void main() { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } ", }).unwrap(); let mut frame = display.draw(); match frame.draw((&buffer1, buffer2, buffer3), &index_buffer, &program, &uniform!{}, &Default::default()) { Err(glium::DrawError::InstancesCountMismatch) => (), a => panic!("{:?}", a) } frame.finish().unwrap(); display.assert_no_error(None); } #[test] fn normalized_vertex() { let display = support::build_display(); let buffer1 = { #[derive(Copy, Clone)] struct Vertex { position: [f32; 2], } implement_vertex!(Vertex, position); glium::VertexBuffer::new(&display, &[ Vertex { position: [-1.0, 1.0] }, Vertex { position: [ 1.0, 1.0] }, Vertex { position: [-1.0, -1.0] }, Vertex { position: [ 1.0, -1.0] }, ] ).unwrap() }; let buffer2 = { #[derive(Copy, Clone)] struct Vertex { color: [u8; 3], } implement_vertex!(Vertex, color normalize(true)); glium::VertexBuffer::new(&display, &[ Vertex { color: [0, 0, 0] }, Vertex { color: [128, 0, 0] }, Vertex { color: [0, 128, 0] }, Vertex { color: [0, 0, 128] }, ] ).unwrap() }; let index_buffer = glium::IndexBuffer::new(&display, PrimitiveType::TriangleStrip, &[0u16, 1, 2, 3]).unwrap(); let program = program!(&display, 110 => { vertex: " #version 110 attribute vec2 position; attribute vec3 color; varying vec3 v_color; void main() { gl_Position = vec4(position, 0.0, 1.0); v_color = color; } ", fragment: " #version 110 varying vec3 v_color; void main() { gl_FragColor = vec4(v_color, 1.0); } ", }, 100 => { vertex: " #version 100 attribute lowp vec2 position; attribute lowp vec3 color; varying lowp vec3 v_color; void main() { gl_Position = vec4(position, 0.0, 1.0); v_color = color; } ", fragment: " #version 100 varying lowp vec3 v_color; void main() { gl_FragColor = vec4(v_color, 1.0); } ", }).unwrap(); let texture = support::build_renderable_texture(&display); texture.as_surface().clear_color(0.0, 0.0, 0.0, 0.0); texture.as_surface().draw((&buffer1, &buffer2), &index_buffer, &program, &uniform!{}, &Default::default()).unwrap(); let data: Vec> = texture.read(); // If the data wasn't normalized, the 128 would be 255 instead assert_eq!(data[0][0], (0, 128, 0, 255)); display.assert_no_error(None); }