diff --git a/src/js/common.js b/src/js/common.js index aa7dfc6..7276c5b 100644 --- a/src/js/common.js +++ b/src/js/common.js @@ -70,6 +70,9 @@ class Vec3 { this.y -= other.y; this.z -= other.z; } + splatToArray() { + return [this.x, this.y, this.z]; + } } class Vec4 { x; @@ -146,6 +149,22 @@ class Mat4 { ]); return new Mat4(data); } + static isometric() { + //let m = new Mat4(new Float32Array([ + // Math.sqrt(3), 0, -Math.sqrt(3), 0, + // 1, 2, 1, 0, + // Math.sqrt(2), -Math.sqrt(2), Math.sqrt(2), 0, + // 0, 0, 0, 1, + //])); + //m.multScalar(1 / Math.sqrt(6)); + let m = new Mat4(new Float32Array([ + 1, -1, 0, 0, + 1, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + ])); + return m; + } static rotation_x(angle) { let data = new Float32Array([ 1, 0, 0, 0, @@ -218,7 +237,7 @@ class Mat4 { vec.w = w; return vec; } - mult(other) { + multNew(other) { let m = new Mat4(0); for (let i = 0; i < 4; ++i) { for (let j = 0; j < 4; ++j) { @@ -230,5 +249,10 @@ class Mat4 { } return m; } + multScalar(scalar) { + for (let i = 0; i < this.data.length; ++i) { + this.data[i] *= scalar; + } + } } export { initializeContext, Mat4, Vec2, Vec3, Vec4 }; diff --git a/src/js/common.ts b/src/js/common.ts index 3a0a922..7359db9 100644 --- a/src/js/common.ts +++ b/src/js/common.ts @@ -91,6 +91,10 @@ class Vec3 { this.y -= other.y; this.z -= other.z; } + + splatToArray(): Array { + return [this.x, this.y, this.z]; + } } class Vec4 { @@ -193,6 +197,26 @@ class Mat4 { return new Mat4(data); } + + static isometric(): Mat4 { + //let m = new Mat4(new Float32Array([ + // Math.sqrt(3), 0, -Math.sqrt(3), 0, + // 1, 2, 1, 0, + // Math.sqrt(2), -Math.sqrt(2), Math.sqrt(2), 0, + // 0, 0, 0, 1, + //])); + + //m.multScalar(1 / Math.sqrt(6)); + + let m = new Mat4(new Float32Array([ + 1, -1, 0, 0, + 1, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + ])); + + return m; + } static rotation_x(angle: number): Mat4 { let data = new Float32Array([ @@ -285,7 +309,7 @@ class Mat4 { return vec; } - mult(other: Mat4): Mat4 { + multNew(other: Mat4): Mat4 { let m = new Mat4(0); for (let i = 0; i < 4; ++i) { @@ -299,6 +323,12 @@ class Mat4 { return m; } + + multScalar(scalar: number) { + for (let i = 0; i < this.data.length; ++i) { + this.data[i] *= scalar; + } + } } export { initializeContext, Mat4, Vec2, Vec3, Vec4, Color }; diff --git a/src/js/draw.js b/src/js/draw.js index 52c0f2b..5395467 100644 --- a/src/js/draw.js +++ b/src/js/draw.js @@ -1,6 +1,6 @@ -import { Vec2 } from "./common.js"; +import { Vec3, Vec2 } from "./common.js"; import { Texture } from "./graphics.js"; -function drawTriangle(gfx, positions, color) { +export function drawTriangle(gfx, positions, color) { const a_position = gfx.getAttribute("a_position"); const a_color = gfx.getAttribute("a_color"); const points = [ @@ -17,13 +17,13 @@ function drawTriangle(gfx, positions, color) { a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW); gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3); } -function drawTriangleExts(gfx, position, exts, color) { +export function drawTriangleExts(gfx, position, exts, color) { const a_position = gfx.getAttribute("a_position"); const a_color = gfx.getAttribute("a_color"); const points = [ - position.x, position.y, - position.x + exts.x, position.y, - position.x, position.y + exts.y, + position.x, position.y, position.z, + position.x + exts.x, position.y, position.z, + position.x, position.y + exts.y, position.z, ]; const colors = [ color, @@ -34,15 +34,15 @@ function drawTriangleExts(gfx, position, exts, color) { a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW); gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3); } -function drawRectangle(gfx, position, exts, color) { +export function drawRectangle(gfx, corners, color) { const a_position = gfx.getAttribute("a_position"); const points = [ - position.x, position.y, - position.x + exts.x, position.y, - position.x, position.y + exts.y, - position.x + exts.x, position.y + exts.y, - position.x + exts.x, position.y, - position.x, position.y + exts.y, + corners[0].x, corners[0].y, corners[0].z, + corners[1].x, corners[1].y, corners[1].z, + corners[3].x, corners[3].y, corners[3].z, + corners[2].x, corners[2].y, corners[2].z, + corners[1].x, corners[1].y, corners[1].z, + corners[3].x, corners[3].y, corners[3].z, ]; if (color instanceof Texture) { const a_tex_position = gfx.getAttribute("a_tex_position"); @@ -69,7 +69,71 @@ function drawRectangle(gfx, position, exts, color) { gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); } } -function drawCircle(gfx, position, radius, color) { +export function drawIsometricCube(gfx, position, exts, color) { + let points = [ + position, + new Vec3(position.x, position.y + exts.y, position.z), + new Vec3(position.x + exts.x, position.y, position.z), + new Vec3(position.x + exts.x, position.y + exts.y, position.z), + new Vec3(position.x + 1.5 * exts.x, position.y - 0.5 * exts.y, position.z + 0.25 * exts.z), + new Vec3(position.x + 1.5 * exts.x, position.y + 0.5 * exts.y, position.z + 0.25 * exts.z), + new Vec3(position.x + 0.5 * exts.x, position.y - 0.5 * exts.y, position.z + 0.25 * exts.z), + ]; + drawRectangle(gfx, [ + points[0], + points[1], + points[3], + points[2], + ], color); + drawRectangle(gfx, [ + points[3], + points[2], + points[4], + points[5], + ], color); + drawRectangle(gfx, [ + points[0], + points[2], + points[4], + points[6], + ], color); +} +export function drawRectangleExts(gfx, position, exts, color) { + const a_position = gfx.getAttribute("a_position"); + const points = [ + position.x, position.y, position.z, + position.x + exts.x, position.y, position.z, + position.x, position.y + exts.y, position.z, + position.x + exts.x, position.y + exts.y, position.z, + position.x + exts.x, position.y, position.z, + position.x, position.y + exts.y, position.z, + ]; + if (color instanceof Texture) { + const a_tex_position = gfx.getAttribute("a_tex_position"); + const uv = [ + 0.0, 0.0, + -1.0, 0.0, + 0.0, -1.0, + -1.0, -1.0, + -1.0, 0.0, + 0.0, -1.0, + ]; + a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW); + a_tex_position.data(gfx.ctx, uv, gfx.ctx.STATIC_DRAW); + color.bind(gfx); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); + color.unbind(gfx); + } + else { + const a_color = gfx.getAttribute("a_color"); + const colors = new Array(6); + colors.fill(color); + a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW); + a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); + } +} +export function drawCircle(gfx, position, radius, color) { const points = new Array(); const precision = 40; const angle = 2.0 * Math.PI / precision; @@ -87,7 +151,7 @@ function drawCircle(gfx, position, radius, color) { drawTriangle(gfx, [center, center.addNew(current), center.addNew(next)], color); } } -function drawLine(gfx, A, B, color) { +export function drawLine(gfx, A, B, color) { const a_position = gfx.getAttribute("a_position"); const a_color = gfx.getAttribute("a_color"); let points = [ @@ -102,4 +166,3 @@ function drawLine(gfx, A, B, color) { a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW); gfx.ctx.drawArrays(gfx.ctx.LINES, 0, 2); } -export { drawTriangle, drawTriangleExts, drawRectangle, drawCircle, drawLine }; diff --git a/src/js/draw.ts b/src/js/draw.ts index 2570725..8879fff 100644 --- a/src/js/draw.ts +++ b/src/js/draw.ts @@ -1,7 +1,7 @@ -import { Vec2, Color } from "./common.js" +import { Vec3, Vec2, Color } from "./common.js" import { Graphics, Texture } from "./graphics.js"; -function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color) { +export function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color) { const a_position = gfx.getAttribute("a_position"); const a_color = gfx.getAttribute("a_color"); @@ -22,14 +22,14 @@ function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3); } -function drawTriangleExts(gfx: Graphics, position: Vec2, exts: Vec2, color: Color) { +export function drawTriangleExts(gfx: Graphics, position: Vec3, exts: Vec2, color: Color) { const a_position = gfx.getAttribute("a_position"); const a_color = gfx.getAttribute("a_color"); const points: Array = [ - position.x, position.y, - position.x + exts.x, position.y, - position.x, position.y + exts.y, + position.x, position.y, position.z, + position.x + exts.x, position.y, position.z, + position.x, position.y + exts.y, position.z, ] const colors: Array = [ @@ -43,17 +43,18 @@ function drawTriangleExts(gfx: Graphics, position: Vec2, exts: Vec2, color: Colo gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3); } -function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2, color: Color | Texture) { +export function drawRectangle(gfx: Graphics, corners: [Vec3, Vec3, Vec3, Vec3], color: Color | Texture) { const a_position = gfx.getAttribute("a_position"); const points: Array = [ - position.x, position.y, - position.x + exts.x, position.y, - position.x, position.y + exts.y, - - position.x + exts.x, position.y + exts.y, - position.x + exts.x, position.y, - position.x, position.y + exts.y, + corners[0].x, corners[0].y, corners[0].z, + corners[1].x, corners[1].y, corners[1].z, + corners[3].x, corners[3].y, corners[3].z, + + corners[2].x, corners[2].y, corners[2].z, + corners[1].x, corners[1].y, corners[1].z, + corners[3].x, corners[3].y, corners[3].z, + ] if (color instanceof Texture) { @@ -86,7 +87,92 @@ function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2, color: Color | } -function drawCircle(gfx: Graphics, position: Vec2, radius: number, color: Color) { +export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, color: Color) { + let points = [ + position, + new Vec3(position.x, position.y + exts.y, position.z), + new Vec3(position.x + exts.x, position.y, position.z), + new Vec3(position.x + exts.x, position.y + exts.y, position.z), + new Vec3(position.x + 1.5 * exts.x, position.y - 0.5 * exts.y, position.z + 0.25 * exts.z), + new Vec3(position.x + 1.5 * exts.x, position.y + 0.5 * exts.y, position.z + 0.25 * exts.z), + new Vec3(position.x + 0.5 * exts.x, position.y - 0.5 * exts.y, position.z + 0.25 * exts.z), + ]; + + drawRectangle( + gfx, + [ + points[0], + points[1], + points[3], + points[2], + ], + color); + + drawRectangle( + gfx, + [ + points[3], + points[2], + points[4], + points[5], + ], + color); + + drawRectangle( + gfx, + [ + points[0], + points[2], + points[4], + points[6], + ], + color); +} + +export function drawRectangleExts(gfx: Graphics, position: Vec3, exts: Vec2, color: Color | Texture) { + const a_position = gfx.getAttribute("a_position"); + + const points: Array = [ + position.x, position.y, position.z, + position.x + exts.x, position.y, position.z, + position.x, position.y + exts.y, position.z, + + position.x + exts.x, position.y + exts.y, position.z, + position.x + exts.x, position.y, position.z, + position.x, position.y + exts.y, position.z, + ] + + if (color instanceof Texture) { + const a_tex_position = gfx.getAttribute("a_tex_position"); + + const uv: Array = [ + 0.0, 0.0, + -1.0, 0.0, + 0.0, -1.0, + -1.0, -1.0, + -1.0, 0.0, + 0.0, -1.0, + ]; + + a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW); + a_tex_position.data(gfx.ctx, uv, gfx.ctx.STATIC_DRAW); + color.bind(gfx); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); + color.unbind(gfx); + } else { + const a_color = gfx.getAttribute("a_color"); + + const colors: Array = new Array(6); + colors.fill(color); + + a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW); + a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); + } + +} + +export function drawCircle(gfx: Graphics, position: Vec2, radius: number, color: Color) { const points: Array = new Array(); const precision = 40; @@ -107,7 +193,7 @@ function drawCircle(gfx: Graphics, position: Vec2, radius: number, color: Color) } } -function drawLine(gfx: Graphics, A: Vec2, B: Vec2, color: Color) { +export function drawLine(gfx: Graphics, A: Vec2, B: Vec2, color: Color) { const a_position = gfx.getAttribute("a_position"); const a_color = gfx.getAttribute("a_color"); @@ -125,5 +211,3 @@ function drawLine(gfx: Graphics, A: Vec2, B: Vec2, color: Color) { a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW); gfx.ctx.drawArrays(gfx.ctx.LINES, 0, 2); } - -export { drawTriangle, drawTriangleExts, drawRectangle, drawCircle, drawLine } diff --git a/src/js/script.js b/src/js/script.js index 2fe64eb..8a154ec 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -1,10 +1,10 @@ -import { initializeContext, Vec2, Mat4 } from "./common.js"; +import { initializeContext, Vec3, Mat4 } from "./common.js"; import { Graphics, fullscreenCanvas, Texture } from "./graphics.js"; import * as drawing from "./draw.js"; import * as wasm from "./wasm.js"; const vertexShader = `#version 300 es - in vec2 a_position; + in vec3 a_position; in vec2 a_tex_position; in vec4 a_color; out vec2 v_tex_position; @@ -13,7 +13,7 @@ const vertexShader = `#version 300 es uniform bool u_isTex; void main() { - vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0); + vec4 transformed = u_matrix * vec4(a_position.xyz, 1.0); gl_Position = transformed; @@ -45,19 +45,29 @@ const fragmentShader = `#version 300 es `; function draw(gfx, angle, tex) { gfx.clear(0, 0, 0, 0); - let left = 0; let right = gfx.ctx.canvas.width; - let bottom = 0; + let left = 0; let top = gfx.ctx.canvas.height; - let near = -1; - let far = 1; - let m = Mat4.orthographic(left, right, bottom, top, near, far); - m = m.mult(Mat4.rotation_x(angle)); - m = m.mult(Mat4.rotation_y(angle)); - m = m.mult(Mat4.rotation_z(angle)); + let bottom = 0; + let near = -100; + let far = 100; + let mo = Mat4.orthographic(left, right, bottom, top, near, far); + let mi = Mat4.isometric(); + let m = mi.multNew(mo); + //m = m.multNew(Mat4.rotation_x(angle)); + //m = m.multNew(Mat4.rotation_y(angle)); + //m = m.multNew(Mat4.rotation_z(angle)); gfx.ctx.uniformMatrix4fv(gfx.getUniform("u_matrix"), false, m.splat()); - drawing.drawRectangle(gfx, new Vec2(gfx.ctx.canvas.width / 2 - 200, gfx.ctx.canvas.height / 2 - 200), new Vec2(400, 400), tex); - drawing.drawRectangle(gfx, new Vec2(100, 100), new Vec2(100, 100), [Math.sin(angle), Math.cos(angle), -Math.sin(angle), 1]); + let exts = new Vec3(50, 50, 20); + for (let i = 0; i < 10; ++i) { + for (let j = 0; j < 10; ++j) { + //drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [Math.sin(angle * i + j), Math.cos(angle * i + j), -Math.sin(angle * i + j), 1]); + if ((i + j) % 2) + drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 1, 1]); + else + drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [0, 0, 0, 1]); + } + } } (async () => { const canvasId = "game"; @@ -67,7 +77,7 @@ function draw(gfx, angle, tex) { const gfx = new Graphics(ctx, vertexShader, fragmentShader); fullscreenCanvas(gfx, canvasId); const a_position = gfx.createAttribute("a_position"); - a_position.format(2, gfx.ctx.FLOAT, false, 0, 0); + a_position.format(3, gfx.ctx.FLOAT, false, 0, 0); const a_color = gfx.createAttribute("a_color"); a_color.format(4, gfx.ctx.FLOAT, false, 0, 0); const a_tex_position = gfx.createAttribute("a_tex_position"); diff --git a/src/js/script.ts b/src/js/script.ts index 20143a0..ac2e9e4 100644 --- a/src/js/script.ts +++ b/src/js/script.ts @@ -1,4 +1,4 @@ -import { initializeContext, Vec2, Mat4 } from "./common.js"; +import { initializeContext, Vec2, Vec3, Mat4 } from "./common.js"; import { Graphics, fullscreenCanvas, Texture } from "./graphics.js"; import * as drawing from "./draw.js"; import * as wasm from "./wasm.js"; @@ -6,7 +6,7 @@ import * as wasm from "./wasm.js"; const vertexShader = `#version 300 es - in vec2 a_position; + in vec3 a_position; in vec2 a_tex_position; in vec4 a_color; out vec2 v_tex_position; @@ -15,7 +15,7 @@ const vertexShader = uniform bool u_isTex; void main() { - vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0); + vec4 transformed = u_matrix * vec4(a_position.xyz, 1.0); gl_Position = transformed; @@ -53,17 +53,19 @@ const fragmentShader = function draw(gfx: Graphics, angle: number, tex: Texture) { gfx.clear(0, 0, 0, 0); - let left = 0; let right = gfx.ctx.canvas.width; - let bottom = 0; + let left = 0; let top = gfx.ctx.canvas.height; - let near = -1; - let far = 1; + let bottom = 0; + let near = -100; + let far = 100; - let m = Mat4.orthographic(left, right, bottom, top, near, far); - m = m.mult(Mat4.rotation_x(angle)); - m = m.mult(Mat4.rotation_y(angle)); - m = m.mult(Mat4.rotation_z(angle)); + let mo = Mat4.orthographic(left, right, bottom, top, near, far); + let mi = Mat4.isometric(); + let m = mi.multNew(mo); + //m = m.multNew(Mat4.rotation_x(angle)); + //m = m.multNew(Mat4.rotation_y(angle)); + //m = m.multNew(Mat4.rotation_z(angle)); gfx.ctx.uniformMatrix4fv( gfx.getUniform("u_matrix"), @@ -71,17 +73,17 @@ function draw(gfx: Graphics, angle: number, tex: Texture) { m.splat() ); - drawing.drawRectangle( - gfx, - new Vec2(gfx.ctx.canvas.width / 2 - 200, gfx.ctx.canvas.height / 2 - 200), - new Vec2(400, 400), - tex); - - drawing.drawRectangle( - gfx, - new Vec2(100, 100), - new Vec2(100, 100), - [Math.sin(angle), Math.cos(angle), -Math.sin(angle), 1]); + let exts = new Vec3(50, 50, 20); + for (let i = 0; i < 10; ++i) { + for (let j = 0; j < 10; ++j) { + //drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [Math.sin(angle * i + j), Math.cos(angle * i + j), -Math.sin(angle * i + j), 1]); + + if ((i + j) % 2) + drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 1, 1]); + else + drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [0, 0, 0, 1]); + } + } } (async () => { @@ -93,7 +95,7 @@ function draw(gfx: Graphics, angle: number, tex: Texture) { fullscreenCanvas(gfx, canvasId); const a_position = gfx.createAttribute("a_position"); - a_position.format(2, gfx.ctx.FLOAT, false, 0, 0); + a_position.format(3, gfx.ctx.FLOAT, false, 0, 0); const a_color = gfx.createAttribute("a_color"); a_color.format(4, gfx.ctx.FLOAT, false, 0, 0);