use miniquad::{graphics::*, Context};
use specs_blit::PixelBuffer;
use std::slice;
const VERTEX: &str = r#"#version 100
attribute vec2 pos;
attribute vec2 uv;
varying lowp vec2 texcoord;
void main() {
gl_Position = vec4(pos, 0, 1);
texcoord = uv;
}
"#;
const FRAGMENT: &str = r#"#version 100
varying lowp vec2 texcoord;
uniform sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, texcoord);
}"#;
#[repr(C)]
struct Vec2 {
x: f32,
y: f32,
}
#[repr(C)]
struct Vertex {
pos: Vec2,
uv: Vec2,
}
pub struct Render {
pipeline: Pipeline,
texture: Texture,
bindings: Bindings,
}
impl Render {
pub fn new(ctx: &mut Context, width: usize, height: usize) -> Self {
let vertices: [Vertex; 4] = [
Vertex {
pos: Vec2 { x: -1.0, y: -1.0 },
uv: Vec2 { x: 0.0, y: 1.0 },
},
Vertex {
pos: Vec2 { x: 1.0, y: -1.0 },
uv: Vec2 { x: 1.0, y: 1.0 },
},
Vertex {
pos: Vec2 { x: 1.0, y: 1.0 },
uv: Vec2 { x: 1.0, y: 0.0 },
},
Vertex {
pos: Vec2 { x: -1.0, y: 1.0 },
uv: Vec2 { x: 0.0, y: 0.0 },
},
];
let vertex_buffer = Buffer::immutable(ctx, BufferType::VertexBuffer, &vertices);
let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
let index_buffer = Buffer::immutable(ctx, BufferType::IndexBuffer, &indices);
let texture = Texture::new_render_texture(
ctx,
TextureParams {
format: TextureFormat::RGBA8,
filter: FilterMode::Nearest,
width: width as u32,
height: height as u32,
..Default::default()
},
);
let bindings = Bindings {
vertex_buffers: vec![vertex_buffer],
index_buffer,
images: vec![texture],
};
let meta = ShaderMeta {
images: vec!["tex".to_string()],
uniforms: UniformBlockLayout {
uniforms: Vec::new(),
},
};
let shader = Shader::new(ctx, VERTEX, FRAGMENT, meta).unwrap();
let pipeline = Pipeline::new(
ctx,
&[BufferLayout::default()],
&[
VertexAttribute::new("pos", VertexFormat::Float2),
VertexAttribute::new("uv", VertexFormat::Float2),
],
shader,
);
Self {
pipeline,
bindings,
texture,
}
}
pub fn render(&mut self, ctx: &mut Context, buffer: &PixelBuffer) {
let bytes = unsafe {
slice::from_raw_parts(
buffer.pixels().as_ptr() as *const u8,
buffer.pixels().len() * 4,
)
};
self.texture.update(ctx, &bytes);
ctx.begin_default_pass(Default::default());
ctx.apply_pipeline(&self.pipeline);
ctx.apply_bindings(&self.bindings);
ctx.draw(0, 6, 1);
ctx.end_render_pass();
ctx.commit_frame();
}
}