#[path = "common/runtime.rs"]
mod runtime;
use ombre::prelude::*;
#[repr(C)]
struct Vertex {
position: [f32; 2],
color: [f32; 4],
}
pub struct Renderer<T> {
pipeline: gfx::PipelineId,
bindings: gfx::Bindings,
backend: T,
}
impl<T: gfx::RenderBackend> RuntimeRenderer for Renderer<T> {
type Error = T::Error;
fn window_resized(&mut self, size: platform::LogicalSize) {
self.backend.window_resized(size);
}
fn frame(&mut self) -> Result<(), Self::Error> {
let mut frame = self.backend.frame();
frame.begin_default_pass(Default::default());
frame.apply_pipeline(&self.pipeline)?;
frame.apply_bindings(&self.bindings)?;
frame.draw(0, 3, 1)?;
frame.end_pass();
frame.commit();
Ok(())
}
}
impl<T: gfx::RenderBackend> Renderer<T> {
pub fn init(mut backend: T) -> Result<Self, T::Error> {
#[rustfmt::skip]
let vertices: [Vertex; 3] = [
Vertex { position: [-0.5, -0.5], color: [1., 1., 0., 1.] },
Vertex { position: [ 0.5, -0.5], color: [0., 1., 1., 1.] },
Vertex { position: [ 0.0, 0.5], color: [1., 0., 1., 1.] },
];
let vertex_buffer = backend.buffer(
gfx::BufferKind::Vertex,
gfx::BufferUsage::Immutable,
gfx::BufferSource::slice(&vertices),
)?;
let index_buffer = backend.buffer(
gfx::BufferKind::Index,
gfx::BufferUsage::Immutable,
gfx::BufferSource::slice(&[0, 1, 2]),
)?;
let bindings = gfx::Bindings {
vertex: vec![vertex_buffer],
index: Some(index_buffer),
textures: vec![],
};
let shader = backend
.shader(
gfx::ShaderSource {
vertex: shader::VERTEX,
fragment: shader::FRAGMENT,
},
shader::descriptor(),
)
.unwrap();
let pipeline = backend.pipeline(
shader,
gfx::PipelineDescriptor {
layout: &[gfx::BufferLayout {
attrs: &[
gfx::VertexAttribute::new("position", gfx::VertexFormat::Float2),
gfx::VertexAttribute::new("color", gfx::VertexFormat::Float4),
],
..gfx::BufferLayout::default()
}],
..gfx::PipelineDescriptor::default()
},
);
Ok(Self {
backend,
pipeline,
bindings,
})
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
logger::init(log::Level::Debug)?;
let (mut win, events) =
platform::init("triangle", 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 position;
attribute vec4 color;
varying lowp vec4 f_color;
void main() {
gl_Position = vec4(position, 0, 1);
f_color = color;
}
"#;
pub const FRAGMENT: &str = r#"
#version 100
varying lowp vec4 f_color;
void main() {
gl_FragColor = f_color;
}
"#;
pub fn descriptor() -> gfx::ShaderDescriptor {
gfx::ShaderDescriptor {
textures: vec![],
uniforms: gfx::UniformBlockLayout { uniforms: vec![] },
}
}
}