diff --git a/assets/genetica/READ ME.txt b/assets/genetica/READ ME.txt new file mode 100644 index 0000000..a3c1105 --- /dev/null +++ b/assets/genetica/READ ME.txt @@ -0,0 +1,3 @@ +For a description of the contents of this pack, usage rights, and other useful details, go here: + +http://blog.spiralgraphics.biz/2011/02/nine-cartoon-backdrops.html \ No newline at end of file diff --git a/assets/genetica/ot/Castle Day.gtx b/assets/genetica/ot/Castle Day.gtx new file mode 100644 index 0000000..1d97de9 Binary files /dev/null and b/assets/genetica/ot/Castle Day.gtx differ diff --git a/assets/genetica/ot/Castle Night.gtx b/assets/genetica/ot/Castle Night.gtx new file mode 100644 index 0000000..3a552da Binary files /dev/null and b/assets/genetica/ot/Castle Night.gtx differ diff --git a/assets/genetica/ot/Castle Sunset.gtx b/assets/genetica/ot/Castle Sunset.gtx new file mode 100644 index 0000000..5ecd7e3 Binary files /dev/null and b/assets/genetica/ot/Castle Sunset.gtx differ diff --git a/assets/genetica/ot/City Day.gtx b/assets/genetica/ot/City Day.gtx new file mode 100644 index 0000000..bcbda05 Binary files /dev/null and b/assets/genetica/ot/City Day.gtx differ diff --git a/assets/genetica/ot/City Night.gtx b/assets/genetica/ot/City Night.gtx new file mode 100644 index 0000000..5f55a6f Binary files /dev/null and b/assets/genetica/ot/City Night.gtx differ diff --git a/assets/genetica/ot/City Sunset.gtx b/assets/genetica/ot/City Sunset.gtx new file mode 100644 index 0000000..e409c0c Binary files /dev/null and b/assets/genetica/ot/City Sunset.gtx differ diff --git a/assets/genetica/ot/Jungle Day.gtx b/assets/genetica/ot/Jungle Day.gtx new file mode 100644 index 0000000..b6001cd Binary files /dev/null and b/assets/genetica/ot/Jungle Day.gtx differ diff --git a/assets/genetica/ot/Jungle Night.gtx b/assets/genetica/ot/Jungle Night.gtx new file mode 100644 index 0000000..8bf1b1c Binary files /dev/null and b/assets/genetica/ot/Jungle Night.gtx differ diff --git a/assets/genetica/ot/Jungle Sunset.gtx b/assets/genetica/ot/Jungle Sunset.gtx new file mode 100644 index 0000000..c01f4ec Binary files /dev/null and b/assets/genetica/ot/Jungle Sunset.gtx differ diff --git a/assets/genetica/rt/Castle Day.jpg b/assets/genetica/rt/Castle Day.jpg new file mode 100644 index 0000000..575f3db Binary files /dev/null and b/assets/genetica/rt/Castle Day.jpg differ diff --git a/assets/genetica/rt/Castle Night.jpg b/assets/genetica/rt/Castle Night.jpg new file mode 100644 index 0000000..07a63c7 Binary files /dev/null and b/assets/genetica/rt/Castle Night.jpg differ diff --git a/assets/genetica/rt/Castle Sunset.jpg b/assets/genetica/rt/Castle Sunset.jpg new file mode 100644 index 0000000..824d037 Binary files /dev/null and b/assets/genetica/rt/Castle Sunset.jpg differ diff --git a/assets/genetica/rt/City Day.jpg b/assets/genetica/rt/City Day.jpg new file mode 100644 index 0000000..999b895 Binary files /dev/null and b/assets/genetica/rt/City Day.jpg differ diff --git a/assets/genetica/rt/City Night.jpg b/assets/genetica/rt/City Night.jpg new file mode 100644 index 0000000..c2cfa30 Binary files /dev/null and b/assets/genetica/rt/City Night.jpg differ diff --git a/assets/genetica/rt/City Sunset.jpg b/assets/genetica/rt/City Sunset.jpg new file mode 100644 index 0000000..f72fc88 Binary files /dev/null and b/assets/genetica/rt/City Sunset.jpg differ diff --git a/assets/genetica/rt/Jungle Day.jpg b/assets/genetica/rt/Jungle Day.jpg new file mode 100644 index 0000000..ae7d708 Binary files /dev/null and b/assets/genetica/rt/Jungle Day.jpg differ diff --git a/assets/genetica/rt/Jungle Night.jpg b/assets/genetica/rt/Jungle Night.jpg new file mode 100644 index 0000000..85ef8a3 Binary files /dev/null and b/assets/genetica/rt/Jungle Night.jpg differ diff --git a/assets/genetica/rt/Jungle Sunset.jpg b/assets/genetica/rt/Jungle Sunset.jpg new file mode 100644 index 0000000..64a8120 Binary files /dev/null and b/assets/genetica/rt/Jungle Sunset.jpg differ diff --git a/src/js/draw.js b/src/js/draw.js index 1ffc12a..926e8b7 100644 --- a/src/js/draw.js +++ b/src/js/draw.js @@ -1,4 +1,5 @@ import { Vec2 } from "./common.js"; +import { Texture } from "./graphics.js"; function drawTriangle(gfx, positions, color) { const a_position = gfx.getAttribute("a_position"); const a_color = gfx.getAttribute("a_color"); @@ -35,7 +36,6 @@ function drawTriangleExts(gfx, position, exts, color) { } function drawRectangle(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, @@ -44,17 +44,35 @@ function drawRectangle(gfx, position, exts, color) { position.x + exts.x, position.y, position.x, position.y + exts.y, ]; - const colors = [ - color, - color, - color, - color, - color, - 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); + 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); + gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, color.tex); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); + } + else { + const a_color = gfx.getAttribute("a_color"); + const colors = [ + color, + color, + color, + color, + color, + 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); + } } function drawCircle(gfx, position, radius, color) { const points = new Array(); diff --git a/src/js/draw.ts b/src/js/draw.ts index e3275be..685e151 100644 --- a/src/js/draw.ts +++ b/src/js/draw.ts @@ -1,5 +1,5 @@ import { Vec2, Color } from "./common.js" -import { Graphics } from "./graphics.js"; +import { Graphics, Texture } from "./graphics.js"; function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color) { const a_position = gfx.getAttribute("a_position"); @@ -43,9 +43,8 @@ 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) { +function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2, color: Color | Texture) { const a_position = gfx.getAttribute("a_position"); - const a_color = gfx.getAttribute("a_color"); const points: Array = [ position.x, position.y, @@ -57,18 +56,38 @@ function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2, color: Color) position.x, position.y + exts.y, ] - const colors: Array = [ - color, - color, - color, - color, - color, - color, - ]; + 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_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW); - gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); + a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW); + a_tex_position.data(gfx.ctx, uv, gfx.ctx.STATIC_DRAW); + gfx.ctx.bindTexture(gfx.ctx.TEXTURE_2D, color.tex); + gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6); + } else { + const a_color = gfx.getAttribute("a_color"); + + const colors: Array = [ + color, + color, + color, + color, + color, + 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); + } } diff --git a/src/js/graphics.js b/src/js/graphics.js index e7e2db7..b411e8d 100644 --- a/src/js/graphics.js +++ b/src/js/graphics.js @@ -107,4 +107,30 @@ class Attribute { ctx.vertexAttribPointer(this.loc, this.size, this.type, this.normalized, this.stride, this.offset); } } -export { fullscreenCanvas, Graphics, Attribute }; +class Texture { + tex; + constructor(tex) { + this.tex = tex; + } + static async load(ctx, path) { + let image = await loadTexture(path); + let tex = ctx.createTexture(); + ctx.bindTexture(ctx.TEXTURE_2D, tex); + ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, image); + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR); + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR_MIPMAP_NEAREST); + ctx.generateMipmap(ctx.TEXTURE_2D); + ctx.bindTexture(ctx.TEXTURE_2D, null); + return new Texture(tex); + } +} +async function loadTexture(path) { + return new Promise(resolve => { + const img = new Image(); + img.addEventListener("load", () => { + resolve(img); + }); + img.src = path; + }); +} +export { Texture, fullscreenCanvas, Graphics, Attribute }; diff --git a/src/js/graphics.ts b/src/js/graphics.ts index 1518381..59f8375 100644 --- a/src/js/graphics.ts +++ b/src/js/graphics.ts @@ -1,5 +1,3 @@ -import { Vec2 } from "./common.js" - function fullscreenCanvas(gfx: Graphics, id: string) { const canvas = document.getElementById(id) as HTMLCanvasElement; canvas.width = window.innerWidth; @@ -145,4 +143,36 @@ class Attribute { } } -export { fullscreenCanvas, Graphics, Attribute } +class Texture { + tex: WebGLTexture | null; + + constructor(tex: WebGLTexture) { + this.tex = tex; + } + + static async load(ctx: WebGL2RenderingContext, path: string): Promise { + let image = await loadTexture(path); + + let tex = ctx.createTexture(); + ctx.bindTexture(ctx.TEXTURE_2D, tex); + ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, image); + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR); + ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR_MIPMAP_NEAREST); + ctx.generateMipmap(ctx.TEXTURE_2D); + ctx.bindTexture(ctx.TEXTURE_2D, null); + + return new Texture(tex); + } +} + +async function loadTexture(path: string): Promise { + return new Promise(resolve => { + const img = new Image(); + img.addEventListener("load", () => { + resolve(img); + }) + img.src = path; + }); +} + +export { Texture, fullscreenCanvas, Graphics, Attribute } diff --git a/src/js/script.js b/src/js/script.js index 6e80429..3dadfb5 100644 --- a/src/js/script.js +++ b/src/js/script.js @@ -1,32 +1,35 @@ import { initializeContext, Vec2, Mat4 } from "./common.js"; -import { Graphics, fullscreenCanvas } from "./graphics.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 vec4 a_color; - out vec4 color; + in vec2 a_tex_position; + out vec2 v_tex_position; uniform mat4 u_matrix; void main() { vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0); gl_Position = transformed; - color = a_color; + v_tex_position = a_tex_position; } `; const fragmentShader = `#version 300 es precision highp float; - in vec4 color; + + in vec2 v_tex_position; out vec4 outColor; + uniform sampler2D u_texture; + void main() { - outColor = color; + outColor = texture(u_texture, v_tex_position); } `; -function draw(gfx, angle) { +function draw(gfx, angle, tex) { gfx.clear(0, 0, 0, 0); let left = 0; let right = gfx.ctx.canvas.width; @@ -39,7 +42,7 @@ function draw(gfx, angle) { m = m.mult(Mat4.rotation_y(angle)); m = m.mult(Mat4.rotation_z(angle)); gfx.ctx.uniformMatrix4fv(gfx.getUniform("u_matrix"), false, m.splat()); - drawing.drawRectangle(gfx, new Vec2(gfx.ctx.canvas.width / 2 - 50, gfx.ctx.canvas.height / 2 - 50), new Vec2(100, 100), [1, 0, 0, 1]); + drawing.drawRectangle(gfx, new Vec2(gfx.ctx.canvas.width / 2 - 200, gfx.ctx.canvas.height / 2 - 200), new Vec2(400, 400), tex); } (async () => { const canvasId = "game"; @@ -50,16 +53,19 @@ function draw(gfx, angle) { fullscreenCanvas(gfx, canvasId); const a_position = gfx.createAttribute("a_position"); a_position.format(2, 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_color = gfx.createAttribute("a_color"); + //a_color.format(4, gfx.ctx.FLOAT, false, 0, 0); + const a_tex_position = gfx.createAttribute("a_tex_position"); + a_tex_position.format(2, gfx.ctx.FLOAT, false, 0, 0); gfx.createUniform("u_matrix"); + let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg"); let angle = 0; let prevTimestamp = 0; const frame = (timestamp) => { const deltaTime = (timestamp - prevTimestamp) / 1000; prevTimestamp = timestamp; fullscreenCanvas(gfx, "game"); - draw(gfx, angle); + draw(gfx, angle, city); angle += Math.PI * deltaTime * 0.5; window.requestAnimationFrame(frame); }; diff --git a/src/js/script.ts b/src/js/script.ts index 5121268..5e1a546 100644 --- a/src/js/script.ts +++ b/src/js/script.ts @@ -1,5 +1,5 @@ import { initializeContext, Vec2, Mat4, Vec4 } from "./common.js"; -import { Graphics, fullscreenCanvas } from "./graphics.js"; +import { Graphics, fullscreenCanvas, Texture } from "./graphics.js"; import * as drawing from "./draw.js"; import * as wasm from "./wasm.js"; @@ -7,15 +7,15 @@ const vertexShader = `#version 300 es in vec2 a_position; - in vec4 a_color; - out vec4 color; + in vec2 a_tex_position; + out vec2 v_tex_position; uniform mat4 u_matrix; void main() { vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0); gl_Position = transformed; - color = a_color; + v_tex_position = a_tex_position; } `; @@ -23,17 +23,20 @@ const fragmentShader = `#version 300 es precision highp float; - in vec4 color; + + in vec2 v_tex_position; out vec4 outColor; + uniform sampler2D u_texture; + void main() { - outColor = color; + outColor = texture(u_texture, v_tex_position); } `; -function draw(gfx: Graphics, angle: number) { +function draw(gfx: Graphics, angle: number, tex: Texture) { gfx.clear(0, 0, 0, 0); let left = 0; @@ -56,9 +59,9 @@ function draw(gfx: Graphics, angle: number) { drawing.drawRectangle( gfx, - new Vec2(gfx.ctx.canvas.width / 2 - 50, gfx.ctx.canvas.height / 2 - 50), - new Vec2(100, 100), - [1, 0, 0, 1]); + new Vec2(gfx.ctx.canvas.width / 2 - 200, gfx.ctx.canvas.height / 2 - 200), + new Vec2(400, 400), + tex); } (async () => { @@ -72,11 +75,16 @@ function draw(gfx: Graphics, angle: number) { const a_position = gfx.createAttribute("a_position"); a_position.format(2, 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_color = gfx.createAttribute("a_color"); + //a_color.format(4, gfx.ctx.FLOAT, false, 0, 0); + + const a_tex_position = gfx.createAttribute("a_tex_position"); + a_tex_position.format(2, gfx.ctx.FLOAT, false, 0, 0); gfx.createUniform("u_matrix"); + let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg"); + let angle = 0; let prevTimestamp = 0; const frame = (timestamp: number) => { @@ -84,7 +92,7 @@ function draw(gfx: Graphics, angle: number) { prevTimestamp = timestamp; fullscreenCanvas(gfx, "game"); - draw(gfx, angle); + draw(gfx, angle, city); angle += Math.PI * deltaTime * 0.5; window.requestAnimationFrame(frame);