</head>
<body style="background: black">
- <canvas id="gamecanvas" width="800" height="600">No canvas for you.</canvas>
+ <canvas id="gamecanvas" width="1200" height="1200">No canvas for you.</canvas>
</body>
</html>
});
}
-fetch("game.wasm")
+//fetch("game.wasm")
+fetch("out.wasm")
.then(res => res.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(main);
--- /dev/null
+package gfx
+
+use package core
+use package gl as gl
+use package gl_utils as gl_utils
+
+Vec2 :: struct {
+ x : f32;
+ y : f32;
+}
+
+QuadRenderer :: struct {
+ is_initialized : bool = false;
+
+ quad_data : [..] Quad;
+
+ vertexArray : gl.GLVertexArrayObject;
+ vertexBuffer : gl.GLBuffer;
+ indexBuffer : gl.GLBuffer;
+ quadBuffer : gl.GLBuffer;
+
+ program : gl.GLProgram;
+}
+
+Quad :: struct {
+ x : f32;
+ y : f32;
+ w : f32;
+ h : f32;
+ r : f32;
+ g : f32;
+ b : f32;
+}
+
+quad_renderer_init :: proc (use qr: ^QuadRenderer, initial_quads := 10) {
+ vertexArray = gl.createVertexArray();
+ gl.bindVertexArray(vertexArray);
+
+ // Set up vertex and index data
+ vertex_data : [4] Vec2;
+ vertex_data[0] = Vec2.{ 0.0f, 0.0f };
+ vertex_data[1] = Vec2.{ 0.0f, 1.0f };
+ vertex_data[2] = Vec2.{ 1.0f, 1.0f };
+ vertex_data[3] = Vec2.{ 1.0f, 0.0f };
+
+ vertexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, Buffer.{
+ count = sizeof [4] Vec2,
+ data = cast(^void) vertex_data
+ }, gl.STATIC_DRAW);
+
+ gl.enableVertexAttribArray(0);
+ gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 2 * sizeof gl.GLfloat, 0);
+ gl.bindBuffer(gl.ARRAY_BUFFER, -1);
+
+ array_init(^quad_data, initial_quads);
+
+ for i: 0, initial_quads {
+ array_push(^quad_data, Quad.{
+ x = cast(f32) random_between(0, 1000) / 1000.0f,
+ y = cast(f32) random_between(0, 1000) / 1000.0f,
+ w = 0.1f,
+ h = 0.1f,
+ r = 1.0f,
+ g = 0.0f,
+ b = 0.0f,
+ });
+ }
+
+ quadBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
+ gl.bufferData(gl.ARRAY_BUFFER, Buffer.{
+ count = sizeof Quad * quad_data.count,
+ data = cast(^void) quad_data.data,
+ }, gl.DYNAMIC_DRAW);
+
+ gl.enableVertexAttribArray(1);
+ gl.enableVertexAttribArray(2);
+ gl.enableVertexAttribArray(3);
+ gl.vertexAttribDivisor(1, 1);
+ gl.vertexAttribDivisor(2, 1);
+ gl.vertexAttribDivisor(3, 1);
+ gl.vertexAttribPointer(1, 2, gl.FLOAT, false, sizeof Quad, 0);
+ gl.vertexAttribPointer(2, 2, gl.FLOAT, false, sizeof Quad, 2 * sizeof f32);
+ gl.vertexAttribPointer(3, 3, gl.FLOAT, false, sizeof Quad, 4 * sizeof f32);
+ gl.bindBuffer(gl.ARRAY_BUFFER, -1);
+
+ index_data : [6] gl.GLubyte;
+ index_data[0] = cast(gl.GLubyte) 0;
+ index_data[1] = cast(gl.GLubyte) 1;
+ index_data[2] = cast(gl.GLubyte) 2;
+ index_data[3] = cast(gl.GLubyte) 0;
+ index_data[4] = cast(gl.GLubyte) 2;
+ index_data[5] = cast(gl.GLubyte) 3;
+
+ indexBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+ gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, Buffer.{
+ count = sizeof [6] gl.GLubyte,
+ data = cast(^void) index_data,
+ }, gl.STATIC_DRAW);
+
+ gl.bindVertexArray(-1);
+
+ vertex_shader := gl_utils.compile_shader(gl.VERTEX_SHADER, #file_contents "./src/shaders/basic.vert");
+ fragment_shader := gl_utils.compile_shader(gl.FRAGMENT_SHADER, #file_contents "./src/shaders/basic.frag");
+ program = gl_utils.link_program(vertex_shader, fragment_shader);
+ gl.useProgram(program);
+
+ u_proj_loc := gl.getUniformLocation(program, "u_proj");
+ proj_mat : [9] gl.GLfloat;
+ proj_mat[3 * 0 + 0] = 2.0f;
+ proj_mat[3 * 0 + 1] = 0.0f;
+ proj_mat[3 * 0 + 2] = 0.0f;
+ proj_mat[3 * 1 + 0] = 0.0f;
+ proj_mat[3 * 1 + 1] = -2.0f;
+ proj_mat[3 * 1 + 2] = 0.0f;
+ proj_mat[3 * 2 + 0] = -1.0f;
+ proj_mat[3 * 2 + 1] = 1.0f;
+ proj_mat[3 * 2 + 2] = 1.0f;
+
+ gl.uniformMatrix3(u_proj_loc, false, proj_mat);
+}
+
+quad_renderer_draw :: proc (use qr: ^QuadRenderer) {
+ gl.bindVertexArray(vertexArray);
+ gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, quad_data.count);
+ gl.bindVertexArray(-1);
+}
+
+quad_update_at_index :: proc (use qr: ^QuadRenderer, idx: i32, quad: Quad) {
+ quad_data[idx] = quad;
+}
+
+quad_rebuffer_data :: proc (use qr: ^QuadRenderer) {
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, Buffer.{
+ count = quad_data.count * sizeof Quad,
+ data = cast(^void) quad_data.data,
+ });
+ gl.bindBuffer(gl.ARRAY_BUFFER, -1);
+}
#include_file "core/std/js"
#include_file "core/js/webgl"
+#include_folder "src/"
+#include_file "utils/gl"
+#include_file "gfx/quad_renderer"
+
use package core
+use package gfx
use package gl as gl
-Vec2 :: struct {
- x : f32;
- y : f32;
-}
-
-// print_vec2 :: proc (v: Vec2) #add_overload print {
-// print("Vec2(");
-// print(v.x);
-// print(", ");
-// print(v.y);
-// print(")");
-// }
-
-
GameState :: struct {
dummy : i32;
+ quad_renderer : QuadRenderer;
}
-update :: proc (gs: ^GameState) {
+update :: proc (use gs: ^GameState) {
+ for i: 0, 10000 {
+ quad_update_at_index(^quad_renderer, i, Quad.{
+ x = cast(f32) random_between(0, 100) / 100.0f,
+ y = cast(f32) random_between(0, 100) / 100.0f,
+ w = cast(f32) random_between(1, 10) / 1000.0f,
+ h = cast(f32) random_between(1, 10) / 1000.0f,
+ r = cast(f32) random_between(0, 255) / 255.0f,
+ g = cast(f32) random_between(0, 255) / 255.0f,
+ b = cast(f32) random_between(0, 255) / 255.0f,
+ // r = 0.0f, g = 0.0f, b = 1.0f
+ });
+ }
}
-draw :: proc (gs: ^GameState) {
+draw :: proc (use gs: ^GameState) {
gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.clear(gl.COLOR_BUFFER_BIT);
- gl.bindVertexArray(vao);
- gl.drawElementsInstanced(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0, NUM_QUADS);
- gl.bindVertexArray(-1);
+ quad_rebuffer_data(^quad_renderer);
+ quad_renderer_draw(^quad_renderer);
}
// This procedure is called asynchronously from JS.
draw(gs);
}
-NUM_QUADS :: 500
-vao : gl.GLVertexArrayObject
-
-compile_shader :: proc (shader_type: gl.GLenum, source: cstring) -> gl.GLShader {
- shader := gl.createShader(shader_type);
- gl.shaderSource(shader, string_make(source));
- gl.compileShader(shader);
-
- if cast(i32) gl.getShaderParameter(shader, gl.COMPILE_STATUS) == 0 {
- gl.printShaderInfoLog(shader);
- return -1;
- }
-
- return shader;
-}
-
-link_program :: proc (vertex_shader: gl.GLShader, frag_shader: gl.GLShader) -> gl.GLProgram {
- program := gl.createProgram();
- gl.attachShader(program, vertex_shader);
- gl.attachShader(program, frag_shader);
- gl.linkProgram(program);
-
- if cast(i32) gl.getProgramParameter(program, gl.LINK_STATUS) == 0 {
- gl.printProgramInfoLog(program);
- return -1;
- }
-
- return program;
-}
-
-setup_drawing :: proc {
- vao = gl.createVertexArray();
- gl.bindVertexArray(vao);
-
- vertex_data : [8] gl.GLfloat;
- vertex_data[2 * 0 + 0] = 0.0f;
- vertex_data[2 * 0 + 1] = 0.0f;
- vertex_data[2 * 1 + 0] = 0.0f;
- vertex_data[2 * 1 + 1] = 0.1f;
- vertex_data[2 * 2 + 0] = 0.1f;
- vertex_data[2 * 2 + 1] = 0.1f;
- vertex_data[2 * 3 + 0] = 0.1f;
- vertex_data[2 * 3 + 1] = 0.0f;
-
- vertex_buffer := gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);
- gl.bufferData(gl.ARRAY_BUFFER, Buffer.{
- count = sizeof [8] gl.GLfloat,
- data = cast(^void) vertex_data
- }, gl.STATIC_DRAW);
-
- gl.enableVertexAttribArray(0);
- gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 2 * sizeof gl.GLfloat, 0);
-
- pos_buffer := gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, pos_buffer);
-
- positions : [..] Vec2;
- array_init(^positions, NUM_QUADS);
- defer array_free(^positions);
-
- for i: 0, NUM_QUADS {
- array_push(^positions, Vec2.{
- x = cast(f32) random_between(0, 50) / 50.0f,
- y = cast(f32) random_between(0, 50) / 50.0f,
- });
- }
-
- gl.bufferData(gl.ARRAY_BUFFER, Buffer.{
- count = NUM_QUADS * sizeof Vec2,
- data = cast(^void) positions.data,
- }, gl.DYNAMIC_DRAW);
-
- gl.enableVertexAttribArray(1);
- gl.vertexAttribDivisor(1, 1);
- gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 2 * sizeof gl.GLfloat, 0);
-
- index_data : [6] gl.GLubyte;
- index_data[0] = cast(gl.GLubyte) 0;
- index_data[1] = cast(gl.GLubyte) 1;
- index_data[2] = cast(gl.GLubyte) 2;
- index_data[3] = cast(gl.GLubyte) 0;
- index_data[4] = cast(gl.GLubyte) 2;
- index_data[5] = cast(gl.GLubyte) 3;
-
- index_buffer := gl.createBuffer();
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, index_buffer);
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, Buffer.{
- count = sizeof [6] gl.GLubyte,
- data = cast(^void) index_data,
- }, gl.STATIC_DRAW);
-
- gl.bindVertexArray(-1);
-
- vertex_shader := compile_shader(gl.VERTEX_SHADER, #file_contents "./src/shaders/basic.vert");
- fragment_shader := compile_shader(gl.FRAGMENT_SHADER, #file_contents "./src/shaders/basic.frag");
- program := link_program(vertex_shader, fragment_shader);
- gl.useProgram(program);
-
- u_proj_loc := gl.getUniformLocation(program, "u_proj");
- proj_mat : [9] gl.GLfloat;
- proj_mat[3 * 0 + 0] = 2.0f;
- proj_mat[3 * 0 + 1] = 0.0f;
- proj_mat[3 * 0 + 2] = 0.0f;
- proj_mat[3 * 1 + 0] = 0.0f;
- proj_mat[3 * 1 + 1] = -2.0f;
- proj_mat[3 * 1 + 2] = 0.0f;
- proj_mat[3 * 2 + 0] = -1.0f;
- proj_mat[3 * 2 + 1] = 1.0f;
- proj_mat[3 * 2 + 2] = 1.0f;
-
- gl.uniformMatrix3(u_proj_loc, false, proj_mat);
+setup_drawing :: proc (use state: ^GameState) {
+ quad_renderer_init(^quad_renderer, 10000);
}
-
main :: proc (args: [] cstring) {
- print("Hello, World!\n");
+ print("Setting up WebGL2 canvas...\n");
if !gl.init("gamecanvas") {
print("Failed to initialize GL canvas.");
return;
}
- setup_drawing();
-
gs := cast(^GameState) calloc(sizeof GameState);
+ setup_drawing(gs);
+
game_launch(gs);
}
precision mediump float;
+in vec3 v_col;
+
out vec4 fragColor;
void main() {
- fragColor = vec4(1, 0, 1, 1);
+ fragColor = vec4(v_col, 1);
}
layout(location = 0) in vec2 a_vert_pos;
layout(location = 1) in vec2 a_pos;
+layout(location = 2) in vec2 a_size;
+layout(location = 3) in vec3 a_col;
uniform mat3 u_proj;
+out vec3 v_col;
+
void main() {
- gl_Position = vec4(u_proj * vec3(a_vert_pos + a_pos, 1), 1);
-}
\ No newline at end of file
+ gl_Position = vec4(u_proj * vec3(a_vert_pos * a_size + a_pos, 1), 1);
+ v_col = a_col;
+}
--- /dev/null
+package gl_utils
+
+use package core { string_make }
+use package gl as gl
+
+compile_shader :: proc (shader_type: gl.GLenum, source: cstring) -> gl.GLShader {
+ shader := gl.createShader(shader_type);
+ gl.shaderSource(shader, string_make(source));
+ gl.compileShader(shader);
+
+ if cast(i32) gl.getShaderParameter(shader, gl.COMPILE_STATUS) == 0 {
+ gl.printShaderInfoLog(shader);
+ return -1;
+ }
+
+ return shader;
+}
+
+link_program :: proc (vertex_shader: gl.GLShader, frag_shader: gl.GLShader) -> gl.GLProgram {
+ program := gl.createProgram();
+ gl.attachShader(program, vertex_shader);
+ gl.attachShader(program, frag_shader);
+ gl.linkProgram(program);
+
+ if cast(i32) gl.getProgramParameter(program, gl.LINK_STATUS) == 0 {
+ gl.printProgramInfoLog(program);
+ return -1;
+ }
+
+ return program;
+}
+