Skip to content

Instantly share code, notes, and snippets.

@tinaun
Created May 11, 2018
Embed
What would you like to do?
i wrote a proc macro!
extern crate luminance;
extern crate luminance_glfw;
#[macro_use]
extern crate luminance_derive;
use luminance_glfw::{Device, GLFWDevice, WindowDim, WindowOpt, WindowEvent};
use luminance::framebuffer::Framebuffer;
use luminance::shader::program::{Program, Uniform};
use luminance::pipeline::{BoundTexture, RenderState, entry, pipeline};
use luminance::texture::{self, Texture, Sampler, TextureError};
use luminance::pixel;
use luminance::tess::{Tess, Mode};
use std::error::Error;
use std::thread;
use std::time::Duration;
type RectTex = Texture<texture::Flat, texture::Dim2, pixel::RGBA32F>;
#[derive(Vertex, Debug, Copy, Clone, PartialEq)]
struct Vertex {
#[component(ty = "f32", dim = "2")]
pos: [f32; 2],
#[component(ty = "f32", dim = "2")]
texcoord: [f32; 2],
}
#[derive(UniformInterface)]
struct Uniforms<'a: 'b, 'b> {
#[uniform(name = "t")]
pub angle: Uniform<f32>,
pub tex: Uniform<&'b BoundTexture<'a, RectTex>>,
}
fn debug_texture() -> Result<RectTex, TextureError> {
let tex = RectTex::new([16, 16], 0, &Sampler::default())?;
let pixels = [(1.0, 0.0, 0.0, 1.0),(0.0, 1.0, 0.0, 1.0),(0.0, 0.0, 1.0, 1.0)].iter()
.cycle().cloned().take(16*16).collect::<Vec<_>>();
tex.upload(false, &pixels);
Ok(tex)
}
fn main() -> Result<(), Box<Error>> {
let mut window = GLFWDevice::new(WindowDim::Windowed(600, 600), "rotating rect", WindowOpt::default())?;
let mut backbuffer = Framebuffer::default([600, 600]);
// each shader has an associated vertex type and uniform type - that way its easy to keep track of what each
// shader needs
let (shader, _) = Program::<Vertex, (), Uniforms>::from_strings(None, VERT, None, FRAG)?;
let tex = debug_texture()?;
// just a simple square mesh
let verts = [
Vertex { pos: [-0.5, 0.5], texcoord: [0.0, 0.0] },
Vertex { pos: [0.5, 0.5], texcoord: [1.0, 0.0] },
Vertex { pos: [0.5, -0.5], texcoord: [1.0, 1.0] },
Vertex { pos: [-0.5, -0.5], texcoord: [0.0, 1.0] },
];
let idxs = [0, 1, 2, 2, 3, 0];
let mesh = Tess::new(Mode::Triangle, &verts[..], Some(&idxs[..]));
let mut t = 0.0;
'window: loop {
// update
for ev in window.events() {
match ev {
WindowEvent::Close => break 'window,
WindowEvent::Size(x, y) => {
backbuffer = Framebuffer::default([x as u32, y as u32]);
}
_ => {},
}
}
// rotate
t += 0.03;
// draw a frame
window.draw(|| {
//in here, we can ajust what is bound to the gpu. right now, we bind a texture
entry(|gpu| {
let tex_binding = gpu.bind_texture(&tex);
// start a render pipeline, outputing to the backbuffer, with a clear color of solid white
pipeline(&backbuffer, [1.0; 4], |shader_gate| {
// now that we have a shader gate, we can start a shader pass using any program object that we have.
// in a shader pass, we have access to the uniforms associated with the program object
shader_gate.shade(&shader, |render, uniforms| {
// update each uniform
uniforms.angle.update(t);
uniforms.tex.update(&tex_binding);
// the render state controls a variety of rendering options including
// blending, depth testing, and face culling
// inside the render gate we can finally draw some primitives
render.render(RenderState::default().set_face_culling(None), |t| {
t.render((&mesh).into());
});
})
});
})
});
// rest
thread::sleep(Duration::from_millis(10));
}
Ok(())
}
const VERT: &'static str = r"
layout(location = 0) in vec2 vPos;
layout(location = 1) in vec2 texcoord;
uniform float t;
out vec2 fPos;
void main() {
mat2 rot = mat2(cos(t), -sin(t), sin(t), cos(t));
gl_Position = vec4(rot * vPos, -0.1, 1.0);
fPos = texcoord;
}
";
const FRAG: &'static str = r"
in vec2 fPos;
uniform sampler2D tex;
out vec4 color;
void main() {
color = texture(tex, fPos);
}
";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment