3

我尝试使用统一块来做到这一点:

锈:

#[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 { name: "MapBlock", err: MemberMismatch { member: "map", err: MemberMismatch { member: "", err: MemberMismatch { member: "position", err : OffsetMismatch { 预期:16,获得:0 } } } } }

每次启动程序时,shader 都会期望不同的尺寸结构,像这样:expected: 160, expected: 32, expected: 48。这可以解决吗?还有其他方法可以将数组传递给着色器吗?

我在用着:

  • Rust 1.28.0 稳定版,
  • 胶质 0.22.0,
  • 代数 0.16.0

完整代码锈:

#[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);
}
4

0 回答 0