Added support for Textures
|
@ -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
|
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 114 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 132 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 82 KiB |
|
@ -1,4 +1,5 @@
|
||||||
import { Vec2 } from "./common.js";
|
import { Vec2 } from "./common.js";
|
||||||
|
import { Texture } from "./graphics.js";
|
||||||
function drawTriangle(gfx, positions, color) {
|
function drawTriangle(gfx, positions, color) {
|
||||||
const a_position = gfx.getAttribute("a_position");
|
const a_position = gfx.getAttribute("a_position");
|
||||||
const a_color = gfx.getAttribute("a_color");
|
const a_color = gfx.getAttribute("a_color");
|
||||||
|
@ -35,7 +36,6 @@ function drawTriangleExts(gfx, position, exts, color) {
|
||||||
}
|
}
|
||||||
function drawRectangle(gfx, position, exts, color) {
|
function drawRectangle(gfx, position, exts, color) {
|
||||||
const a_position = gfx.getAttribute("a_position");
|
const a_position = gfx.getAttribute("a_position");
|
||||||
const a_color = gfx.getAttribute("a_color");
|
|
||||||
const points = [
|
const points = [
|
||||||
position.x, position.y,
|
position.x, position.y,
|
||||||
position.x + exts.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 + exts.x, position.y,
|
||||||
position.x, position.y + exts.y,
|
position.x, position.y + exts.y,
|
||||||
];
|
];
|
||||||
const colors = [
|
if (color instanceof Texture) {
|
||||||
color,
|
const a_tex_position = gfx.getAttribute("a_tex_position");
|
||||||
color,
|
const uv = [
|
||||||
color,
|
0.0, 0.0,
|
||||||
color,
|
-1.0, 0.0,
|
||||||
color,
|
0.0, -1.0,
|
||||||
color,
|
-1.0, -1.0,
|
||||||
];
|
-1.0, 0.0,
|
||||||
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
0.0, -1.0,
|
||||||
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 = [
|
||||||
|
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) {
|
function drawCircle(gfx, position, radius, color) {
|
||||||
const points = new Array();
|
const points = new Array();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Vec2, Color } from "./common.js"
|
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) {
|
function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color) {
|
||||||
const a_position = gfx.getAttribute("a_position");
|
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);
|
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_position = gfx.getAttribute("a_position");
|
||||||
const a_color = gfx.getAttribute("a_color");
|
|
||||||
|
|
||||||
const points: Array<number> = [
|
const points: Array<number> = [
|
||||||
position.x, position.y,
|
position.x, position.y,
|
||||||
|
@ -57,18 +56,38 @@ function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2, color: Color)
|
||||||
position.x, position.y + exts.y,
|
position.x, position.y + exts.y,
|
||||||
]
|
]
|
||||||
|
|
||||||
const colors: Array<number[]> = [
|
if (color instanceof Texture) {
|
||||||
color,
|
const a_tex_position = gfx.getAttribute("a_tex_position");
|
||||||
color,
|
|
||||||
color,
|
|
||||||
color,
|
|
||||||
color,
|
|
||||||
color,
|
|
||||||
];
|
|
||||||
|
|
||||||
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
|
const uv: Array<number> = [
|
||||||
a_color.data(gfx.ctx, colors.flat(), gfx.ctx.STATIC_DRAW);
|
0.0, 0.0,
|
||||||
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6);
|
-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: Array<number[]> = [
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,4 +107,30 @@ class Attribute {
|
||||||
ctx.vertexAttribPointer(this.loc, this.size, this.type, this.normalized, this.stride, this.offset);
|
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 };
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { Vec2 } from "./common.js"
|
|
||||||
|
|
||||||
function fullscreenCanvas(gfx: Graphics, id: string) {
|
function fullscreenCanvas(gfx: Graphics, id: string) {
|
||||||
const canvas = document.getElementById(id) as HTMLCanvasElement;
|
const canvas = document.getElementById(id) as HTMLCanvasElement;
|
||||||
canvas.width = window.innerWidth;
|
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<Texture> {
|
||||||
|
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<HTMLImageElement> {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const img = new Image();
|
||||||
|
img.addEventListener("load", () => {
|
||||||
|
resolve(img);
|
||||||
|
})
|
||||||
|
img.src = path;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Texture, fullscreenCanvas, Graphics, Attribute }
|
||||||
|
|
|
@ -1,32 +1,35 @@
|
||||||
import { initializeContext, Vec2, Mat4 } from "./common.js";
|
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 drawing from "./draw.js";
|
||||||
import * as wasm from "./wasm.js";
|
import * as wasm from "./wasm.js";
|
||||||
const vertexShader = `#version 300 es
|
const vertexShader = `#version 300 es
|
||||||
|
|
||||||
in vec2 a_position;
|
in vec2 a_position;
|
||||||
in vec4 a_color;
|
in vec2 a_tex_position;
|
||||||
out vec4 color;
|
out vec2 v_tex_position;
|
||||||
uniform mat4 u_matrix;
|
uniform mat4 u_matrix;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0);
|
vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0);
|
||||||
|
|
||||||
gl_Position = transformed;
|
gl_Position = transformed;
|
||||||
color = a_color;
|
v_tex_position = a_tex_position;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
const fragmentShader = `#version 300 es
|
const fragmentShader = `#version 300 es
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
in vec4 color;
|
|
||||||
|
in vec2 v_tex_position;
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
|
||||||
void main() {
|
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);
|
gfx.clear(0, 0, 0, 0);
|
||||||
let left = 0;
|
let left = 0;
|
||||||
let right = gfx.ctx.canvas.width;
|
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_y(angle));
|
||||||
m = m.mult(Mat4.rotation_z(angle));
|
m = m.mult(Mat4.rotation_z(angle));
|
||||||
gfx.ctx.uniformMatrix4fv(gfx.getUniform("u_matrix"), false, m.splat());
|
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 () => {
|
(async () => {
|
||||||
const canvasId = "game";
|
const canvasId = "game";
|
||||||
|
@ -50,16 +53,19 @@ function draw(gfx, angle) {
|
||||||
fullscreenCanvas(gfx, canvasId);
|
fullscreenCanvas(gfx, canvasId);
|
||||||
const a_position = gfx.createAttribute("a_position");
|
const a_position = gfx.createAttribute("a_position");
|
||||||
a_position.format(2, gfx.ctx.FLOAT, false, 0, 0);
|
a_position.format(2, gfx.ctx.FLOAT, false, 0, 0);
|
||||||
const a_color = gfx.createAttribute("a_color");
|
//const a_color = gfx.createAttribute("a_color");
|
||||||
a_color.format(4, gfx.ctx.FLOAT, false, 0, 0);
|
//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");
|
gfx.createUniform("u_matrix");
|
||||||
|
let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
|
||||||
let angle = 0;
|
let angle = 0;
|
||||||
let prevTimestamp = 0;
|
let prevTimestamp = 0;
|
||||||
const frame = (timestamp) => {
|
const frame = (timestamp) => {
|
||||||
const deltaTime = (timestamp - prevTimestamp) / 1000;
|
const deltaTime = (timestamp - prevTimestamp) / 1000;
|
||||||
prevTimestamp = timestamp;
|
prevTimestamp = timestamp;
|
||||||
fullscreenCanvas(gfx, "game");
|
fullscreenCanvas(gfx, "game");
|
||||||
draw(gfx, angle);
|
draw(gfx, angle, city);
|
||||||
angle += Math.PI * deltaTime * 0.5;
|
angle += Math.PI * deltaTime * 0.5;
|
||||||
window.requestAnimationFrame(frame);
|
window.requestAnimationFrame(frame);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { initializeContext, Vec2, Mat4, Vec4 } from "./common.js";
|
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 drawing from "./draw.js";
|
||||||
import * as wasm from "./wasm.js";
|
import * as wasm from "./wasm.js";
|
||||||
|
|
||||||
|
@ -7,15 +7,15 @@ const vertexShader =
|
||||||
`#version 300 es
|
`#version 300 es
|
||||||
|
|
||||||
in vec2 a_position;
|
in vec2 a_position;
|
||||||
in vec4 a_color;
|
in vec2 a_tex_position;
|
||||||
out vec4 color;
|
out vec2 v_tex_position;
|
||||||
uniform mat4 u_matrix;
|
uniform mat4 u_matrix;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0);
|
vec4 transformed = u_matrix * vec4(a_position.xy, 0.0, 1.0);
|
||||||
|
|
||||||
gl_Position = transformed;
|
gl_Position = transformed;
|
||||||
color = a_color;
|
v_tex_position = a_tex_position;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -23,17 +23,20 @@ const fragmentShader =
|
||||||
`#version 300 es
|
`#version 300 es
|
||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
in vec4 color;
|
|
||||||
|
in vec2 v_tex_position;
|
||||||
out vec4 outColor;
|
out vec4 outColor;
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
|
||||||
void main() {
|
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);
|
gfx.clear(0, 0, 0, 0);
|
||||||
|
|
||||||
let left = 0;
|
let left = 0;
|
||||||
|
@ -56,9 +59,9 @@ function draw(gfx: Graphics, angle: number) {
|
||||||
|
|
||||||
drawing.drawRectangle(
|
drawing.drawRectangle(
|
||||||
gfx,
|
gfx,
|
||||||
new Vec2(gfx.ctx.canvas.width / 2 - 50, gfx.ctx.canvas.height / 2 - 50),
|
new Vec2(gfx.ctx.canvas.width / 2 - 200, gfx.ctx.canvas.height / 2 - 200),
|
||||||
new Vec2(100, 100),
|
new Vec2(400, 400),
|
||||||
[1, 0, 0, 1]);
|
tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -72,11 +75,16 @@ function draw(gfx: Graphics, angle: number) {
|
||||||
const a_position = gfx.createAttribute("a_position");
|
const a_position = gfx.createAttribute("a_position");
|
||||||
a_position.format(2, gfx.ctx.FLOAT, false, 0, 0);
|
a_position.format(2, gfx.ctx.FLOAT, false, 0, 0);
|
||||||
|
|
||||||
const a_color = gfx.createAttribute("a_color");
|
//const a_color = gfx.createAttribute("a_color");
|
||||||
a_color.format(4, gfx.ctx.FLOAT, false, 0, 0);
|
//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");
|
gfx.createUniform("u_matrix");
|
||||||
|
|
||||||
|
let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
|
||||||
|
|
||||||
let angle = 0;
|
let angle = 0;
|
||||||
let prevTimestamp = 0;
|
let prevTimestamp = 0;
|
||||||
const frame = (timestamp: number) => {
|
const frame = (timestamp: number) => {
|
||||||
|
@ -84,7 +92,7 @@ function draw(gfx: Graphics, angle: number) {
|
||||||
prevTimestamp = timestamp;
|
prevTimestamp = timestamp;
|
||||||
|
|
||||||
fullscreenCanvas(gfx, "game");
|
fullscreenCanvas(gfx, "game");
|
||||||
draw(gfx, angle);
|
draw(gfx, angle, city);
|
||||||
angle += Math.PI * deltaTime * 0.5;
|
angle += Math.PI * deltaTime * 0.5;
|
||||||
|
|
||||||
window.requestAnimationFrame(frame);
|
window.requestAnimationFrame(frame);
|
||||||
|
|