Is there any way in glium to pass an array to a shader? I tried to do it with a uniform block, like this:
//Rust #[derive(Copy, Clone)] struct Circle { position: (f32, f32), radius: u32 } #[derive(Copy, Clone)] struct UniformBlock { map: [Circle; 64] } implement_uniform_block!(Circle, position, radius); implement_uniform_block!(UniformBlock, map); let buffer = UniformBuffer::new(&display, UniformBlock::new([Circle::new((20., 20.), 8); 64])).unwrap(); uniform! { MapBlock: &buffer } //GLSL struct Circle { vec2 position; uint radius; }; layout(std140) uniform MapBlock { Circle map[64]; }; but got the following run-time error:
Errvalue: UniformBlockLayoutMismatch {name: "MapBlock", err: MemberMismatch {member: "map", err: MemberMismatch {member: "", err: MemberMismatch {member: "position", err : OffsetMismatch {expected: 16, obtained: 0}}}}}
This error can somehow be solved? Or are there other ways to pass an array to the shader? Full code:
//Rust #[macro_use] extern crate glium; use glium::{ glutin, uniforms::{ UniformValue, UniformBuffer, AsUniformValue }, vertex::{ Attribute, AttributeType } }; extern crate nalgebra as na; use std::{ fs::File, fmt::Debug, io::prelude::* }; #[derive(Copy, Clone)] struct Point2<T: 'static + Copy + PartialEq + Debug>(na::Point2<T>); impl<T: 'static + Copy + PartialEq + Debug> Point2<T> { fn new(x: T, y: T) -> Self { Point2(na::Point2::new(x, y)) } } unsafe impl Attribute for Point2<f32> { #[inline] fn get_type() -> AttributeType { AttributeType::F32F32 } } impl AsUniformValue for Point2<f32> { fn as_uniform_value(&self) -> UniformValue { UniformValue::Vec2([self.0.x, self.0.y]) } } #[derive(Copy, Clone)] struct Vertex { position: Point2<f32> } impl Vertex { fn new(position: Point2<f32>) -> Self { Self { position } } } #[derive(Copy, Clone)] struct Circle { position: (f32, f32), radius: u32, _padding: u32 } impl Circle { fn new(position: (f32, f32), radius: u32) -> Self { Self { position, radius, _padding: 0 } } } #[derive(Copy, Clone)] struct UniformBlock { map: [Circle; 64] } impl UniformBlock { fn new(map: [Circle; 64]) -> Self { Self { map } } } implement_vertex!(Vertex, position); implement_uniform_block!(Circle, position, radius); implement_uniform_block!(UniformBlock, map); fn main() { let mut events_loop = glutin::EventsLoop::new(); let display = { let window = glutin::WindowBuilder::new() .with_title("Window"); let context = glutin::ContextBuilder::new() .with_vsync(true); glium::Display::new(window, context, &events_loop).unwrap() }; let vertex_buffer = glium::VertexBuffer::new(&display, &[ Vertex::new(Point2::new(-1.0, 1.0)), Vertex::new(Point2::new(-1.0, -1.0)), Vertex::new(Point2::new( 1.0, -1.0)), Vertex::new(Point2::new( 1.0, 1.0)) ]).unwrap(); let indices = glium::IndexBuffer::new(&display, glium::index::PrimitiveType::TrianglesList, &[ 0, 1, 3, 1, 2, 3u8 ]).unwrap(); let program = { let mut v_sh_src = String::new(); File::open("shaders/vertex.glsl").unwrap() .read_to_string(&mut v_sh_src).unwrap(); let mut f_sh_src = String::new(); File::open("shaders/fragment.glsl").unwrap() .read_to_string(&mut f_sh_src).unwrap(); glium::Program::from_source(&display, v_sh_src.as_str(), f_sh_src.as_str(), None).unwrap() }; let buffer = UniformBuffer::new(&display, UniformBlock::new([Circle::new((20., 20.), 8); 64])).unwrap(); let mut done = false; while !done { use glium::Surface; let mut target = display.draw(); target.clear_color(0.0, 0.0, 0.0, 1.0); target.draw(&vertex_buffer, &indices, &program, &uniform! { mapBlock: &buffer }, &Default::default()).unwrap(); target.finish().unwrap(); events_loop.poll_events(|event| { use glutin::{ Event, WindowEvent, ElementState, VirtualKeyCode }; match event { Event::WindowEvent { event, window_id } => if window_id == display.gl_window().id() { match event { WindowEvent::CloseRequested => done = true, WindowEvent::KeyboardInput { input, .. } => { match input.state { ElementState::Released => match input.virtual_keycode { Some(VirtualKeyCode::Escape) => done = true, _ => () } _ => () } } _ => () } } _ => () } }); } } //fragment.glsl #version 330 core struct Circle { vec2 position; uint radius; }; layout(std140) uniform mapBlock { Circle map[64]; }; void main() { for (int i = 0; i < 64; ++i) if (distance(map[i].position, gl_FragCoord.xy) <= map[i].radius) gl_FragColor = vec4(0.0f, 0.5f, 0.0f, 1.0f); } //vertex.glsl #version 330 core layout (location = 0) in vec2 position; void main() { gl_Position = vec4(position, 0.0f, 1.0f); }