#[path = "common/runtime.rs"]
mod runtime;
use std::time::SystemTime;
use ombre::prelude::*;
#[repr(C)]
struct Vec2 {
x: f32,
y: f32,
}
#[repr(C)]
struct Vertex {
pos: Vec2,
uv: Vec2,
}
struct Renderer<T> {
pipeline: PipelineId,
bindings: Bindings,
backend: T,
}
impl<T: RenderBackend> RuntimeRenderer for Renderer<T> {
type Error = T::Error;
fn window_resized(&mut self, _size: platform::LogicalSize) {}
fn frame(&mut self) -> Result<(), Self::Error> {
let t = SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs_f64();
let mut frame = self.backend.frame();
frame.begin_default_pass(Default::default());
frame.apply_pipeline(&self.pipeline)?;
frame.apply_bindings(&self.bindings)?;
for i in 0..10 {
let t = t + i as f64 * 0.3;
frame.apply_uniforms(&shader::Uniforms {
offset: [t.sin() as f32 * 0.5, (t * 3.).cos() as f32 * 0.5],
})?;
frame.draw(0, 6, 1)?;
}
frame.end_pass();
frame.commit();
Ok(())
}
}
impl<T: RenderBackend> Renderer<T> {
pub fn init(mut backend: T) -> Result<Renderer<T>, T::Error> {
#[rustfmt::skip]
let vertices: [Vertex; 4] = [
Vertex { pos : Vec2 { x: -0.5, y: -0.5 }, uv: Vec2 { x: 0., y: 0. } },
Vertex { pos : Vec2 { x: 0.5, y: -0.5 }, uv: Vec2 { x: 1., y: 0. } },
Vertex { pos : Vec2 { x: 0.5, y: 0.5 }, uv: Vec2 { x: 1., y: 1. } },
Vertex { pos : Vec2 { x: -0.5, y: 0.5 }, uv: Vec2 { x: 0., y: 1. } },
];
let vertex_buffer = backend.buffer(
BufferKind::Vertex,
BufferUsage::Immutable,
BufferSource::slice(&vertices),
)?;
let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
let index_buffer = backend.buffer(
BufferKind::Index,
BufferUsage::Immutable,
BufferSource::slice(&indices),
)?;
let pixels: [Rgba8; 4 * 4] = [
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0xFF),
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0xFF),
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0xFF),
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0x00),
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0xFF),
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
Rgba8::new(0xFF, 0x00, 0x00, 0xFF),
Rgba8::new(0xFF, 0xFF, 0xFF, 0xFF),
];
let texture = backend.texture(gfx::Texture {
data: pixels.as_slice(),
size: Size::new(4, 4),
min_filter: FilterMode::Linear,
mag_filter: FilterMode::Linear,
..gfx::Texture::default()
})?;
let bindings = Bindings {
vertex: vec![vertex_buffer],
index: Some(index_buffer),
textures: vec![texture],
};
let shader = backend
.shader(
ShaderSource {
vertex: shader::VERTEX,
fragment: shader::FRAGMENT,
},
shader::meta(),
)
.unwrap();
let pipeline = backend.pipeline(
shader,
gfx::PipelineDescriptor {
layout: &[gfx::BufferLayout {
attrs: &[
VertexAttribute::new("in_pos", VertexFormat::Float2),
VertexAttribute::new("in_uv", VertexFormat::Float2),
],
..gfx::BufferLayout::default()
}],
..gfx::PipelineDescriptor::default()
},
);
Ok(Self {
pipeline,
bindings,
backend,
})
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
logger::init(log::Level::Debug)?;
let (mut win, events) =
platform::init("texture", 640, 480, &[], platform::GraphicsContext::Gl)?;
let ctx = unsafe { glow::Context::from_loader_function(|p| win.get_proc_address(p)) };
let backend = gfx::gl::Context::new(ctx, win.size())?;
let renderer = Renderer::init(backend)?;
runtime::run(win, events, renderer)?;
Ok(())
}
mod shader {
use super::*;
pub const VERTEX: &str = r#"#version 100
attribute vec2 in_pos;
attribute vec2 in_uv;
uniform vec2 offset;
varying lowp vec2 texcoord;
void main() {
gl_Position = vec4(in_pos + offset, 0, 1);
texcoord = in_uv;
}"#;
pub const FRAGMENT: &str = r#"#version 100
varying lowp vec2 texcoord;
uniform sampler2D tex;
void main() {
gl_FragColor = texture2D(tex, texcoord);
}"#;
pub fn meta() -> ShaderDescriptor {
ShaderDescriptor {
textures: vec!["tex".to_string()],
uniforms: UniformBlockLayout {
uniforms: vec![UniformDescriptor::new("offset", UniformKind::Float2)],
},
}
}
#[repr(C)]
pub struct Uniforms {
pub offset: [f32; 2],
}
unsafe impl bytes::Packed for Uniforms {}
}