From: Brendan Hansen Date: Tue, 2 Mar 2021 02:32:58 +0000 (-0600) Subject: working immediate mode renderer with triangles X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=9e1c7f6f73b5435358f8d8df9306f785cabdc5b0;p=onyx-imgui.git working immediate mode renderer with triangles --- diff --git a/build.sh b/build.sh index f75d1e5..93ea467 100755 --- a/build.sh +++ b/build.sh @@ -1,3 +1,3 @@ #!/bin/sh -onyx -r js -V --use-post-mvp-features test/basic.onyx -o imgui.wasm +onyx -r js -V --use-post-mvp-features test/basic.onyx -o site/imgui.wasm diff --git a/lib/immediate_renderer.onyx b/lib/immediate_renderer.onyx index 5c3528d..4ade840 100644 --- a/lib/immediate_renderer.onyx +++ b/lib/immediate_renderer.onyx @@ -40,6 +40,9 @@ Immediate_Renderer :: struct { clear_color : Color4; + vertex_array : gl.GLVertexArrayObject; + vertex_buffer : gl.GLBuffer; + // Needs to be a multiple of 3!! Default_Max_Verticies :: 1023; @@ -54,8 +57,32 @@ Immediate_Renderer :: struct { vertex_source := #file_contents "lib/shaders/immediate_vertex.glsl"; fragment_source := #file_contents "lib/shaders/immediate_fragment.glsl"; shader = Shader.make_from_source(vertex_source, fragment_source); + gl.useProgram(shader.program); verticies = memory.make_slice(Immediate_Vertex, max_verticies); + memory.set(verticies.data, 0, verticies.count * sizeof Immediate_Vertex); + + vertex_array = gl.createVertexArray(); + gl.bindVertexArray(vertex_array); + defer gl.bindVertexArray(-1); + + vertex_buffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + gl.bufferData(gl.ARRAY_BUFFER, cast(gl.GLsizei) (max_verticies * sizeof Immediate_Vertex), gl.STREAM_DRAW); + + // Position + gl.enableVertexAttribArray(0); + gl.vertexAttribPointer(0, 2, gl.FLOAT, false, sizeof Immediate_Vertex, 0); + + // Color + gl.enableVertexAttribArray(1); + gl.vertexAttribPointer(1, 4, gl.FLOAT, false, sizeof Immediate_Vertex, 2 * sizeof f32); + + // Texture + // gl.enableVertexAttribArray(2); + // gl.vertexAttribPointer(2, 2, gl.FLOAT, false, sizeof Immediate_Vertex, 6 * sizeof f32); + + gl.bindBuffer(gl.ARRAY_BUFFER, -1); } // As a small note, I love the pattern matching style of programming that @@ -79,7 +106,12 @@ Immediate_Renderer :: struct { } flush :: (use ir: ^Immediate_Renderer) { + gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); + gl.bufferSubData(gl.ARRAY_BUFFER, 0, .{ count = vertex_count * sizeof Immediate_Vertex, data = ~~verticies.data }); + gl.bindBuffer(gl.ARRAY_BUFFER, -1); + gl.useProgram(shader.program); + gl.bindVertexArray(vertex_array); gl.drawArrays(gl.TRIANGLES, 0, vertex_count); vertex_count = 0; @@ -97,7 +129,7 @@ Immediate_Renderer :: struct { immediate_renderer : Immediate_Renderer; immediate_renderer_init :: () { - immediate_renderer = Immediate_Renderer.make(); + Immediate_Renderer.init(^immediate_renderer); } immediate_vertex :: proc { diff --git a/lib/shaders/immediate_fragment.glsl b/lib/shaders/immediate_fragment.glsl index 37bdf80..c2186dc 100644 --- a/lib/shaders/immediate_fragment.glsl +++ b/lib/shaders/immediate_fragment.glsl @@ -2,13 +2,10 @@ precision mediump float; -uniform sampler2D u_texture; - in vec4 v_color; -in vec2 v_texture; out vec4 fragColor; void main() { - fragColor = v_color + vec4(v_texture, 0, 0) * 0; -} \ No newline at end of file + fragColor = v_color; +} diff --git a/lib/shaders/immediate_vertex.glsl b/lib/shaders/immediate_vertex.glsl index e8531ed..c1b47e7 100644 --- a/lib/shaders/immediate_vertex.glsl +++ b/lib/shaders/immediate_vertex.glsl @@ -2,17 +2,11 @@ layout(location = 0) in vec2 a_vertex; layout(location = 1) in vec4 a_color; -layout(location = 2) in vec2 a_texture; - -uniform mat4 u_view; -uniform mat4 u_world; out vec4 v_color; -out vec4 v_texture; void main() { - gl_Position = u_view * u_world * vec4(a_vertex, 0, 1); + gl_Position = vec4(a_vertex, 0, 1); v_color = a_color; - v_texture = v_texture; -} \ No newline at end of file +} diff --git a/site/imgui.mjs b/site/imgui.mjs new file mode 100644 index 0000000..1df95fe --- /dev/null +++ b/site/imgui.mjs @@ -0,0 +1,108 @@ +import { WebGL_Wasm } from "./webgl.mjs" + +let wasm_instance; + +function push_event_to_buffer(esp, event_size, event_kind, data) { + let WASM_U32 = new Uint32Array(wasm_instance.exports.memory.buffer); + + if (WASM_U32[esp] >= WASM_U32[esp + 1]) { + console.log("Buffer full!"); + return; + } + + WASM_U32[esp] += 1; + + let event_idx = esp + (WASM_U32[esp] - 1) * (event_size / 4) + 2; + WASM_U32[event_idx] = event_kind; + WASM_U32[event_idx + 1] = Date.now(); + + for (let i = 0; i < data.length; i++) { + WASM_U32[event_idx + 2 + i] = data[i]; + } +} + + +let event_module = { + setup(esp, event_size) { + // Indicies into a Uint32Array are not based on bytes, + // but on the index. + esp /= 4; + + document.addEventListener("keydown", (ev) => { + if (ev.isComposing || ev.keyCode === 229) return; + push_event_to_buffer(esp, event_size, 0x04, [ ev.keyCode ]); + }); + + document.addEventListener("keyup", (ev) => { + if (ev.isComposing || ev.keyCode === 229) return; + push_event_to_buffer(esp, event_size, 0x05, [ ev.keyCode ]); + }); + + document.addEventListener("mousedown", (ev) => { + push_event_to_buffer(esp, event_size, 0x01, [ ev.clientX, ev.clientY, ev.button ]); + }); + + document.addEventListener("mouseup", (ev) => { + push_event_to_buffer(esp, event_size, 0x02, [ ev.clientX, ev.clientY, ev.button ]); + }); + + document.addEventListener("mousemove", (ev) => { + push_event_to_buffer(esp, event_size, 0x03, [ ev.clientX, ev.clientY, -1 ]); + }); + + document.addEventListener("wheel", (ev) => { + push_event_to_buffer(esp, event_size, 0x07, [ ev.clientX, ev.clientY, ev.deltaY >= 0 ? 0x04 : 0x03 ]); + }); + + window.addEventListener("resize", (ev) => { + push_event_to_buffer(esp, event_size, 0x06, [ window.innerWidth, window.innerHeight ]); + }); + + push_event_to_buffer(esp, event_size, 0x06, [ window.innerWidth, window.innerHeight ]); + + document.oncontextmenu = (e) => { + e.preventDefault = true; + return false; + }; + }, +} + +let import_obj = { + host: { + print_str(ptr, len) { + let buffer = new Uint8Array(wasm_instance.exports.memory.buffer, ptr, len); + let string = new TextDecoder().decode(buffer); + console.log(string); + }, + + exit() { debugger; }, + + debug() { debugger; }, + + start_loop() { + let loop = () => { + wasm_instance.exports.loop(); + window.requestAnimationFrame(loop); + }; + + window.requestAnimationFrame(loop); + }, + }, + + gl: WebGL_Wasm, + event: event_module, +} + +window.onload = () => { + fetch("imgui.wasm") + .then(res => res.arrayBuffer()) + .then(res => WebAssembly.instantiate(res, import_obj)) + .then(({ module, instance }) => { + wasm_instance = instance + WebGL_Wasm.memory = wasm_instance.exports.memory + + console.log(module, instance) + + wasm_instance.exports._start() + }) +} diff --git a/site/index.html b/site/index.html new file mode 100644 index 0000000..e77e58e --- /dev/null +++ b/site/index.html @@ -0,0 +1,21 @@ + + + IMGUI + + + + + + + + This browser does not support the Canvas API. + + diff --git a/site/webgl.mjs b/site/webgl.mjs new file mode 100644 index 0000000..1236539 --- /dev/null +++ b/site/webgl.mjs @@ -0,0 +1,301 @@ +let programs = []; +let shaders = []; +let buffers = []; +let framebuffers = []; +let renderbuffers = []; +let textures = []; +let uniformlocs = []; +let vertexArrays = []; +let canvas = null; +let gl = null; + +let WebGL_Wasm = { + memory: null, + + init(name, namelen) { + const decoder = new TextDecoder(); + const str = new Uint8Array(WebGL_Wasm.memory.buffer, name, namelen); + const canvasname = decoder.decode(str); + + canvas = document.getElementById(canvasname); + if (canvas == null) return 0; + + gl = canvas.getContext("webgl2"); + if (gl == null) return 0; + + return 1; + }, + + setSize(width, height) { + canvas.width = width; + canvas.height = height; + }, + + activeTexture(texture) { gl.activeTexture(texture); }, + attachShader(program, shader) { gl.attachShader(programs[program], shaders[shader]); return programs[program]; }, + bindAttribLocation(program, index, name, namelen) { console.log("NOT IMPLEMENTED!"); }, + bindBuffer(target, buffer) { + if (buffer == -1) { + gl.bindBuffer(target, null); + } else { + gl.bindBuffer(target, buffers[buffer]); + } + }, + bindFramebuffer(target, framebuffer) { gl.bindFramebuffer(target, framebuffers[framebuffer]); }, + bindRenderbuffer(target, renderbuffer) { gl.bindRenderbuffer(target, renderbuffers[renderbuffer]); }, + bindTexture(target, texture) { gl.bindTexture(target, textures[texture]); }, + bindVertexArray(vertexArray) { + if (vertexArray == -1) { + gl.bindVertexArray(null); + } else { + gl.bindVertexArray(vertexArrays[vertexArray]); + } + }, + + blendColor(red, green, blue, alpha) { gl.blendColor(red, green, blue, alpha); }, + blendEquation(mode) { gl.blendEquation(mode); }, + blendEquationSeparate(modeRGB, modeAlpha) { gl.blendEquationSeparate(modeRGB, modeAlpha); }, + blendFunc(sfactor, dfactor) { gl.blendFunc(sfactor, dfactor); }, + blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha) { gl.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); }, + + blitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, mask, filter) { + gl.blitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, mask, filter); + }, + + bufferDataWithData(target, bufferdata, bufferlen, usage) { + const data = new DataView(WebGL_Wasm.memory.buffer, bufferdata, bufferlen); + gl.bufferData(target, data, usage); + }, + + bufferDataNoData(target, size, usage) { gl.bufferData(target, size, usage); }, + bufferSubData(target, offset, bufferdata, bufferlen) { + const data = new DataView(WebGL_Wasm.memory.buffer, bufferdata, bufferlen); + gl.bufferSubData(target, offset, data); + }, + canvasSize(width, height) { + canvas.width = width; + canvas.height = height; + }, + checkFrameBufferStatus(target) { return gl.checkFrameBufferStatus(target); }, + clear(bit) { gl.clear(bit); }, + clearColor(r, g, b, a) { gl.clearColor(r, g, b, a); }, + clearDepth(depth) { gl.clearDepth(depth); }, + clearStencil(stencil) { gl.clearStencil(stencil); }, + colorMask(r, g, b, a) { gl.colorMask(r, g, b, a); }, + compileShader(shader) { gl.compileShader(shaders[shader]); }, + compressedTexImage2D(target, level, internalformat, width, height, border, data, datalen) { + const pixels = new DataView(WebGL_Wasm.memory.buffer, data, datalen); + gl.compressedTexImage2D(target, level, internalformat, width, height, border, pixels); + }, + compressedTexSubImage2D(target, level, internalformat, xoff, yoff, width, height, format, data, datalen) { + const pixels = new DataView(WebGL_Wasm.memory.buffer, data, datalen); + gl.compressedSubTexImage2D(target, level, internalformat, xoff, yoff, width, height, format, pixels); + }, + copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size) { gl.copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); }, + copyTexImage2D(target, level, internalforamt, x, y, width, height, border) { + gl.copyTexImage2D(target, level, internalforamt, x, y, width, height, border); + }, + copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height) { + gl.copyTexSubImage2D(target, level, xoff, yoff, x, y, width, height); + }, + createBuffer() { + const buf = gl.createBuffer(); + if (buf == null) return -1; + + buffers.push(buf); + return buffers.length - 1; + }, + createFramebuffer() { + const buf = gl.createFramebuffer(); + if (buf == null) return -1; + + framebuffers.push(buf); + return framebuffers.length - 1; + }, + createProgram() { + const prog = gl.createProgram(); + if (prog == null) return -1; + + programs.push(prog); + return programs.length - 1; + }, + createRenderbuffer() { + const buf = gl.createRenderbuffer(); + if (buf == null) return -1; + + renderbuffers.push(buf); + return renderbuffers.length - 1; + }, + createShader(type) { + const shader = gl.createShader(type); + if (shader == null) return -1; + + shaders.push(shader); + return shaders.length - 1; + }, + createTexture() { + const texture = gl.createTexture(); + if (texture == null) return -1; + + textures.push(texture); + return textures.length - 1; + }, + createVertexArray() { + const vao = gl.createVertexArray(); + if (vao == null) return -1; + + vertexArrays.push(vao); + return vertexArrays.length - 1; + }, + cullFace(mode) { gl.cullFace(mode); }, + deleteBuffer(buffer) { gl.deleteBuffer(buffers[buffer]); }, + deleteFramebuffer(framebuffer) { gl.deleteFramebuffer(framebuffers[framebuffer]); }, + deleteProgram(program) { gl.deleteProgram(programs[program]); }, + deleteRenderbuffer(renderbuffer) { gl.deleteRenderbuffer(renderbuffers[renderbuffer]); }, + deleteShader(shader) { gl.deleteShader(shaders[shader]); }, + deleteTexture(texture) { gl.deleteTexture(textures[texture]); }, + deleteVertexArray(vertexArray) { gl.deleteVertexArray(vertexArrays[vertexArray]); }, + depthFunc(func) { gl.depthFunc(func); }, + depthMask(flag) { gl.depthMask(flag); }, + depthRange(znear, zfar) { gl.depthRange(znear, zfar); }, + detachShader(program, shader) { gl.detachShader(programs[program], shaders[shader]); }, + disable(cap) { gl.disable(cap); }, + disableVertexAttribArray(index) { gl.disableVertexAttribArray(index); }, + drawArrays(mode, first, count) { gl.drawArrays(mode, first, count); }, + drawArraysInstanced(mode, first, count, instanceCount) { gl.drawArraysInstanced(mode, first, count, instanceCount); }, + drawElements(mode, count, type, offset) { gl.drawElements(mode, count, type, offset); }, + drawElementsInstanced(mode, count, type, offset, instanceCount) { gl.drawElementsInstanced(mode, count, type, offset, instanceCount); }, + enable(cap) { gl.enable(cap); }, + enableVertexAttribArray(index) { gl.enableVertexAttribArray(index); }, + finish() { gl.finish(); }, + flush() { gl.flush(); }, + framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) { + gl.framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffers[renderbuffer]); + }, + framebufferTexture2D(target, attachment, texttarget, texture, level) { + gl.framebufferTexture2D(target, attachment, texttarget, textures[texture], level); + }, + framebufferTextureLayer(target, attachment, texture, level, layer) { gl.framebufferTextureLayer(target, attachment, textures[texture], level, layer); }, + frontFace(mode) { gl.frontFace(mode); }, + generateMipmap(target) { gl.generateMipmap(target); }, + getActiveAttrib(program, index, out) { + const loc = gl.getActiveAttrib(programs[program], index); + const data = new Int32Array(WebGL_Wasm.memory.buffer, out, 2); + data[0] = loc.size; + data[1] = loc.type; + }, + getActiveUniform(program, index, out) { + const loc = gl.getActiveUniform(programs[program], index); + const data = new Int32Array(WebGL_Wasm.memory.buffer, out, 2); + data[0] = loc.size; + data[1] = loc.type; + }, + // getAttachedShaders() { console.log("NOT IMPLEMENTED!"); }, + getAttribLocation(program, name, namelen) { + const decoder = new TextDecoder(); + const str = new Uint8Array(WebGL_Wasm.memory.buffer, name, namelen); + const attribname = decoder.decode(str); + + return gl.getAttribLocation(programs[program], attribname); + }, + // getBufferParameter() { console.log("NOT IMPLEMENTED!"); }, + getBufferSubData(target, srcbyteoffset, dstbufferdata, dstbufferlen, dstoffset, length) { + const dst = new DataView(WebGL_Wasm.meory.buffer, dstbufferdata, dstbufferlen); + gl.getBufferSubData(target, srcbyteoffset, dst, dstoffset, length); + }, + getError() { return gl.getError(); }, + getInternalformatParameter(target, internalformat, pname) { return gl.getInternalformatParameter(target, internalformat, pname); }, + // many of the 'gets() { console.log("NOT IMPLEMENTED!"); }, + getShaderParameter(shader, param) { return gl.getShaderParameter(shaders[shader], param); }, + getProgramParameter(program, param) { return gl.getProgramParameter(programs[program], param); }, + getUniformLocation(program, name, namelen) { + const decoder = new TextDecoder(); + const str = new Int8Array(WebGL_Wasm.memory.buffer, name, namelen); + const uniname = decoder.decode(str); + + uniformlocs.push(gl.getUniformLocation(programs[program], uniname)); + return uniformlocs.length - 1; + }, + getVertexAttribOffset(index, pname) { return gl.getVertexAttribOffset(index, pname); }, + hint(target, mode) { gl.hint(target, mode); }, + isEnabled(cap) { return gl.isEnabled(cap); }, + invalidateFramebuffer(target, attachdata, attachlen) { + const attachments = new Int32Array(WebGL_Wasm.memory.buffer, attachdata, attachlen); + gl.invalidateFramebuffer(target, attacements); + }, + invalidateSubFramebuffer(target, attachdata, attachlen, x, y, width, height) { + const attachments = new Int32Array(WebGL_Wasm.memory.buffer, attachdata, attachlen); + gl.invalidateFramebuffer(target, attacements, x, y, width, height); + }, + lineWidth(width) { gl.lineWidth(width); }, + linkProgram(program) { gl.linkProgram(programs[program]); }, + pixelStorei(pname, param) { gl.pixelStorei(pname, param); }, + polygonOffset(factor, units) { gl.polygonOffset(factor, units); }, + printProgramInfoLog(program) { console.log(gl.getProgramInfoLog(programs[program])); }, + printShaderInfoLog(shader) { console.log(gl.getShaderInfoLog(shaders[shader])); }, + readPixels(x, y, width, height, format, type, pixels, pixelslen) { + const pixeldata = new Uint8Array(WebGL_Wasm.memory.buffer, pixels, pixelslen); + gl.readPixels(x, y, width, height, format, type, pixeldata); + }, + readBuffer(src) { gl.readBuffer(src); }, + renderbufferStorageMultisample(target, samples, internalforamt, width, height) { + gl.renderbufferStorageMultisample(target, samples, internalforamt, width, height); + }, + sampleCoverage(value, invert) { gl.sampleCoverage(value, invert); }, + scissor(x, y, width, height) { gl.scissor(x, y, width, height); }, + shaderSource(shader, source, sourcelen) { + const decoder = new TextDecoder(); + const str = new Int8Array(WebGL_Wasm.memory.buffer, source, sourcelen); + const sourcedata = decoder.decode(str); + + gl.shaderSource(shaders[shader], sourcedata); + }, + stencilFunc(func, ref, mask) { gl.stencilFunc(func, ref, mask); }, + stencilFuncSeparate(face, func, ref, mask) { gl.stencilFuncSeparate(face, func, ref, mask); }, + stencilMask(mask) { gl.stencilMask(mask); }, + stencilMaskSeparate(face, mask) { gl.stencilMaskSeparate(face, mask); }, + stencilOp(fail, zfail, mask) { gl.stencilOp(fail, zfail, mask); }, + stencilOpSeparate(face, fail, zfail, zpass) { gl.stencilOpSeparate(face, fail, zfail, zpass); }, + texImage2D(target, level, internalforamt, width, height, border, format, type, pixels, pixelslen) { + const data = new DataView(WebGL_Wasm.memory.buffer, pixels, pixelslen); + gl.texImage2D(target, level, internalforamt, width, height, border, format, type, data); + }, + texParameterf(target, pname, param) { gl.texParameterf(target, pname, param); }, + texParameteri(target, pname, param) { gl.texParameteri(target, pname, param); }, + texSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels, pixelslen) { + const data = new Uint8Array(WebGL_Wasm.memory.buffer, pixels, pixelslen); + gl.texSubImage2D(target, level, xoff, yoff, width, height, format, type, data); + }, + uniform1f(loc, x) { gl.uniform1f(uniformlocs[loc], x); }, + uniform1i(loc, x) { gl.uniform1i(uniformlocs[loc], x); }, + uniform2f(loc, x, y) { gl.uniform2f(uniformlocs[loc], x, y); }, + uniform2i(loc, x, y) { gl.uniform2i(uniformlocs[loc], x, y); }, + uniform3f(loc, x, y, z) { gl.uniform3f(uniformlocs[loc], x, y, z); }, + uniform3i(loc, x, y, z) { gl.uniform3i(uniformlocs[loc], x, y, z); }, + uniform4f(loc, x, y, z, w) { gl.uniform4f(uniformlocs[loc], x, y, z, w); }, + uniform4i(loc, x, y, z, w) { gl.uniform4i(uniformlocs[loc], x, y, z, w); }, + uniformMatrix2(loc, transpose, valueptr) { + const data = new Float32Array(WebGL_Wasm.memory.buffer, valueptr, 4); + gl.uniformMatrix2fv(uniformlocs[loc], transpose, data); + }, + uniformMatrix3(loc, transpose, valueptr) { + const data = new Float32Array(WebGL_Wasm.memory.buffer, valueptr, 9); + gl.uniformMatrix3fv(uniformlocs[loc], transpose, data); + }, + uniformMatrix4(loc, transpose, valueptr) { + const data = new Float32Array(WebGL_Wasm.memory.buffer, valueptr, 16); + gl.uniformMatrix4fv(uniformlocs[loc], transpose, data); + }, + useProgram(program) { gl.useProgram(programs[program]); }, + validateProgram(program) { gl.validateProgram(program[program]); }, + vertexAttrib1f(idx, x) { gl.vertexAttrib1f(idx, x); }, + vertexAttrib2f(idx, x, y) { gl.vertexAttrib2f(idx, x, y); }, + vertexAttrib3f(idx, x, y, z) { gl.vertexAttrib3f(idx, x, y, z); }, + vertexAttrib4f(idx, x, y, z, w) { gl.vertexAttrib4f(idx, x, y, z, w); }, + vertexAttribPointer(idx, size, type, normalized, stride, offset) { gl.vertexAttribPointer(idx, size, type, normalized, stride, offset); }, + vertexAttribDivisor(idx, divisor) { gl.vertexAttribDivisor(idx, divisor); }, + viewport(x, y, width, height) { gl.viewport(x, y, width, height); }, +}; + +export { WebGL_Wasm }; + diff --git a/test/basic.onyx b/test/basic.onyx index 21b3825..a95ad5f 100644 --- a/test/basic.onyx +++ b/test/basic.onyx @@ -14,12 +14,27 @@ use package core use package imgui as imgui use package imgui.events as events +use package gl as gl + +init :: () { + events.init(); + + gl.init("imgui-canvas"); + imgui.immediate_renderer_init(); +} poll_events :: () { use events.DomEventKind; event: events.Event; while events.poll(^event) do switch event.kind { + case Resize { + println("The window was resized!"); + + gl.setSize(event.resize.width, event.resize.height); + gl.viewport(0, 0, event.resize.width, event.resize.height); + } + case MouseDown { println("The mouse was pressed!"); printf("Specifically, the %i button.\n", event.mouse.button); @@ -27,28 +42,46 @@ poll_events :: () { } } +t := 0.0f + update :: () { + t += 1.0 / 60.0; } draw :: () { + gl.clearColor(0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + use imgui; + defer immediate_flush(); + + x := math.cos(t); + y := math.sin(t); + + immediate_vertex(.{ 0, 0 }, color=.{ 1, 1, 1, 1 }); + immediate_vertex(.{ x, -y }); + immediate_vertex(.{ y, x }); - immediate_vertex(.{ 0, 0 }, color=.{ 1, 0, 0, 1 }); - immediate_vertex(.{ 1, 0 }); - immediate_vertex(.{ 0, 1 }); + if cast(u32) t % 2 == 0 { + immediate_vertex(.{ 0, 0 }, color=.{ 1, 0, 0, 1 }); + immediate_vertex(.{ -1.0f, 0 }, color=.{ 0, 1, 0, 1 }); + immediate_vertex(.{ 0, -1.0f }, color=.{ 0, 0, 1, 1 }); + } } -loop :: () { +loop :: () -> void #export { poll_events(); update(); draw(); } + main :: (args: [] cstr) { println("Hey! We got here!"); - events.init(); + init(); - imgui.immediate_renderer_init(); + start_loop :: () -> void #foreign "host" "start_loop" --- + start_loop(); }