transparent-cube

Minimal cross-platform native/wasm graphics example.
git clone git://git.amin.space/transparent-cube.git
Log | Files | Refs | README | LICENSE

platform_wasm_loader.js (8109B)


      1 let utf8decoder = new TextDecoder("utf-8");
      2 let memory = null;
      3 let exports = {};
      4 let imports = {};
      5 let files = [];
      6 let gl = null;
      7 let gl_id_freelist = [];
      8 let gl_id_map = [null];
      9 imports["webglAttachShader"] = function(program_id, shader_id) {
     10     let program = gl_id_map[program_id];
     11     let shader = gl_id_map[shader_id];
     12     gl.attachShader(program, shader);
     13 }
     14 imports["webglBindBuffer"] = function(target, buffer_id) {
     15     let buffer = gl_id_map[buffer_id];
     16     gl.bindBuffer(target, buffer);
     17 }
     18 imports["webglBindVertexArray"] = function(vao_id) {
     19     let vao = gl_id_map[vao_id];
     20     gl.bindVertexArray(vao);
     21 }
     22 imports["webglBlendColor"] = function(red, green, blue, alpha) {
     23     gl.blendColor(red, green, blue, alpha);
     24 }
     25 imports["webglBlendFunc"] = function(sfactor, dfactor) {
     26     gl.blendFunc(sfactor, dfactor);
     27 }
     28 imports["webglBufferData"] = function(target, size, data, usage) {
     29     let dataslice = memory.subarray(data, data + size);
     30     gl.bufferData(target, dataslice, usage);
     31 }
     32 imports["webglClear"] = function(mask) {
     33     gl.clear(mask);
     34 }
     35 imports["webglClearColor"] = function(red, green, blue, alpha) {
     36     gl.clearColor(red, green, blue, alpha);
     37 }
     38 imports["webglCompileShader"] = function(shader_id) {
     39     let shader = gl_id_map[shader_id];
     40     gl.compileShader(shader);
     41 }
     42 imports["webglCreateBuffer"] = function() {
     43     let buffer = gl.createBuffer();
     44     let buffer_id = webgl_id_new(buffer);
     45     return buffer_id
     46 }
     47 imports["webglCreateProgram"] = function() {
     48     let program = gl.createProgram();
     49     let program_id = webgl_id_new(program);
     50     return program_id;
     51 }
     52 imports["webglCreateShader"] = function(type) {
     53     let shader = gl.createShader(type);
     54     let shader_id = webgl_id_new(shader);
     55     return shader_id;
     56 }
     57 imports["webglCreateVertexArray"] = function() {
     58     let vao = gl.createVertexArray()
     59     let vao_id = webgl_id_new(vao);
     60     return vao_id
     61 }
     62 imports["webglDeleteBuffer"] = function(buffer_id) {
     63     let buffer = gl_id_map[buffer_id];
     64     gl.deleteBuffer(buffer);
     65     webgl_id_remove(buffer_id);
     66 }
     67 imports["webglDeleteShader"] = function(shader_id) {
     68     let shader = gl_id_map[shader_id];
     69     gl.deleteShader(shader);
     70     webgl_id_remove(shader_id);
     71 }
     72 imports["webglDeleteVertexArray"] = function(vao_id) {
     73     let vao = gl_id_map[vao_id];
     74     gl.deleteVertexArray(vao);
     75     webgl_id_remove(vao_id);
     76 }
     77 imports["webglDepthMask"] = function(flag) {
     78     gl.depthMask(flag);
     79 }
     80 imports["webglDisable"] = function(cap) {
     81     gl.disable(cap);
     82 }
     83 imports["webglDrawElements"] = function(mode, count, type, offset) {
     84     gl.drawElements(mode, count, type, offset);
     85 }
     86 imports["webglEnable"] = function(cap) {
     87     gl.enable(cap);
     88 }
     89 imports["webglEnableVertexAttribArray"] = function(index) {
     90     gl.enableVertexAttribArray(index);
     91 }
     92 imports["webglGetProgramInfoLog"] = function() {
     93 }
     94 imports["webglGetProgramParameter"] = function(program_id, param) {
     95     let program = gl_id_map[program_id];
     96     return gl.getProgramParameter(program, param);
     97 }
     98 imports["webglGetShaderInfoLog"] = function(shader_id, out_buf) {
     99     let shader = gl_id_map[shader_id];
    100     let info_log = gl.getShaderInfoLog(shader);
    101 
    102     // TODO: remove this once we get sprintf workingk
    103     console.log(info_log);
    104 
    105     let arr = memory.subarray(info_log, out_buf + info_log.byteLength);
    106     arr.set(new Uint8Array(info_log));
    107     return true;
    108 }
    109 imports["webglGetShaderParameter"] = function(shader_id, param) {
    110     let shader = gl_id_map[shader_id];
    111     let result = gl.getShaderParameter(shader, param);
    112     return result;
    113 }
    114 imports["webglGetUniformLocation"] = function(program_id, name_ptr, name_len) {
    115     let program = gl_id_map[program_id];
    116     let name = utf8decoder.decode(memory.subarray(name_ptr, name_ptr+name_len));
    117     let loc = gl.getUniformLocation(program, name);
    118     let location_id = webgl_id_new(loc);
    119     return location_id;
    120 }
    121 imports["webglLinkProgram"] = function(program_id) {
    122     let program = gl_id_map[program_id];
    123     gl.linkProgram(program);
    124 }
    125 imports["webglShaderSource"] = function(shader_id, source_ptr, source_len) {
    126     let shader = gl_id_map[shader_id];
    127     let arr = memory.subarray(source_ptr, source_ptr + source_len);
    128     let s = utf8decoder.decode(arr);
    129     gl.shaderSource(shader, s);
    130 }
    131 imports["webglUniform1f"] = function(location_id, value) {
    132     let loc = gl_id_map[location_id];
    133     gl['uniform1f'](loc, value);
    134 }
    135 imports["webglUniform1i"] = function(location_id, value) {
    136     let loc = gl_id_map[location_id];
    137     gl['uniform1i'](loc, value);
    138 }
    139 imports["webglUniform3f"] = function(location_id, x, y, z) {
    140     let loc = gl_id_map[location_id];
    141     gl['uniform3fv'](loc, [x, y, z]);
    142 }
    143 imports["webglUniformMatrix4fv"] = function(location_id, transpose, data) {
    144     let loc = gl_id_map[location_id];
    145     let dataslice = memory.slice(data, data + 4 * 16);
    146     gl.uniformMatrix4fv(loc, transpose, new Float32Array(dataslice.buffer));
    147 }
    148 imports["webglUseProgram"] = function(program_id) {
    149     let program = gl_id_map[program_id];
    150     gl.useProgram(program);
    151 }
    152 imports["webglVertexAttribPointer"] = function(index, size, type, normalized, stride, offset) {
    153     gl.vertexAttribPointer(index, size, type, normalized, stride, offset);
    154 }
    155 imports["webglViewport"] = function(x, y, width, height) {
    156     gl.viewport(x, y, width, height);
    157 }
    158 imports["js_read_entire_file"] = function(name, name_len, out_buf) {
    159     let file_name = utf8decoder.decode(memory.subarray(name, name + name_len))
    160     if (file_name == "shader/cube_f.glsl") {
    161         var file = files[1];
    162     } else if (file_name == "shader/cube_v.glsl") {
    163         var file = files[2];
    164     } else {
    165         return false;
    166     }
    167     let arr = memory.subarray(out_buf, out_buf + file.byteLength);
    168     let s = String.fromCharCode.apply(null, arr);
    169     arr.set(new Uint8Array(file));
    170     return true;
    171 }
    172 imports["js_print"] = function(s, len) {
    173     let arr = memory.subarray(s, s + len);
    174     console.log(utf8decoder.decode(arr));
    175 }
    176 function error_fatal(message) {
    177     console.log(message);
    178     throw message;
    179 }
    180 function webgl_id_new(obj) {
    181     if(gl_id_freelist.length == 0) {
    182         gl_id_map.push(obj);
    183         return gl_id_map.length - 1;
    184     } else {
    185         let id = gl_id_freelist.shift();
    186         gl_id_map[id] = obj;
    187         return id;
    188     }
    189 }
    190 function webgl_id_remove(id) {
    191     delete gl_id_map[id];
    192     gl_id_freelist.push(id);
    193 }
    194 function canvas_resize() {
    195     let pr = window.devicePixelRatio;
    196     let w = window.innerWidth;
    197     let h = window.innerHeight;
    198     // Bitwise OR does float truncation
    199     let w_pixels = (w * pr) | 0;
    200     let h_pixels = (h * pr) | 0;
    201     gl.canvas.width = w_pixels;
    202     gl.canvas.height = h_pixels
    203     exports['window_resize'](w_pixels, h_pixels);
    204     console.log("resize: (" + w_pixels + ", " + h_pixels + ")");
    205 }
    206 function canvas_render() {
    207     exports['render']();
    208     window.requestAnimationFrame(canvas_render);
    209 }
    210 function file_load(name) {
    211     let promise = new Promise((resolve, reject) => {
    212         fetch(name).then(resp => {
    213             resp.arrayBuffer().then(arr => resolve(arr));
    214         });
    215     });
    216     return promise;
    217 }
    218 window.onload = async function() {
    219     let ctxopts = {
    220         alpha: false,
    221         depth: true,
    222         stencil: false,
    223         antialias: true,
    224         preserveDrawingBuffer: false
    225     };
    226     gl = document.getElementById("webglcanvas").getContext("webgl2", ctxopts);
    227     if(!gl) {
    228         error_fatal("Your browser does not support WebGL 2.");
    229     }
    230     files[0] = file_load("binary.wasm");
    231     files[1] = file_load("shader/cube_f.glsl");
    232     files[2] = file_load("shader/cube_v.glsl");
    233     for(var i=0; i<files.length; i++) {
    234         files[i] = await files[i];
    235     }
    236     let binary = files[0];
    237     imports['memory'] = new WebAssembly.Memory({'initial':32});
    238     memory = new Uint8Array(imports['memory']['buffer']);
    239     let program = await WebAssembly.instantiate(binary, {"env":imports});
    240     let instance = program['instance'];
    241     exports = instance['exports'];
    242     canvas_resize();
    243     window.addEventListener("resize", canvas_resize);
    244     if(!exports['init']()) {
    245         error_fatal("Game initialization failed.");
    246     }
    247     canvas_render();
    248 }