diff --git a/script.js b/script.js index 654874c..0f7a326 100644 --- a/script.js +++ b/script.js @@ -1,8 +1,8 @@ "use strict"; var vertexShaderSource = `#version 300 es - in vec2 a_position; + in vec2 a_position; uniform vec2 u_resolution; void main() { @@ -64,7 +64,24 @@ function initializeContext(canvasId) { const ctx = canvas.getContext("webgl2", { antialias: false }); return ctx; } -function drawTriangle(gfx, position, exts) { +function drawTriangle(gfx, positions) { + const positionLoc = gfx.attribs.get("a_position"); + if (positionLoc === undefined) + throw new Error("`drawTriangle` requires attribute `a_position` to be defined"); + const points = [ + positions[0].x, positions[0].y, + positions[1].x, positions[1].y, + positions[2].x, positions[2].y, + ]; + gfx.ctx.bindBuffer(gfx.ctx.ARRAY_BUFFER, gfx.buffer); + gfx.ctx.enableVertexAttribArray(positionLoc); + gfx.ctx.vertexAttribPointer(positionLoc, 2, gfx.ctx.FLOAT, false, 0, 0); + gfx.ctx.bufferData(gfx.ctx.ARRAY_BUFFER, new Float32Array(points), gfx.ctx.STATIC_DRAW); + gfx.ctx.bindVertexArray(gfx.vao); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3); + gfx.ctx.disableVertexAttribArray(positionLoc); +} +function drawTriangleExts(gfx, position, exts) { const positionLoc = gfx.attribs.get("a_position"); if (positionLoc === undefined) throw new Error("`drawTriangle` requires attribute `a_position` to be defined"); @@ -102,27 +119,40 @@ function drawRectangle(gfx, position, exts) { gfx.ctx.disableVertexAttribArray(positionLoc); } function drawCircle(gfx, position, radius) { - const precision = 20; const positionLoc = gfx.attribs.get("a_position"); if (positionLoc === undefined) throw new Error("`drawCircle` requires attribute `a_position` to be defined"); const points = new Array(); + const precision = 40; const angle = 2.0 * Math.PI / precision; - var a = 0; - points.push(position.x); - points.push(position.y); - points.push(position.x); - points.push(position.y + radius); - for (let i = precision; i >= 0; --i) { + let a = 0; + for (let i = 0; i < precision; ++i) { var vec = Vec2.angle(a); + vec.mult(radius); a += angle; + points.push(vec); } + for (let i = 0; i < points.length; i++) { + const current = points[i]; + const next = points[(i + 1) % points.length]; + let center = position; + drawTriangle(gfx, [center, center.addNew(current), center.addNew(next)]); + } +} +function drawLine(gfx, A, B) { + const positionLoc = gfx.attribs.get("a_position"); + if (positionLoc === undefined) + throw new Error("`drawTriangle` requires attribute `a_position` to be defined"); + let points = [ + A.x, A.y, + B.x, B.y, + ]; gfx.ctx.bindBuffer(gfx.ctx.ARRAY_BUFFER, gfx.buffer); gfx.ctx.enableVertexAttribArray(positionLoc); gfx.ctx.vertexAttribPointer(positionLoc, 2, gfx.ctx.FLOAT, false, 0, 0); gfx.ctx.bufferData(gfx.ctx.ARRAY_BUFFER, new Float32Array(points), gfx.ctx.STATIC_DRAW); gfx.ctx.bindVertexArray(gfx.vao); - gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3 * precision); + gfx.ctx.drawArrays(gfx.ctx.LINES, 0, 2); gfx.ctx.disableVertexAttribArray(positionLoc); } class Graphics { @@ -173,6 +203,9 @@ class Vec2 { this.x += other.x; this.y += other.y; } + addNew(other) { + return new Vec2(this.x + other.x, this.y + other.y); + } sub(other) { this.x -= other.x; this.y -= other.y; @@ -181,6 +214,9 @@ class Vec2 { this.x *= scalar; this.y *= scalar; } + splatToArray() { + return [this.x, this.y]; + } static angle(angle) { const eps = 1e-6; let x = Math.cos(angle); @@ -232,8 +268,12 @@ function draw() { const position = new Vec2(ctx.canvas.width / 2 - 100, ctx.canvas.height / 2 - 100); gfx.clear(0, 0, 0, 0); ctx.uniform2f(gfx.getUniform("u_resolution"), ctx.canvas.width, ctx.canvas.height); - ctx.uniform4f(gfx.getUniform("u_color"), 0.2, 0.2, 0.2, 1); + ctx.uniform4f(gfx.getUniform("u_color"), 0.5, 0.2, 0.2, 1); drawRectangle(gfx, position, new Vec2(200, 200)); + drawTriangle(gfx, [new Vec2(100, 100), new Vec2(200, 100), new Vec2(100, 200)]); + drawTriangleExts(gfx, new Vec2(200, 200), new Vec2(-100, -100)); + drawCircle(gfx, new Vec2(400, 200), 100); + drawLine(gfx, new Vec2(100, 600), new Vec2(600, 600)); } (() => { draw(); diff --git a/script.ts b/script.ts index be71287..8ca9ae7 100644 --- a/script.ts +++ b/script.ts @@ -1,8 +1,8 @@ var vertexShaderSource = `#version 300 es - in vec2 a_position; + in vec2 a_position; uniform vec2 u_resolution; void main() { @@ -82,7 +82,28 @@ function initializeContext(canvasId: string): WebGL2RenderingContext | null { } -function drawTriangle(gfx: Graphics, position: Vec2, exts: Vec2) { +function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2]) { + const positionLoc = gfx.attribs.get("a_position"); + + if (positionLoc === undefined) + throw new Error("`drawTriangle` requires attribute `a_position` to be defined"); + + const points: Array = [ + positions[0].x, positions[0].y, + positions[1].x, positions[1].y, + positions[2].x, positions[2].y, + ] + + gfx.ctx.bindBuffer(gfx.ctx.ARRAY_BUFFER, gfx.buffer); + gfx.ctx.enableVertexAttribArray(positionLoc); + gfx.ctx.vertexAttribPointer(positionLoc, 2, gfx.ctx.FLOAT, false, 0, 0); + gfx.ctx.bufferData(gfx.ctx.ARRAY_BUFFER, new Float32Array(points), gfx.ctx.STATIC_DRAW); + gfx.ctx.bindVertexArray(gfx.vao); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3); + gfx.ctx.disableVertexAttribArray(positionLoc); +} + +function drawTriangleExts(gfx: Graphics, position: Vec2, exts: Vec2) { const positionLoc = gfx.attribs.get("a_position"); if (positionLoc === undefined) @@ -130,32 +151,48 @@ function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2) { } function drawCircle(gfx: Graphics, position: Vec2, radius: number) { - const precision = 20; - const positionLoc = gfx.attribs.get("a_position"); if (positionLoc === undefined) throw new Error("`drawCircle` requires attribute `a_position` to be defined"); - const points: Array = new Array(); + const points: Array = new Array(); + const precision = 40; const angle = 2.0*Math.PI/precision; - var a = 0; - points.push(position.x); - points.push(position.y); - points.push(position.x); - points.push(position.y + radius); - for (let i = precision; i >= 0; --i) { + let a = 0; + for (let i = 0; i < precision; ++i) { var vec = Vec2.angle(a); + vec.mult(radius); a += angle; + points.push(vec); } - + + for (let i = 0; i < points.length; i++) { + const current = points[i]; + const next = points[(i + 1) % points.length]; + let center = position; + drawTriangle(gfx, [center, center.addNew(current), center.addNew(next)]); + } +} + +function drawLine(gfx: Graphics, A: Vec2, B: Vec2) { + const positionLoc = gfx.attribs.get("a_position"); + + if (positionLoc === undefined) + throw new Error("`drawTriangle` requires attribute `a_position` to be defined"); + + let points: Array = [ + A.x, A.y, + B.x, B.y, + ]; + gfx.ctx.bindBuffer(gfx.ctx.ARRAY_BUFFER, gfx.buffer); gfx.ctx.enableVertexAttribArray(positionLoc); gfx.ctx.vertexAttribPointer(positionLoc, 2, gfx.ctx.FLOAT, false, 0, 0); gfx.ctx.bufferData(gfx.ctx.ARRAY_BUFFER, new Float32Array(points), gfx.ctx.STATIC_DRAW); gfx.ctx.bindVertexArray(gfx.vao); - gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3*precision); + gfx.ctx.drawArrays(gfx.ctx.LINES, 0, 2); gfx.ctx.disableVertexAttribArray(positionLoc); } @@ -220,6 +257,10 @@ class Vec2 { this.y += other.y; } + addNew(other: Vec2): Vec2 { + return new Vec2(this.x + other.x, this.y + other.y); + } + sub(other: Vec2) { this.x -= other.x; this.y -= other.y; @@ -230,6 +271,10 @@ class Vec2 { this.y *= scalar; } + splatToArray(): Array { + return [this.x, this.y]; + } + static angle(angle: number): Vec2 { const eps = 1e-6; let x = Math.cos(angle); @@ -293,8 +338,12 @@ function draw() { gfx.clear(0, 0, 0, 0); ctx.uniform2f(gfx.getUniform("u_resolution"), ctx.canvas.width, ctx.canvas.height); - ctx.uniform4f(gfx.getUniform("u_color"), 0.2, 0.2, 0.2, 1); + ctx.uniform4f(gfx.getUniform("u_color"), 0.5, 0.2, 0.2, 1); drawRectangle(gfx, position, new Vec2(200, 200)) + drawTriangle(gfx, [new Vec2(100, 100), new Vec2(200, 100), new Vec2(100, 200)]); + drawTriangleExts(gfx, new Vec2(200, 200), new Vec2(-100, -100)); + drawCircle(gfx, new Vec2(400, 200), 100); + drawLine(gfx, new Vec2(100, 600), new Vec2(600, 600)); } (() => {