Fixed, camera translate, matrix transform and texture transparency

This commit is contained in:
Maciej Samborski 2024-12-31 16:03:15 +01:00
parent e936b626f3
commit 14d5db166e
17 changed files with 333 additions and 156 deletions

BIN
assets/grass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

BIN
assets/greenary.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

BIN
assets/log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

38
src/js/assets.js Normal file
View File

@ -0,0 +1,38 @@
import { Texture } from "./graphics.js";
export const Colors = {
Red: [1, 0, 0, 1],
Green: [0, 1, 0, 1],
Blue: [0, 0, 1, 1],
Brown: [0.341, 0.337, 0.204, 1],
};
export function AssetToTileFill(name) {
let asset = assets.get(name);
return {
left: asset,
top: asset,
right: asset,
};
}
export class Assets {
assets = new Map();
loaded = false;
push(name, asset) {
if (this.assets.get(name) !== undefined)
throw new Error("Asset name occupied!");
this.assets.set(name, asset);
}
get(name) {
if (!this.loaded)
throw new Error("Tried to assess assets without loading them!");
return this.assets.get(name);
}
async load(ctx) {
assets.push("city", await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg"));
assets.push("wall", await Texture.load(ctx, "../../assets/wall.png"));
assets.push("grass", await Texture.load(ctx, "../../assets/grass.png"));
assets.push("leaves", await Texture.load(ctx, "../../assets/greenary.png"));
assets.push("log", await Texture.load(ctx, "../../assets/log.png"));
this.loaded = true;
}
}
export const assets = new Assets();

53
src/js/assets.ts Normal file
View File

@ -0,0 +1,53 @@
import {Texture} from "./graphics.js";
import {TileFill} from "./world.js";
export type Color = [number, number, number, number]
export const Colors = {
Red : [1, 0, 0, 1] as Color,
Green : [0, 1, 0, 1] as Color,
Blue : [0, 0, 1, 1] as Color,
Brown : [0.341, 0.337, 0.204, 1] as Color,
}
export type Asset = Texture;
export function AssetToTileFill(name: string): TileFill {
let asset = assets.get(name);
return {
left: asset,
top: asset,
right: asset,
};
}
export class Assets {
assets: Map<string, Asset> = new Map();
loaded: boolean = false;
push(name: string, asset: Asset) {
if (this.assets.get(name) !== undefined)
throw new Error("Asset name occupied!");
this.assets.set(name, asset);
}
get(name: string): Asset {
if (!this.loaded)
throw new Error("Tried to assess assets without loading them!");
return this.assets.get(name)!;
}
async load(ctx: WebGL2RenderingContext) {
assets.push("city", await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg"));
assets.push("wall", await Texture.load(ctx, "../../assets/wall.png"));
assets.push("grass", await Texture.load(ctx, "../../assets/grass.png"));
assets.push("leaves", await Texture.load(ctx, "../../assets/greenary.png"));
assets.push("log", await Texture.load(ctx, "../../assets/log.png"));
this.loaded = true;
}
}
export const assets = new Assets();

View File

@ -1,4 +0,0 @@
export let Red = [1, 0, 0, 1];
export let Green = [0, 1, 0, 1];
export let Blue = [0, 0, 1, 1];
export let Brown = [0.341, 0.337, 0.204, 1];

View File

@ -1,6 +0,0 @@
export type Color = [number, number, number, number]
export let Red : Color = [1, 0, 0, 1];
export let Green : Color = [0, 1, 0, 1];
export let Blue : Color = [0, 0, 1, 1];
export let Brown : Color = [0.341, 0.337, 0.204, 1];

View File

@ -280,13 +280,20 @@ class Mat4 {
return new Mat4(data);
}
static isometric() {
let m = new Mat4(new Float32Array([
return new Mat4(new Float32Array([
1, -1, 0, 0,
1, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
return m;
}
static isometric_inverse() {
return new Mat4(new Float32Array([
0.5, 0.5, 0, 0,
-0.5, 0.5, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
}
static rotation_x(angle) {
let data = new Float32Array([
@ -347,17 +354,17 @@ class Mat4 {
this.data[i * 4 + col] = data[i];
}
transform(v) {
let x = v.x * this.x(0) + v.x * this.x(1) + v.x * this.x(2) + v.x * this.x(3);
let y = v.y * this.y(0) + v.y * this.y(1) + v.y * this.y(2) + v.y * this.y(3);
let z = v.z * this.z(0) + v.z * this.z(1) + v.z * this.z(2) + v.z * this.z(3);
let w = v.w * this.w(0) + v.w * this.w(1) + v.w * this.w(2) + v.w * this.w(3);
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);
let z = v.x * this.z(0) + v.y * this.z(1) + v.z * this.z(2) + v.w * this.z(3);
let w = v.x * this.w(0) + v.y * this.w(1) + v.z * this.w(2) + v.w * this.w(3);
v.x = x;
v.y = y;
v.z = z;
v.w = w;
}
transformNew(v) {
let vec = new Vec4(v.x, v.y, v.z, v.w);
let vec = v.copy();
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);
let z = v.x * this.z(0) + v.y * this.z(1) + v.z * this.z(2) + v.w * this.z(3);

View File

@ -395,14 +395,21 @@ class Mat4 {
}
static isometric(): Mat4 {
let m = new Mat4(new Float32Array([
return new Mat4(new Float32Array([
1, -1, 0, 0,
1, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
}
return m;
static isometric_inverse(): Mat4 {
return new Mat4(new Float32Array([
0.5, 0.5, 0, 0,
-0.5, 0.5, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
]));
}
static rotation_x(angle: number): Mat4 {
@ -478,10 +485,10 @@ class Mat4 {
}
transform(v: Vec4) {
let x = v.x * this.x(0) + v.x * this.x(1) + v.x * this.x(2) + v.x * this.x(3);
let y = v.y * this.y(0) + v.y * this.y(1) + v.y * this.y(2) + v.y * this.y(3);
let z = v.z * this.z(0) + v.z * this.z(1) + v.z * this.z(2) + v.z * this.z(3);
let w = v.w * this.w(0) + v.w * this.w(1) + v.w * this.w(2) + v.w * this.w(3);
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);
let z = v.x * this.z(0) + v.y * this.z(1) + v.z * this.z(2) + v.w * this.z(3);
let w = v.x * this.w(0) + v.y * this.w(1) + v.z * this.w(2) + v.w * this.w(3);
v.x = x;
v.y = y;
@ -490,7 +497,7 @@ class Mat4 {
}
transformNew(v: Vec4): Vec4 {
let vec = new Vec4(v.x, v.y, v.z, v.w);
let vec = v.copy();
let x = v.x * this.x(0) + v.y * this.x(1) + v.z * this.x(2) + v.w * this.x(3);
let y = v.x * this.y(0) + v.y * this.y(1) + v.z * this.y(2) + v.w * this.y(3);

View File

@ -1,16 +1,17 @@
import { Vec3, Vec2 } from "./common.js";
import { Vec3, Vec2, Vec4 } from "./common.js";
import { Texture } from "./graphics.js";
import { TileEdge } from "./world.js";
function cull(bb, screen) {
if (bb.x > screen.x)
return false;
if (bb.x + bb.z < screen.x + screen.z)
return false;
if (bb.y > screen.y)
return false;
if (bb.y + bb.w < screen.y + screen.w)
return false;
return true;
// TODO: Don't assume tile size is same in all directions
function cull(point, screen, tileSize) {
if (point.x + tileSize < screen.x)
return true;
if (point.x + tileSize > screen.x + screen.z)
return true;
if (point.y - tileSize < screen.y)
return true;
if (point.y + tileSize > screen.y + screen.w)
return true;
return false;
}
export function drawTriangle(gfx, positions, color) {
const a_position = gfx.getAttribute("a_position");
@ -81,16 +82,22 @@ export function drawRectangle(gfx, corners, color) {
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6);
}
}
export function drawIsometricCube(gfx, position, exts, color, edge) {
export function drawIsometricCube(gfx, camera, position, exts, color, edge) {
let points = [
// Left Top
position,
//Top
new Vec3(position.x, position.y + exts.y, position.z),
//Mid
new Vec3(position.x + exts.x, position.y, position.z),
//Right Top
new Vec3(position.x + exts.x, position.y + exts.y, position.z),
//Bottom
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),
];
let screen = new Vec4(-camera.position.x, -camera.position.y, gfx.ctx.canvas.width, gfx.ctx.canvas.height);
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 1);
// Top
drawRectangle(gfx, [
@ -98,7 +105,7 @@ export function drawIsometricCube(gfx, position, exts, color, edge) {
points[1],
points[3],
points[2],
], color);
], color.top);
// Right Edge
if (edge == TileEdge.Right || edge == TileEdge.Both) {
drawRectangle(gfx, [
@ -106,7 +113,7 @@ export function drawIsometricCube(gfx, position, exts, color, edge) {
points[2],
points[4],
points[5],
], color);
], color.right);
}
// Left Edge
if (edge == TileEdge.Left || edge == TileEdge.Both) {
@ -115,17 +122,15 @@ export function drawIsometricCube(gfx, position, exts, color, edge) {
points[2],
points[4],
points[6],
], color);
], color.left);
}
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 0);
}
export function drawIsometricGrid(gfx, grid) {
export function drawIsometricGrid(gfx, camera, grid) {
let position = { ...grid.position };
let exts = new Vec3(grid.tileSize, grid.tileSize, 0);
let tileCoord = new Vec3(0, 0, 0);
// Optimize this by:
// 1. Skip all empty tiles by using lowTiles
// 2. tba
// TODO: Optimize this
for (let k = 0; k < grid.height; ++k) {
for (let j = 0; j < grid.length; ++j) {
for (let i = 0; i < grid.width; ++i) {
@ -137,7 +142,7 @@ export function drawIsometricGrid(gfx, grid) {
position.x += grid.tileSize;
continue;
}
drawIsometricCube(gfx, new Vec3(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, position.z), exts, tile.fill, tile.edge);
drawIsometricCube(gfx, camera, new Vec3(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, position.z), exts, tile.fill, tile.edge);
position.x += grid.tileSize;
}
position.y -= grid.tileSize;

View File

@ -1,19 +1,26 @@
import {Color} from "./colors.js";
import { Vec3, Vec2, Vec4 } from "./common.js"
import { Graphics, Texture } from "./graphics.js";
import {Grid, TileEdge} from "./world.js";
import { Vec3, Vec2, Vec4, Mat4 } from "./common.js"
import { Camera, Graphics, Texture } from "./graphics.js";
import {Grid, TileEdge, TileFill} from "./world.js";
import * as Assets from "./assets.js";
function cull(bb: Vec4, screen: Vec4): boolean {
if (bb.x > screen.x) return false;
if (bb.x + bb.z < screen.x + screen.z) return false;
// TODO: Don't assume tile size is same in all directions
function cull(point: Vec3, screen: Vec4, tileSize: number): boolean {
if (point.x + tileSize < screen.x)
return true;
if (bb.y > screen.y) return false;
if (bb.y + bb.w < screen.y + screen.w) return false;
if (point.x + tileSize > screen.x + screen.z)
return true;
return true;
if (point.y - tileSize < screen.y)
return true;
if (point.y + tileSize > screen.y + screen.w)
return true;
return false;
}
export function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Color) {
export function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color: Assets.Color) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");
@ -34,7 +41,7 @@ export function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2], color
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
}
export function drawTriangleExts(gfx: Graphics, position: Vec3, exts: Vec2, color: Color) {
export function drawTriangleExts(gfx: Graphics, position: Vec3, exts: Vec2, color: Assets.Color) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");
@ -55,7 +62,7 @@ export function drawTriangleExts(gfx: Graphics, position: Vec3, exts: Vec2, colo
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
}
export function drawRectangle(gfx: Graphics, corners: [Vec3, Vec3, Vec3, Vec3], color: Color | Texture) {
export function drawRectangle(gfx: Graphics, corners: [Vec3, Vec3, Vec3, Vec3], color: Assets.Color | Texture) {
const a_position = gfx.getAttribute("a_position");
const points: Array<number> = [
@ -99,17 +106,28 @@ export function drawRectangle(gfx: Graphics, corners: [Vec3, Vec3, Vec3, Vec3],
}
export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, color: Color | Texture, edge: TileEdge) {
export function drawIsometricCube(gfx: Graphics, camera: Camera, position: Vec3, exts: Vec3, color: TileFill, edge: TileEdge) {
let points = [
// Left Top
position,
//Top
new Vec3(position.x, position.y + exts.y, position.z),
//Mid
new Vec3(position.x + exts.x, position.y, position.z),
//Right Top
new Vec3(position.x + exts.x, position.y + exts.y, position.z),
//Bottom
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),
];
let screen = new Vec4(
-camera.position.x,
-camera.position.y,
gfx.ctx.canvas.width,
gfx.ctx.canvas.height);
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 1);
// Top
@ -121,7 +139,7 @@ export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, col
points[3],
points[2],
],
color);
color.top);
// Right Edge
@ -134,7 +152,7 @@ export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, col
points[4],
points[5],
],
color);
color.right);
}
// Left Edge
@ -147,20 +165,18 @@ export function drawIsometricCube(gfx: Graphics, position: Vec3, exts: Vec3, col
points[4],
points[6],
],
color);
color.left);
}
gfx.ctx.uniform1i(gfx.getUniform("u_isIso"), 0);
}
export function drawIsometricGrid(gfx: Graphics, grid: Grid) {
export function drawIsometricGrid(gfx: Graphics, camera: Camera, grid: Grid) {
let position = {...grid.position} as Vec3;
let exts = new Vec3(grid.tileSize, grid.tileSize, 0);
let tileCoord = new Vec3(0, 0, 0);
// Optimize this by:
// 1. Skip all empty tiles by using lowTiles
// 2. tba
// TODO: Optimize this
for (let k = 0; k < grid.height; ++k) {
for (let j = 0; j < grid.length; ++j) {
for (let i = 0; i < grid.width; ++i) {
@ -175,7 +191,7 @@ export function drawIsometricGrid(gfx: Graphics, grid: Grid) {
continue;
}
drawIsometricCube(gfx, new Vec3(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, position.z), exts, tile.fill, tile.edge);
drawIsometricCube(gfx, camera, new Vec3(position.x - grid.tileSize / 2 * k, position.y + grid.tileSize / 2 * k, position.z), exts, tile.fill, tile.edge);
position.x += grid.tileSize;
}
@ -186,7 +202,7 @@ export function drawIsometricGrid(gfx: Graphics, grid: Grid) {
}
}
export function drawRectangleExts(gfx: Graphics, position: Vec3, exts: Vec2, color: Color | Texture) {
export function drawRectangleExts(gfx: Graphics, position: Vec3, exts: Vec2, color: Assets.Color | Texture) {
const a_position = gfx.getAttribute("a_position");
const points: Array<number> = [
@ -229,7 +245,7 @@ export function drawRectangleExts(gfx: Graphics, position: Vec3, exts: Vec2, col
}
export function drawCircle(gfx: Graphics, position: Vec2, radius: number, color: Color) {
export function drawCircle(gfx: Graphics, position: Vec2, radius: number, color: Assets.Color) {
const points: Array<Vec2> = new Array<Vec2>();
const precision = 40;
@ -250,7 +266,7 @@ export function drawCircle(gfx: Graphics, position: Vec2, radius: number, color:
}
}
export function drawLine(gfx: Graphics, A: Vec2, B: Vec2, color: Color) {
export function drawLine(gfx: Graphics, A: Vec2, B: Vec2, color: Assets.Color) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");

View File

@ -52,6 +52,8 @@ export class Graphics {
ctx.bindVertexArray(this.vao);
ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.useProgram(this.program);
ctx.blendFunc(ctx.SRC_ALPHA, ctx.ONE_MINUS_SRC_ALPHA);
ctx.enable(ctx.BLEND);
}
clear(r, g, b, a) {
this.ctx.clearColor(r, g, b, a);
@ -122,9 +124,8 @@ export class Texture {
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.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.NEAREST);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.NEAREST);
ctx.bindTexture(ctx.TEXTURE_2D, null);
return new Texture(tex, image.width, image.height);
}
@ -150,6 +151,7 @@ export class Camera {
dt = 0;
position;
movement;
speed = 600;
constructor(position) {
this.position = position;
this.movement = new Vec4(0, 0, 0, 0);
@ -157,7 +159,7 @@ export class Camera {
update(dt) {
this.dt = dt;
let newPosition = this.movement.multScalarNew(this.dt);
this.position.x += (newPosition.x + newPosition.y) / 2;
this.position.y += newPosition.z + newPosition.w;
this.position.x += (newPosition.x + newPosition.y) * this.speed;
this.position.y += (newPosition.z + newPosition.w) * this.speed;
}
}

View File

@ -65,6 +65,9 @@ export class Graphics {
ctx.bindVertexArray(this.vao);
ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.useProgram(this.program);
ctx.blendFunc(ctx.SRC_ALPHA, ctx.ONE_MINUS_SRC_ALPHA);
ctx.enable(ctx.BLEND);
}
clear(r: number, g: number, b: number, a: number) {
@ -161,9 +164,8 @@ export class Texture {
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.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.NEAREST);
ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.NEAREST);
ctx.bindTexture(ctx.TEXTURE_2D, null);
return new Texture(tex, image.width, image.height);
@ -194,6 +196,7 @@ export class Camera {
dt: number = 0;
position: Vec3;
movement: Vec4;
speed: number = 600;
constructor(position: Vec3) {
this.position = position;
@ -204,8 +207,8 @@ export class Camera {
this.dt = dt;
let newPosition = this.movement.multScalarNew(this.dt);
this.position.x += (newPosition.x + newPosition.y) / 2;
this.position.y += newPosition.z + newPosition.w;
this.position.x += (newPosition.x + newPosition.y) * this.speed;
this.position.y += (newPosition.z + newPosition.w) * this.speed;
}
}

View File

@ -1,15 +1,16 @@
import { initializeContext, Vec3, Mat4, Vec2 } from "./common.js";
import { initializeContext, Vec3, Mat4, Vec4, Vec2 } from "./common.js";
import { Graphics, fullscreenCanvas, Camera } from "./graphics.js";
import * as drawing from "./draw.js";
import * as wasm from "./wasm.js";
import { Input } from "./input.js";
import { Grid, Tile, tree } from "./world.js";
import { bush, Grid, Tile, tree } from "./world.js";
import * as Assets from "./assets.js";
const vertexShader = `#version 300 es
in vec3 a_position;
in vec2 a_tex_position;
in vec4 a_color;
out vec2 v_tex_position;
in vec4 a_color;
out vec4 v_color;
uniform mat4 u_matrix;
uniform bool u_isTex;
@ -28,6 +29,7 @@ const vertexShader = `#version 300 es
if (u_isIso) {
vec4 isometric = Iso * vec4(a_position.xyz, 1.0);
orthographic = u_matrix * isometric;
//orthographic = u_matrix * vec4(a_position.xyz, 1.0);
} else {
orthographic = u_matrix * vec4(a_position.xyz, 1.0);
}
@ -63,27 +65,18 @@ const fragmentShader = `#version 300 es
function draw(gfx, camera, dt, grid) {
gfx.clear(0, 0, 0, 0);
camera.update(dt);
let zoom = 2;
let zoom = 1;
let right = gfx.ctx.canvas.width * zoom;
let left = -right * zoom;
let left = 0;
let top = gfx.ctx.canvas.height * zoom;
let bottom = -top * zoom;
let bottom = 0;
let near = -100;
let far = 100;
let mo = Mat4.orthographic(left, right, bottom, top, near, far);
let mt = Mat4.translate(camera.position);
let m = mo.multNew(mt);
let m = mt.multNew(mo);
gfx.ctx.uniformMatrix4fv(gfx.getUniform("u_matrix"), false, m.splat());
//let exts = new Vec3(50, 50, 20);
//for (let i = 0; i < 10; ++i) {
// for (let j = 0; j < 10; ++j) {
// if ((i + j) % 2)
// drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 0, 1, 1], TileEdge.None);
// else
// drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 0, 1], TileEdge.None);
// }
//}
drawing.drawIsometricGrid(gfx, grid);
drawing.drawIsometricGrid(gfx, camera, grid);
}
function addDefaultKeybinds(input, camera) {
input.addKeyAction("KeyA", [], camera, (c) => {
@ -123,14 +116,22 @@ function addDefaultKeybinds(input, camera) {
gfx.createUniform("u_matrix");
gfx.createUniform("u_isTex");
gfx.createUniform("u_isIso");
//let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
//let wall = await Texture.load(ctx, "../../assets/wall.png");
let camera = new Camera(new Vec3(0, 0, 0));
let grid = new Grid(new Vec3(-800, 0, 0), 100, 20, 20, 10);
grid.fillLayer(new Tile([0, 0, 1, 1]), 0);
for (let i = 0; i < 5; i++) {
tree(grid, new Vec2(Math.floor(Math.random() * 19), Math.floor(Math.random() * 19)));
}
let camera = new Camera(new Vec3(0, 0, -1));
await Assets.assets.load(ctx);
let m = Mat4.isometric();
let size = 20;
let grid = new Grid(m.transformNew(new Vec4(ctx.canvas.width / 4, ctx.canvas.height / 2, 0, 1)).reduce(), 24, size, size, 10);
grid.fillLayer(new Tile({
top: Assets.assets.get("grass"),
right: Assets.Colors.Brown,
left: Assets.Colors.Brown,
}), 0);
tree(grid, new Vec2(size / 2, size / 2));
bush(grid, new Vec2(size / 2 + 4, size / 2 + 4));
//for (let i = 0; i < 10; i++) {
// tree(grid, new Vec2(Math.floor(Math.random() * size - 1), Math.floor(Math.random() * size - 1)));
//}
//grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(0, 29, 1));
let prevTimestamp = 0;
const frame = (timestamp) => {
const deltaTime = (timestamp - prevTimestamp) / 1000;
@ -143,7 +144,7 @@ function addDefaultKeybinds(input, camera) {
prevTimestamp = timestamp;
window.requestAnimationFrame(frame);
});
let input = new Input();
const input = new Input();
addDefaultKeybinds(input, camera);
let wasmgl = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm"));
const wasmgl = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm"));
})();

View File

@ -1,17 +1,18 @@
import { initializeContext, Vec3, Mat4, Vec2 } from "./common.js";
import { Graphics, fullscreenCanvas, Texture, Camera } from "./graphics.js";
import { initializeContext, Vec3, Mat4, Vec4, Vec2 } from "./common.js";
import { Graphics, fullscreenCanvas, Camera } from "./graphics.js";
import * as drawing from "./draw.js";
import * as wasm from "./wasm.js";
import { Input } from "./input.js";
import {Grid, Tile, tree} from "./world.js";
import {bush, Grid, Tile, tree} from "./world.js";
import * as Assets from "./assets.js";
const vertexShader =
`#version 300 es
in vec3 a_position;
in vec2 a_tex_position;
in vec4 a_color;
out vec2 v_tex_position;
in vec4 a_color;
out vec4 v_color;
uniform mat4 u_matrix;
uniform bool u_isTex;
@ -30,6 +31,7 @@ const vertexShader =
if (u_isIso) {
vec4 isometric = Iso * vec4(a_position.xyz, 1.0);
orthographic = u_matrix * isometric;
//orthographic = u_matrix * vec4(a_position.xyz, 1.0);
} else {
orthographic = u_matrix * vec4(a_position.xyz, 1.0);
}
@ -69,35 +71,25 @@ function draw(gfx: Graphics, camera: Camera, dt: number, grid: Grid) {
gfx.clear(0, 0, 0, 0);
camera.update(dt);
let zoom = 2;
let zoom = 1;
let right = gfx.ctx.canvas.width * zoom;
let left = -right * zoom;
let left = 0;
let top = gfx.ctx.canvas.height * zoom;
let bottom = -top * zoom;
let bottom = 0;
let near = -100;
let far = 100;
let mo = Mat4.orthographic(left, right, bottom, top, near, far);
let mt = Mat4.translate(camera.position);
let m = mo.multNew(mt);
let m = mt.multNew(mo);
gfx.ctx.uniformMatrix4fv(
gfx.getUniform("u_matrix"),
false,
m.splat()
);
//let exts = new Vec3(50, 50, 20);
//for (let i = 0; i < 10; ++i) {
// for (let j = 0; j < 10; ++j) {
// if ((i + j) % 2)
// drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 0, 1, 1], TileEdge.None);
// else
// drawing.drawIsometricCube(gfx, new Vec3(exts.x * i, 1000 - exts.y * j, 0), exts, [1, 1, 0, 1], TileEdge.None);
// }
//}
drawing.drawIsometricGrid(gfx, grid);
drawing.drawIsometricGrid(gfx, camera, grid);
}
function addDefaultKeybinds(input: Input, camera: Camera) {
@ -155,18 +147,27 @@ function addDefaultKeybinds(input: Input, camera: Camera) {
gfx.createUniform("u_isTex");
gfx.createUniform("u_isIso");
//let city = await Texture.load(ctx, "../../assets/genetica/rt/City Night.jpg");
//let wall = await Texture.load(ctx, "../../assets/wall.png");
let camera = new Camera(new Vec3(0, 0, -1));
let camera = new Camera(new Vec3(0, 0, 0));
await Assets.assets.load(ctx);
let grid = new Grid(new Vec3(-800, 0, 0), 100, 20, 20, 10);
grid.fillLayer(new Tile([0, 0, 1, 1]), 0);
let m = Mat4.isometric();
let size = 20;
let grid = new Grid(m.transformNew(new Vec4(ctx.canvas.width / 4, ctx.canvas.height / 2, 0, 1)).reduce(), 24, size, size, 10);
grid.fillLayer(new Tile({
top: Assets.assets.get("grass"),
right: Assets.Colors.Brown,
left: Assets.Colors.Brown,
}), 0);
for (let i = 0; i < 5; i++) {
tree(grid, new Vec2(Math.floor(Math.random() * 19), Math.floor(Math.random() * 19)));
}
tree(grid, new Vec2(size / 2, size / 2));
bush(grid, new Vec2(size / 2 + 4, size / 2 + 4));
//for (let i = 0; i < 10; i++) {
// tree(grid, new Vec2(Math.floor(Math.random() * size - 1), Math.floor(Math.random() * size - 1)));
//}
//grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(0, 29, 1));
let prevTimestamp = 0;
const frame = (timestamp: number) => {
@ -184,8 +185,8 @@ function addDefaultKeybinds(input: Input, camera: Camera) {
window.requestAnimationFrame(frame);
});
let input = new Input();
const input = new Input();
addDefaultKeybinds(input, camera);
let wasmgl: wasm.WASMGL = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm"));
const wasmgl: wasm.WASMGL = new wasm.WASMGL(await wasm.loadWasmModule("./src/wasm/module.wasm"));
})();

View File

@ -1,4 +1,4 @@
import * as Colors from "./colors.js";
import * as Assets from "./assets.js";
import { Vec3 } from "./common.js";
export var TileEdge;
(function (TileEdge) {
@ -8,7 +8,11 @@ export var TileEdge;
TileEdge[TileEdge["Both"] = 3] = "Both";
})(TileEdge || (TileEdge = {}));
export class Tile {
fill = [1, 0, 1, 1];
fill = {
top: [1, 0, 1, 1],
left: [0, 0, 0, 1],
right: [0, 0, 0, 1],
};
edge = TileEdge.None;
constructor(fill, edge) {
if (fill !== undefined)
@ -17,6 +21,13 @@ export class Tile {
this.edge = edge;
}
}
export function ColorToTile(c) {
return {
left: c,
top: c,
right: c,
};
}
export class Grid {
position;
tiles3d;
@ -62,12 +73,25 @@ export class Grid {
}
}
export function tree(grid, position) {
grid.setTile(new Tile(Colors.Brown, TileEdge.Both), new Vec3(position.x, position.y, 1));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 4));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 3));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 5));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 3));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 6));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 2));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 3));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.None), new Vec3(position.x, position.y, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 5));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y, 5));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 5));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 5));
}
export function bush(grid, position) {
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(2));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 2));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 2));
}

View File

@ -1,4 +1,4 @@
import * as Colors from "./colors.js";
import * as Assets from "./assets.js";
import {Vec2, Vec3} from "./common.js";
import {Texture} from "./graphics.js";
@ -9,11 +9,18 @@ export enum TileEdge {
Both,
}
export type TileFillament = Texture | Assets.Color;
export type TileFill = { left: TileFillament, top: TileFillament, right: TileFillament };
export class Tile {
fill: Texture | Colors.Color = [1, 0, 1, 1];
fill: TileFill = {
top : [1, 0, 1, 1],
left : [0, 0, 0, 1],
right : [0, 0, 0, 1],
};
edge: TileEdge = TileEdge.None;
constructor(fill?: Texture | Colors.Color, edge?: TileEdge) {
constructor(fill?: TileFill, edge?: TileEdge) {
if (fill !== undefined)
this.fill = fill;
@ -22,6 +29,14 @@ export class Tile {
}
}
export function ColorToTile(c: Assets.Color) {
return {
left: c,
top: c,
right: c,
};
}
export class Grid {
position: Vec3;
tiles3d: Tile[][];
@ -81,12 +96,27 @@ export class Grid {
}
export function tree(grid: Grid, position: Vec2) {
grid.setTile(new Tile(Colors.Brown, TileEdge.Both), new Vec3(position.x, position.y, 1));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 4));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 3));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 5));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 3));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
grid.setTile(new Tile(Colors.Green, TileEdge.Both), new Vec3(position.x, position.y, 6));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 2));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 3));
grid.setTile(new Tile(Assets.AssetToTileFill("log"), TileEdge.Both), new Vec3(position.x, position.y, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.None), new Vec3(position.x, position.y, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 5));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y, 5));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 5));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 4));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 5));
}
export function bush(grid: Grid, position: Vec2) {
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y + 1, 1));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), position.extend(2));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x + 1, position.y, 2));
grid.setTile(new Tile(Assets.AssetToTileFill("leaves"), TileEdge.Both), new Vec3(position.x, position.y + 1, 2));
}