Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
323 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
[workspace] | ||
members = ["canvas", "echo", "hasher", "minimal", "todomvc"] | ||
members = ["canvas", "echo", "hasher", "minimal", "todomvc", "webgl"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "webgl" | ||
version = "0.1.0" | ||
authors = ["Diggory Blake"] | ||
|
||
[dependencies] | ||
stdweb = { path = "../.." } | ||
stdweb-derive = { path = "../../stdweb-derive" } | ||
serde = "1.0.0" | ||
serde_derive = "1.0.0" | ||
|
||
[build-dependencies] | ||
webgl_generator = "0.1.0" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
extern crate webgl_generator; | ||
|
||
use webgl_generator::*; | ||
use std::env; | ||
use std::fs::File; | ||
use std::path::*; | ||
|
||
fn main() { | ||
let dest = env::var("OUT_DIR").unwrap(); | ||
let mut file = File::create(&Path::new(&dest).join("webgl_rendering_context.rs")).unwrap(); | ||
|
||
Registry::new(Api::WebGl2, Exts::NONE) | ||
.write_bindings(StdwebGenerator, &mut file) | ||
.unwrap(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
#[macro_use] | ||
extern crate stdweb; | ||
#[macro_use] | ||
extern crate serde_derive; | ||
#[macro_use] | ||
extern crate stdweb_derive; | ||
|
||
use std::rc::Rc; | ||
use std::cell::RefCell; | ||
|
||
mod webgl_rendering_context; | ||
|
||
use stdweb::unstable::TryInto; | ||
use stdweb::web::{ | ||
IEventTarget, | ||
IHtmlElement, | ||
IParentNode, | ||
document, | ||
window, | ||
TypedArray, | ||
}; | ||
|
||
use stdweb::web::event::{ | ||
ResizeEvent, | ||
}; | ||
|
||
use stdweb::web::html_element::CanvasElement; | ||
use webgl_rendering_context::{ | ||
WebGLRenderingContext as gl, | ||
WebGLUniformLocation, | ||
WebGLBuffer | ||
}; | ||
|
||
// Shamelessly stolen from webplatform's TodoMVC example. | ||
macro_rules! enclose { | ||
( ($( $x:ident ),*) $y:expr ) => { | ||
{ | ||
$(let $x = $x.clone();)* | ||
$y | ||
} | ||
}; | ||
} | ||
|
||
/*==================== Rotation ====================*/ | ||
fn rotate_z(m: &mut [f32], angle: f32) { | ||
let (s, c) = angle.sin_cos(); | ||
let (mv0, mv4, mv8) = (m[0], m[4], m[8]); | ||
|
||
m[0] = c*m[0]-s*m[1]; | ||
m[4] = c*m[4]-s*m[5]; | ||
m[8] = c*m[8]-s*m[9]; | ||
|
||
m[1]=c*m[1]+s*mv0; | ||
m[5]=c*m[5]+s*mv4; | ||
m[9]=c*m[9]+s*mv8; | ||
} | ||
|
||
fn rotate_x(m: &mut [f32], angle: f32) { | ||
let (s, c) = angle.sin_cos(); | ||
let (mv1, mv5, mv9) = (m[1], m[5], m[9]); | ||
|
||
m[1] = m[1]*c-m[2]*s; | ||
m[5] = m[5]*c-m[6]*s; | ||
m[9] = m[9]*c-m[10]*s; | ||
|
||
m[2] = m[2]*c+mv1*s; | ||
m[6] = m[6]*c+mv5*s; | ||
m[10] = m[10]*c+mv9*s; | ||
} | ||
|
||
fn rotate_y(m: &mut [f32], angle: f32) { | ||
let (s, c) = angle.sin_cos(); | ||
let (mv0, mv4, mv8) = (m[0], m[4], m[8]); | ||
|
||
m[0] = c*m[0]+s*m[2]; | ||
m[4] = c*m[4]+s*m[6]; | ||
m[8] = c*m[8]+s*m[10]; | ||
|
||
m[2] = c*m[2]-s*mv0; | ||
m[6] = c*m[6]-s*mv4; | ||
m[10] = c*m[10]-s*mv8; | ||
} | ||
|
||
/*==================== MATRIX =====================*/ | ||
fn get_projection(angle: f32, a: f32, z_min: f32, z_max: f32) -> [f32; 16] { | ||
let ang = (angle*0.5).to_radians().tan(); | ||
return [ | ||
0.5/ang, 0., 0., 0., | ||
0., 0.5*a/ang, 0., 0., | ||
0., 0., -(z_max+z_min)/(z_max-z_min), -1., | ||
0., 0., (-2.*z_max*z_min)/(z_max-z_min), 0. | ||
]; | ||
} | ||
|
||
struct State { | ||
time_old: f64, | ||
mov_matrix: [f32; 16], | ||
view_matrix: [f32; 16], | ||
canvas: CanvasElement, | ||
context: gl, | ||
p_matrix: WebGLUniformLocation, | ||
v_matrix: WebGLUniformLocation, | ||
m_matrix: WebGLUniformLocation, | ||
index_buffer: WebGLBuffer, | ||
} | ||
|
||
impl State { | ||
fn animate(&mut self, time: f64, rc: Rc<RefCell<Self>>) { | ||
let dt = (time - self.time_old) as f32; | ||
rotate_z(&mut self.mov_matrix, dt*0.0007);//time | ||
rotate_y(&mut self.mov_matrix, dt*0.0002); | ||
rotate_x(&mut self.mov_matrix, dt*0.0003); | ||
self.time_old = time; | ||
|
||
self.context.enable(gl::DEPTH_TEST); | ||
self.context.depth_func(gl::LEQUAL); | ||
self.context.clear_color(0.5, 0.5, 0.5, 0.9); | ||
self.context.clear_depth(1.0); | ||
|
||
let (w, h) = (self.canvas.width(), self.canvas.height()); | ||
let proj_matrix = get_projection(40., (w as f32)/(h as f32), 1., 100.); | ||
|
||
self.context.viewport(0, 0, w as i32, h as i32); | ||
self.context.clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT); | ||
self.context.uniform_matrix4fv(Some(&self.p_matrix), false, &proj_matrix[..]); | ||
self.context.uniform_matrix4fv(Some(&self.v_matrix), false, &self.view_matrix[..]); | ||
self.context.uniform_matrix4fv(Some(&self.m_matrix), false, &self.mov_matrix[..]); | ||
self.context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, Some(&self.index_buffer)); | ||
self.context.draw_elements(gl::TRIANGLES, 36, gl::UNSIGNED_SHORT, 0); | ||
|
||
window().request_animation_frame(move |time| { | ||
rc.borrow_mut().animate(time, rc.clone()); | ||
}); | ||
} | ||
} | ||
|
||
fn main() { | ||
stdweb::initialize(); | ||
|
||
let canvas: CanvasElement = document().query_selector( "#canvas" ).unwrap().unwrap().try_into().unwrap(); | ||
let context: gl = canvas.get_context().unwrap(); | ||
|
||
canvas.set_width(canvas.offset_width() as u32); | ||
canvas.set_height(canvas.offset_height() as u32); | ||
|
||
context.clear_color(1.0, 0.0, 0.0, 1.0); | ||
context.clear(gl::COLOR_BUFFER_BIT); | ||
|
||
window().add_event_listener( enclose!( (canvas) move |_: ResizeEvent| { | ||
canvas.set_width(canvas.offset_width() as u32); | ||
canvas.set_height(canvas.offset_height() as u32); | ||
})); | ||
|
||
let vertices = TypedArray::<f32>::from(&[ | ||
-1.,-1.,-1., 1.,-1.,-1., 1., 1.,-1., -1., 1.,-1., | ||
-1.,-1., 1., 1.,-1., 1., 1., 1., 1., -1., 1., 1., | ||
-1.,-1.,-1., -1., 1.,-1., -1., 1., 1., -1.,-1., 1., | ||
1.,-1.,-1., 1., 1.,-1., 1., 1., 1., 1.,-1., 1., | ||
-1.,-1.,-1., -1.,-1., 1., 1.,-1., 1., 1.,-1.,-1., | ||
-1., 1.,-1., -1., 1., 1., 1., 1., 1., 1., 1.,-1., | ||
][..]).buffer(); | ||
|
||
let colors = TypedArray::<f32>::from(&[ | ||
5.,3.,7., 5.,3.,7., 5.,3.,7., 5.,3.,7., | ||
1.,1.,3., 1.,1.,3., 1.,1.,3., 1.,1.,3., | ||
0.,0.,1., 0.,0.,1., 0.,0.,1., 0.,0.,1., | ||
1.,0.,0., 1.,0.,0., 1.,0.,0., 1.,0.,0., | ||
1.,1.,0., 1.,1.,0., 1.,1.,0., 1.,1.,0., | ||
0.,1.,0., 0.,1.,0., 0.,1.,0., 0.,1.,0. | ||
][..]).buffer(); | ||
|
||
let indices = TypedArray::<u16>::from(&[ | ||
0,1,2, 0,2,3, 4,5,6, 4,6,7, | ||
8,9,10, 8,10,11, 12,13,14, 12,14,15, | ||
16,17,18, 16,18,19, 20,21,22, 20,22,23 | ||
][..]).buffer(); | ||
|
||
// Create and store data into vertex buffer | ||
let vertex_buffer = context.create_buffer().unwrap(); | ||
context.bind_buffer(gl::ARRAY_BUFFER, Some(&vertex_buffer)); | ||
context.buffer_data_1(gl::ARRAY_BUFFER, Some(&vertices), gl::STATIC_DRAW); | ||
|
||
// Create and store data into color buffer | ||
let color_buffer = context.create_buffer().unwrap(); | ||
context.bind_buffer(gl::ARRAY_BUFFER, Some(&color_buffer)); | ||
context.buffer_data_1(gl::ARRAY_BUFFER, Some(&colors), gl::STATIC_DRAW); | ||
|
||
// Create and store data into index buffer | ||
let index_buffer = context.create_buffer().unwrap(); | ||
context.bind_buffer(gl::ELEMENT_ARRAY_BUFFER, Some(&index_buffer)); | ||
context.buffer_data_1(gl::ELEMENT_ARRAY_BUFFER, Some(&indices), gl::STATIC_DRAW); | ||
|
||
/*=================== Shaders =========================*/ | ||
let vert_code = r#" | ||
attribute vec3 position; | ||
uniform mat4 Pmatrix; | ||
uniform mat4 Vmatrix; | ||
uniform mat4 Mmatrix; | ||
attribute vec3 color; | ||
varying vec3 vColor; | ||
void main() { | ||
gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.); | ||
vColor = color; | ||
} | ||
"#; | ||
|
||
let frag_code = r#" | ||
precision mediump float; | ||
varying vec3 vColor; | ||
void main() { | ||
gl_FragColor = vec4(vColor, 1.); | ||
} | ||
"#; | ||
|
||
let vert_shader = context.create_shader(gl::VERTEX_SHADER).unwrap(); | ||
context.shader_source(&vert_shader, vert_code); | ||
context.compile_shader(&vert_shader); | ||
|
||
let frag_shader = context.create_shader(gl::FRAGMENT_SHADER).unwrap(); | ||
context.shader_source(&frag_shader, frag_code); | ||
context.compile_shader(&frag_shader); | ||
|
||
let shader_program = context.create_program().unwrap(); | ||
context.attach_shader(&shader_program, &vert_shader); | ||
context.attach_shader(&shader_program, &frag_shader); | ||
context.link_program(&shader_program); | ||
|
||
/* ====== Associating attributes to vertex shader =====*/ | ||
let p_matrix = context.get_uniform_location(&shader_program, "Pmatrix").unwrap(); | ||
let v_matrix = context.get_uniform_location(&shader_program, "Vmatrix").unwrap(); | ||
let m_matrix = context.get_uniform_location(&shader_program, "Mmatrix").unwrap(); | ||
|
||
context.bind_buffer(gl::ARRAY_BUFFER, Some(&vertex_buffer)); | ||
let position = context.get_attrib_location(&shader_program, "position") as u32; | ||
context.vertex_attrib_pointer(position, 3, gl::FLOAT, false, 0, 0) ; | ||
|
||
// Position | ||
context.enable_vertex_attrib_array(position); | ||
context.bind_buffer(gl::ARRAY_BUFFER, Some(&color_buffer)); | ||
let color = context.get_attrib_location(&shader_program, "color") as u32; | ||
context.vertex_attrib_pointer(color, 3, gl::FLOAT, false, 0, 0) ; | ||
|
||
// Color | ||
context.enable_vertex_attrib_array(color); | ||
context.use_program(Some(&shader_program)); | ||
|
||
let mov_matrix = [1.,0.,0.,0., 0.,1.,0.,0., 0.,0.,1.,0., 0.,0.,0.,1.]; | ||
let mut view_matrix = [1.,0.,0.,0., 0.,1.,0.,0., 0.,0.,1.,0., 0.,0.,0.,1.]; | ||
|
||
// translating z | ||
view_matrix[14] -= 6.; //zoom | ||
|
||
let state = Rc::new(RefCell::new(State { | ||
time_old: 0.0, | ||
mov_matrix, | ||
view_matrix, | ||
canvas, | ||
context, | ||
p_matrix, | ||
v_matrix, | ||
m_matrix, | ||
index_buffer, | ||
})); | ||
|
||
state.borrow_mut().animate(0., state.clone()); | ||
|
||
stdweb::event_loop(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#![allow(dead_code, unused_parens, unused_imports)] | ||
|
||
include!(concat!(env!("OUT_DIR"), "/webgl_rendering_context.rs")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>stdweb • WebGL</title> | ||
<style> | ||
html, body, canvas { | ||
margin: 0px; | ||
padding: 0px; | ||
width: 100%; | ||
height: 100%; | ||
overflow: hidden; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<canvas id="canvas"></canvas> | ||
<script src="js/app.js"></script> | ||
</body> | ||
</html> |