我试图用统一块来做到这一点:
铁锈:
#[derive(Copy, Clone)]
struct Circle {
position: (f32, f32),
radius: u32,
_padding: 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];
};
但是我收到以下运行时错误:
在Err值上调用Result :: unwrap():UniformBlockLayoutMismatch {名称:“ MapBlock”,err:MemberMismatch {成员:“ map”,err:MemberMismatch {成员:“”,err:MemberMismatch {成员:“ position “,错误:OffsetMismatch {预期:16,获得:0}}}}}
每次启动程序时,着色器都希望使用不同的大小结构,例如:预期:160,预期:32,预期:48。这可以解决吗?还有其他方法可以将数组传递给着色器吗?
我正在使用:
完整代码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((200., 200.), 32); 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,
_ => ()
}
_ => ()
}
}
_ => ()
}
}
_ => ()
}
});
}
}
完整代码frafment.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);
}