Skip to content

Commit 4ca187c

Browse files
authored
Merge pull request #835 from blm768/webgl-example
Create basic WebGL example
2 parents 35f5127 + 426671d commit 4ca187c

File tree

12 files changed

+247
-0
lines changed

12 files changed

+247
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ members = [
7878
"examples/smorgasboard",
7979
"examples/wasm-in-wasm",
8080
"examples/webaudio",
81+
"examples/webgl",
8182
"tests/no-std",
8283
]
8384

examples/webgl/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package-lock.json
2+
wasm_bindgen_webgl_demo.js
3+
wasm_bindgen_webgl_demo_bg.js
4+
wasm_bindgen_webgl_demo_bg.wasm

examples/webgl/Cargo.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
name = "wasm-bindgen-webgl-demo"
3+
version = "0.1.0"
4+
authors = ["The wasm-bindgen Developers"]
5+
6+
[lib]
7+
crate-type = ["cdylib"]
8+
9+
[dependencies]
10+
js-sys = { path = "../../crates/js-sys" }
11+
wasm-bindgen = { path = "../.." }
12+
13+
[dependencies.web-sys]
14+
path = "../../crates/web-sys"
15+
features = [
16+
'Document',
17+
'Element',
18+
'HtmlCanvasElement',
19+
'WebGlBuffer',
20+
'WebGlRenderingContext',
21+
'WebGlProgram',
22+
'WebGlShader',
23+
'Window',
24+
]

examples/webgl/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# WebGL Example
2+
3+
This directory is an example of using the `web-sys` crate to interact with
4+
a WebGL context.
5+
6+
You can build and run the example with:
7+
8+
```
9+
$ ./build.sh
10+
```
11+
12+
(or running the commands on Windows manually)
13+
14+
and then opening up `http://localhost:8080/` in a web browser should show a
15+
nice triangle.

examples/webgl/build.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/sh
2+
3+
# For more coments about what's going on here, see the `hello_world` example
4+
5+
set -ex
6+
cd "$(dirname $0)"
7+
8+
cargo +nightly build --target wasm32-unknown-unknown
9+
10+
cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \
11+
--bin wasm-bindgen -- \
12+
../../target/wasm32-unknown-unknown/debug/wasm_bindgen_webgl_demo.wasm --out-dir .
13+
14+
npm install
15+
npm run serve

examples/webgl/index.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<html>
2+
<head>
3+
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
4+
</head>
5+
<body>
6+
<canvas id="canvas" height="150" width="150" />
7+
<script src='./index.js'></script>
8+
</body>
9+
</html>

examples/webgl/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// For more comments about what's going on here, check out the `hello_world`
2+
// example.
3+
import('./wasm_bindgen_webgl_demo').then(webgl => {
4+
webgl.draw();
5+
});

examples/webgl/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"scripts": {
3+
"serve": "webpack-dev-server"
4+
},
5+
"devDependencies": {
6+
"html-webpack-plugin": "^3.2.0",
7+
"webpack": "^4.11.1",
8+
"webpack-cli": "^2.0.10",
9+
"webpack-dev-server": "^3.1.0"
10+
}
11+
}

examples/webgl/src/lib.rs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
extern crate js_sys;
2+
extern crate wasm_bindgen;
3+
extern crate web_sys;
4+
5+
use wasm_bindgen::prelude::*;
6+
use wasm_bindgen::JsCast;
7+
use web_sys::{WebGlProgram, WebGlRenderingContext, WebGlShader};
8+
9+
#[wasm_bindgen]
10+
pub fn draw() {
11+
let document = web_sys::Window::document().unwrap();
12+
let canvas = document.get_element_by_id("canvas").unwrap();
13+
let canvas: web_sys::HtmlCanvasElement = canvas
14+
.dyn_into::<web_sys::HtmlCanvasElement>()
15+
.map_err(|_| ())
16+
.unwrap();
17+
18+
let context = canvas
19+
.get_context("webgl")
20+
.unwrap()
21+
.unwrap()
22+
.dyn_into::<WebGlRenderingContext>()
23+
.unwrap();
24+
25+
let vert_shader = compile_shader(
26+
&context,
27+
WebGlRenderingContext::VERTEX_SHADER,
28+
r#"
29+
attribute vec4 position;
30+
void main() {
31+
gl_Position = position;
32+
}
33+
"#,
34+
).unwrap();
35+
let frag_shader = compile_shader(
36+
&context,
37+
WebGlRenderingContext::FRAGMENT_SHADER,
38+
r#"
39+
void main() {
40+
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
41+
}
42+
"#,
43+
).unwrap();
44+
let program = link_program(&context, [vert_shader, frag_shader].iter()).unwrap();
45+
context.use_program(Some(&program));
46+
47+
let vertices = [-0.7, -0.7, 0.0, 0.7, -0.7, 0.0, 0.0, 0.7, 0.0];
48+
let vert_array = js_sys::Float32Array::new(&wasm_bindgen::JsValue::from(vertices.len() as u32));
49+
for (i, f) in vertices.iter().enumerate() {
50+
vert_array.fill(*f, i as u32, (i + 1) as u32);
51+
}
52+
53+
let buffer = context.create_buffer().unwrap();
54+
context.bind_buffer(WebGlRenderingContext::ARRAY_BUFFER, Some(&buffer));
55+
context.buffer_data_with_opt_array_buffer(
56+
WebGlRenderingContext::ARRAY_BUFFER,
57+
Some(&vert_array.buffer()),
58+
WebGlRenderingContext::STATIC_DRAW,
59+
);
60+
context.vertex_attrib_pointer_with_i32(0,
61+
3,
62+
WebGlRenderingContext::FLOAT,
63+
false,
64+
0,
65+
0);
66+
context.enable_vertex_attrib_array(0);
67+
68+
context.clear_color(0.0, 0.0, 0.0, 1.0);
69+
context.clear(WebGlRenderingContext::COLOR_BUFFER_BIT);
70+
71+
context.draw_arrays(WebGlRenderingContext::TRIANGLES, 0, (vertices.len() / 3) as i32);
72+
}
73+
74+
pub fn compile_shader(
75+
context: &WebGlRenderingContext,
76+
shader_type: u32,
77+
source: &str,
78+
) -> Result<WebGlShader, String> {
79+
let shader = context
80+
.create_shader(shader_type)
81+
.ok_or_else(|| String::from("Unable to create shader object"))?;
82+
context.shader_source(&shader, source);
83+
context.compile_shader(&shader);
84+
85+
if context
86+
.get_shader_parameter(&shader, WebGlRenderingContext::COMPILE_STATUS)
87+
.as_bool()
88+
.unwrap_or(false)
89+
{
90+
Ok(shader)
91+
} else {
92+
Err(context
93+
.get_shader_info_log(&shader)
94+
.unwrap_or_else(|| "Unknown error creating shader".into()))
95+
}
96+
}
97+
98+
pub fn link_program<'a, T: IntoIterator<Item = &'a WebGlShader>>(
99+
context: &WebGlRenderingContext,
100+
shaders: T,
101+
) -> Result<WebGlProgram, String> {
102+
let program = context
103+
.create_program()
104+
.ok_or_else(|| String::from("Unable to create shader object"))?;
105+
for shader in shaders {
106+
context.attach_shader(&program, shader)
107+
}
108+
context.link_program(&program);
109+
110+
if context
111+
.get_program_parameter(&program, WebGlRenderingContext::LINK_STATUS)
112+
.as_bool()
113+
.unwrap_or(false)
114+
{
115+
Ok(program)
116+
} else {
117+
Err(context
118+
.get_program_info_log(&program)
119+
.unwrap_or_else(|| "Unknown error creating program object".into()))
120+
}
121+
}

examples/webgl/webpack.config.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
const path = require('path');
2+
const HtmlWebpackPlugin = require('html-webpack-plugin');
3+
4+
module.exports = {
5+
entry: './index.js',
6+
output: {
7+
path: path.resolve(__dirname, 'dist'),
8+
filename: 'index.js',
9+
},
10+
plugins: [
11+
new HtmlWebpackPlugin({
12+
template: "index.html"
13+
})
14+
],
15+
mode: 'development'
16+
};

guide/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
- [The `fetch` API](./web-sys/examples/fetch.md)
6363
- [2D Canvas](./web-sys/examples/2d-canvas.md)
6464
- [WebAudio](./web-sys/examples/web-audio.md)
65+
- [WebGL](./web-sys/examples/webgl.md)
6566
- [A Simple Paint Program](./web-sys/examples/paint.md)
6667

6768
--------------------------------------------------------------------------------

guide/src/web-sys/examples/webgl.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# 2D Canvas
2+
3+
This example draws a triangle to the screen using the WebGL API.
4+
5+
[See the full source at
6+
`wasm-bindgen/examples/webgl`.](https://github.com/rustwasm/wasm-bindgen/tree/master/examples/webgl)
7+
8+
## `Cargo.toml`
9+
10+
The `Cargo.toml` enables features necessary to obtain and use a WebGL
11+
rendering context.
12+
13+
```toml
14+
{{#include ../../../../examples/webgl/Cargo.toml}}
15+
```
16+
17+
## `src/lib.rs`
18+
19+
This source file handles all of the necessary logic to obtain a rendering
20+
context, compile shaders, fill a buffer with vertex coordinates, and draw a
21+
triangle to the screen.
22+
23+
```rust
24+
{{#include ../../../../examples/webgl/src/lib.rs}}
25+
```

0 commit comments

Comments
 (0)