extern crate gl;
extern crate glutin;
extern crate time;
extern crate vec3;
extern crate mat4;
extern crate gl_helpers;
use std::f32;
use glutin::GlContext;
use gl::types::*;
use gl_helpers::*;
static FB_DATA: [GLfloat; 16] = [
// position uv
1f32, 1f32, 1f32, 1f32,
-1f32, 1f32, 0f32, 1f32,
1f32, -1f32, 1f32, 0f32,
-1f32, -1f32, 0f32, 0f32
];
static CUBE_DATA: [GLfloat; 288] = [
1.0, 1.0, -1.0, 0.577349, 0.577349, -0.577349, 0.0, 0.0, 1.0, -1.0, -1.0, 0.577349, -0.577349, -0.577349, 1.0, 0.0, -1.0, -1.0, -1.0, -0.577349, -0.577349, -0.577349, 1.0, 1.0, 1.0, 1.0, 1.0, 0.577349, 0.577349, 0.577349, 0.0, 0.0, -1.0, 1.0, 1.0, -0.577349, 0.577349, 0.577349, 1.0, 0.0, -1.0, -1.0, 1.0, -0.577349, -0.577349, 0.577349, 1.0, 1.0, 1.0, 1.0, -1.0, 0.577349, 0.577349, -0.577349, 0.0, 0.0, 1.0, 1.0, 1.0, 0.577349, 0.577349, 0.577349, 1.0, 0.0, 1.0, -1.0, 1.0, 0.577349, -0.577349, 0.577349, 1.0, 1.0, 1.0, -1.0, -1.0, 0.577349, -0.577349, -0.577349, 0.0, 0.0, 1.0, -1.0, 1.0, 0.577349, -0.577349, 0.577349, 1.0, 0.0, -1.0, -1.0, 1.0, -0.577349, -0.577349, 0.577349, 1.0, 1.0, -1.0, -1.0, -1.0, -0.577349, -0.577349, -0.577349, 0.0, 0.0, -1.0, -1.0, 1.0, -0.577349, -0.577349, 0.577349, 1.0, 0.0, -1.0, 1.0, 1.0, -0.577349, 0.577349, 0.577349, 1.0, 1.0, 1.0, 1.0, 1.0, 0.577349, 0.577349, 0.577349, 0.0, 0.0, 1.0, 1.0, -1.0, 0.577349, 0.577349, -0.577349, 1.0, 0.0, -1.0, 1.0, -1.0, -0.577349, 0.577349, -0.577349, 1.0, 1.0, -1.0, 1.0, -1.0, -0.577349, 0.577349, -0.577349, 0.0, 1.0, 1.0, 1.0, -1.0, 0.577349, 0.577349, -0.577349, 0.0, 0.0, -1.0, -1.0, -1.0, -0.577349, -0.577349, -0.577349, 1.0, 1.0, 1.0, -1.0, 1.0, 0.577349, -0.577349, 0.577349, 0.0, 1.0, 1.0, 1.0, 1.0, 0.577349, 0.577349, 0.577349, 0.0, 0.0, -1.0, -1.0, 1.0, -0.577349, -0.577349, 0.577349, 1.0, 1.0, 1.0, -1.0, -1.0, 0.577349, -0.577349, -0.577349, 0.0, 1.0, 1.0, 1.0, -1.0, 0.577349, 0.577349, -0.577349, 0.0, 0.0, 1.0, -1.0, 1.0, 0.577349, -0.577349, 0.577349, 1.0, 1.0, -1.0, -1.0, -1.0, -0.577349, -0.577349, -0.577349, 0.0, 1.0, 1.0, -1.0, -1.0, 0.577349, -0.577349, -0.577349, 0.0, 0.0, -1.0, -1.0, 1.0, -0.577349, -0.577349, 0.577349, 1.0, 1.0, -1.0, 1.0, -1.0, -0.577349, 0.577349, -0.577349, 0.0, 1.0, -1.0, -1.0, -1.0, -0.577349, -0.577349, -0.577349, 0.0, 0.0, -1.0, 1.0, 1.0, -0.577349, 0.577349, 0.577349, 1.0, 1.0, -1.0, 1.0, 1.0, -0.577349, 0.577349, 0.577349, 0.0, 1.0, 1.0, 1.0, 1.0, 0.577349, 0.577349, 0.577349, 0.0, 0.0, -1.0, 1.0, -1.0, -0.577349, 0.577349, -0.577349, 1.0, 1.0
];
static CUBE_INDEX_DATA: [u16; 36] = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35
];
static FB_VERTEX: &'static str = "
#version 120
attribute vec2 position;
attribute vec2 uv;
varying vec2 v_uv;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
v_uv = uv;
}
";
static FB_FRAGMENT: &'static str = "
#version 120
uniform sampler2D diffuse;
varying vec2 v_uv;
void main() {
gl_FragColor = texture2D(diffuse, v_uv);
}
";
static CUBE_VERTEX: &'static str = "
#version 120
uniform mat4 projection;
uniform mat4 model_view;
uniform vec3 light;
attribute vec3 position;
attribute vec3 normal;
attribute vec2 uv;
varying vec3 v_light;
varying vec3 v_normal;
varying vec2 v_uv;
void main() {
gl_Position = projection * model_view * vec4(position, 1.0);
v_light = normalize(light - position);
v_normal = normal;
v_uv = uv;
}
";
static CUBE_FRAGMENT: &'static str = "
#version 120
varying vec3 v_light;
varying vec3 v_normal;
varying vec2 v_uv;
void main() {
vec3 light_dir = v_light;
vec3 color = vec3(v_uv, 0.5);
vec3 intensity = vec3(0.75, 0.75, 0.75);
float dprod = dot(light_dir, v_normal);
if (dprod > 0.75) {
intensity = vec3(1.0, 1.0, 1.0);
} else if (dprod > 0.25) {
intensity = vec3(0.8, 0.8, 0.8);
}
gl_FragColor = vec4(color * intensity, 1.0);
}
";
fn main() {
let mut screen_width = 1024_usize;
let mut screen_height = 768_usize;
let mut events_loop = glutin::EventsLoop::new();
let window = glutin::WindowBuilder::new()
.with_title("Framebuffer")
.with_dimensions(screen_width as u32, screen_height as u32);
let gl_window = glutin::GlWindow::new(
window,
glutin::ContextBuilder::new()
.with_vsync(true),
&events_loop
).unwrap();
unsafe {
gl_window.make_current().unwrap();
}
gl::load_with(|symbol| gl_window.get_proc_address(symbol) as *const _);
let gl_info = GLInfo::new();
println!("{}", gl_info.version());
println!(
"OpenGL version: {:?}.{:?}, GLSL version {:?}.{:?}0",
gl_info.major(), gl_info.minor(), gl_info.glsl_major(), gl_info.glsl_minor()
);
gl_set_defaults();
static SIZE: usize = 8_usize;
let fb_program = GLProgram::new(FB_VERTEX, FB_FRAGMENT);
let mut fb_texture = GLTexture::new_null_2d(
screen_width / SIZE,
screen_height / SIZE,
DataFormat::RGBA,
DataKind::UnsignedByte,
FilterMode::None,
Wrap::Clamp,
false
);
let fb_framebuffer = GLFramebuffer::new(&fb_texture, &[Attachment::Color], 0);
let fb_renderbuffer = GLRenderbuffer::new(DataFormat::DepthComponent, Attachment::Depth, screen_width / SIZE, screen_height / SIZE);
let mut fb_vertex_array = GLVertexArray::new();
fb_vertex_array.bind();
let fb_buffer = GLBuffer::new(BufferTarget::Array, 4, Usage::StaticDraw, &FB_DATA);
fb_buffer.bind();
fb_vertex_array.add_attribute(&fb_buffer, fb_program.get_attribute("position"), 0);
fb_vertex_array.add_attribute(&fb_buffer, fb_program.get_attribute("uv"), 2);
let cube_program = GLProgram::new(CUBE_VERTEX, CUBE_FRAGMENT);
let mut cube_vertex_array = GLVertexArray::new();
cube_vertex_array.bind();
let cube_buffer = GLBuffer::new(BufferTarget::Array, 8, Usage::StaticDraw, &CUBE_DATA);
let cube_index_buffer = GLBuffer::new(BufferTarget::ElementArray, 0, Usage::StaticDraw, &CUBE_INDEX_DATA);
cube_buffer.bind();
cube_vertex_array.add_attribute(&cube_buffer, cube_program.get_attribute("position"), 0);
cube_vertex_array.add_attribute(&cube_buffer, cube_program.get_attribute("normal"), 3);
cube_vertex_array.add_attribute(&cube_buffer, cube_program.get_attribute("uv"), 5);
cube_index_buffer.bind();
let mut playing = true;
let start_time = time::now();
let mut last_time = start_time;
let mut current_time;
let mut ms = 0f32;
let mut dt;
let fov = 45_f32 * (f32::consts::PI / 180_f32);
//let ortho_size: f32 = 2_f32;
let origin = vec3::new(0_f32, 0_f32, 0_f32);
let up = vec3::new(0_f32, 0_f32, 1_f32);
let mut camera = mat4::new_identity::<f32>();
let mut camera_position = vec3::new(6_f32, 6_f32, 4_f32);
let mut light_position = vec3::new(2_f32, 2_f32, 2_f32);
let mut projection = mat4::new_identity::<f32>();
let mut model_view = mat4::new_identity::<f32>();
while playing {
current_time = time::now();
dt = (current_time - last_time).num_nanoseconds().unwrap() as f32 * 0.000001f32;
ms += dt;
last_time = current_time;
events_loop.poll_events(|event| {
match event {
glutin::Event::WindowEvent { event: glutin::WindowEvent::Closed, .. } => {
playing = false;
},
glutin::Event::WindowEvent { event: glutin::WindowEvent::Resized(w, h), .. } => {
gl_window.resize(w, h);
screen_width = w as usize;
screen_height = h as usize;
fb_texture.resize_null_2d(screen_width / SIZE,screen_height / SIZE);
fb_framebuffer.set(&fb_texture, &[Attachment::Color], 0);
fb_renderbuffer.set(DataFormat::DepthComponent, Attachment::Depth, screen_width / SIZE, screen_height / SIZE);
/*
let aspect = w as f32 / h as f32;
let r = ortho_size * aspect;
let l = -r;
let t = ortho_size;
let b = -t;
mat4::orthographic(&mut projection, t, r, b, l, 0.0001_f32, 1024_f32);
*/
mat4::perspective(&mut projection, fov, screen_width as f32 / screen_height as f32, 0.0001_f32, 1024_f32);
},
_ => (),
}
});
light_position[0] = (ms * 0.001f32).sin() * 6_f32;
light_position[1] = (ms * 0.001f32).cos() * 6_f32;
light_position[2] = (ms * 0.001f32).sin() * 6_f32;
camera_position[0] = (ms * 0.001f32).sin() * 6_f32;
camera_position[1] = (ms * 0.001f32).cos() * 6_f32;
camera_position[2] = 3.5_f32 + ((ms * 0.001f32).sin() * 3_f32);
mat4::look_at(&mut camera, &camera_position, &origin, &up);
mat4::set_position(&mut camera, &camera_position);
mat4::inverse(&mut model_view, &camera);
fb_framebuffer.bind();
fb_renderbuffer.bind();
gl_set_viewport(0, 0, screen_width / SIZE, screen_height / SIZE);
gl_set_clear_color(&[0.3, 0.3, 0.3, 1.0]);
gl_clear(true, true, true);
cube_program.bind();
cube_vertex_array.bind();
cube_vertex_array.enable_attributes();
cube_program.get_uniform("projection").set_mat4f(&projection);
cube_program.get_uniform("model_view").set_mat4f(&model_view);
cube_program.get_uniform("light").set_3f(&light_position);
gl_draw_elements(DrawMode::Triangles, 36, IndexKind::UnsignedShort, 0);
fb_framebuffer.unbind();
fb_renderbuffer.unbind();
gl_set_viewport(0, 0, screen_width, screen_height);
gl_set_clear_color(&[0.3, 0.3, 0.3, 1.0]);
gl_clear(true, true, true);
fb_program.bind();
fb_vertex_array.bind();
fb_vertex_array.enable_attributes();
fb_program.get_uniform("diffuse").set_sampler_2d(&fb_texture, 0);
gl_draw_arrays(DrawMode::TriangleStrip, 0, 4);
gl_window.swap_buffers().unwrap();
}
}