wasm/webgl/webgl_triangle Web

Code

main.odin ¶
113 linesSource

1// Shows how to draw a triangle using WASM + WebGL. Build using the build_web script. Note that
2// there is an index.html in the web folder and that the `odin.js` runtime file will be copied from
3// the Odin core folder into the web folder (by the build_web script).
4
5package webgl_triangle
6
7import "core:sys/wasm/js"
8import gl "vendor:wasm/WebGL"
9
10// The ID of the element in web/index.html to draw into
11CANVAS_ID :: "webgl-canvas"
12
13shader: gl.Program
14vertex_buffer: gl.Buffer
15
16// Run on strartup. But there is no "main loop" in here. Instead, frame "tick" is handled by the `step` proc.
17main :: proc() {
18	js.add_window_event_listener(.Resize, nil, resize_callback)
19	gl.CreateCurrentContextById(CANVAS_ID, gl.DEFAULT_CONTEXT_ATTRIBUTES)
20	gl.SetCurrentContextById(CANVAS_ID)
21	shader = gl.CreateProgramFromStrings({SHADER_VERT}, {SHADER_FRAG}) or_else panic("Failed loading shader")
22
23	vertex_buffer = gl.CreateBuffer()
24	gl.BindBuffer(gl.ARRAY_BUFFER, vertex_buffer)
25	gl.BufferData(gl.ARRAY_BUFFER, size_of(triangle_vertices), raw_data(&triangle_vertices), gl.DYNAMIC_DRAW)
26
27	// Tell shader where it can find the in_position and in_color vertex attributes
28	attr_pos := gl.GetAttribLocation(shader, "in_position")
29	gl.EnableVertexAttribArray(attr_pos)
30	gl.VertexAttribPointer(attr_pos, 3, gl.FLOAT, false, size_of(Vertex), offset_of(Vertex, pos))
31
32	attr_col := gl.GetAttribLocation(shader, "in_color")
33	gl.EnableVertexAttribArray(attr_col)
34	gl.VertexAttribPointer(attr_col, 4, gl.UNSIGNED_BYTE, true, size_of(Vertex), offset_of(Vertex, color))
35
36	update_canvas_size()
37	gl.Disable(gl.DEPTH_TEST)
38	gl.Enable(gl.BLEND)
39	gl.Enable(gl.CULL_FACE)
40	gl.CullFace(gl.BACK)
41	gl.FrontFace(gl.CW)
42	gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
43}
44
45// A proc named "step" is automatically run by Odin JS runtime if exported.
46@(export)
47step :: proc(dt: f32) -> bool {
48	gl.ClearColor(0, 0, 0, 1)
49	gl.Clear(u32(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT))
50	gl.UseProgram(shader)
51	gl.DrawArrays(gl.TRIANGLES, 0, len(triangle_vertices))
52	return true
53}
54
55Vertex :: struct {
56	pos: [3]f32,
57	color: [4]u8,
58}
59
60triangle_vertices := [3]Vertex {
61	{
62		pos = {  0.0,  0.5, 0.0 },
63		color = {255, 0, 0, 255},
64	},
65	{
66		pos = { 0.5, -0.5, 0.0 },
67		color = { 0, 255, 0, 255 },
68	},
69	{
70		pos = { -0.5, -0.5, 0.0 },
71		color = { 0, 0, 255, 255 },
72	},
73}
74
75update_canvas_size :: proc() {
76	rect := js.get_bounding_client_rect(CANVAS_ID)
77	dpi := js.device_pixel_ratio()
78
79	width := f64(rect.width) * dpi
80	height := f64(rect.height) * dpi
81
82	js.set_element_key_f64(CANVAS_ID, "width", width)
83	js.set_element_key_f64(CANVAS_ID, "height", height)
84	gl.Viewport(0, 0, i32(width), i32(height))
85}
86
87resize_callback :: proc(e: js.Event) {
88	update_canvas_size()
89}
90
91SHADER_VERT :: `
92precision highp float;
93
94attribute vec3 in_position;
95attribute vec4 in_color;
96
97varying vec4 color;
98
99void main() {
100	color = in_color;
101	gl_Position = vec4(in_position, 1.0);
102}
103`
104
105SHADER_FRAG :: `
106precision highp float;
107
108varying vec4 color;
109
110void main() {
111	gl_FragColor = color;
112}
113`

To Build and Run 3

Declarations Used 41