nothing works

This commit is contained in:
2026-03-11 16:55:14 -03:00
parent 680aedc2bb
commit 244f0eb741
3 changed files with 456 additions and 113 deletions
+350 -107
View File
@@ -1,21 +1,26 @@
import { Camera } from "../components/camera.ts"; import { Camera } from "../components/camera.ts";
import { mat4_mul, mat4_perspective, mat4_view } from "./math.ts";
const MAX_SPRITES = 10000; const MAX_SPRITES = 10000;
const VERTS_PER_SPRITE = 6; const VERTS_PER_SPRITE = 6;
const FLOATS_PER_VERT = 8; const FLOATS_PER_VERT = 9;
export let gl: WebGLRenderingContext; export let gl: WebGLRenderingContext;
export let canvas: HTMLCanvasElement; export let canvas: HTMLCanvasElement;
let program: WebGLProgram; let program: WebGLProgram;
let buffer: WebGLBuffer; let buffer: WebGLBuffer;
const default_camera = new Camera(); // const default_camera = new Camera();
let camera: Camera = default_camera; // let camera: Camera = default_camera;
//
// let camera_pos_loc: WebGLUniformLocation | null;
// let camera_zoom_loc: WebGLUniformLocation | null;
// let camera_rot_loc: WebGLUniformLocation | null;
// let camera_offset_loc: WebGLUniformLocation | null;
let camera_pos_loc: WebGLUniformLocation | null; export const projection = new Float32Array(16);
let camera_zoom_loc: WebGLUniformLocation | null; export const view = new Float32Array(16);
let camera_rot_loc: WebGLUniformLocation | null; export const mvp_matrix = new Float32Array(16);
let camera_offset_loc: WebGLUniformLocation | null;
const vertex_data = new Float32Array(MAX_SPRITES * VERTS_PER_SPRITE * FLOATS_PER_VERT); const vertex_data = new Float32Array(MAX_SPRITES * VERTS_PER_SPRITE * FLOATS_PER_VERT);
let vert_index = 0; let vert_index = 0;
@@ -23,64 +28,56 @@ let vert_index = 0;
let pos_loc: GLint; let pos_loc: GLint;
let uv_loc: GLint; let uv_loc: GLint;
let resolution_loc: WebGLUniformLocation | null; let resolution_loc: WebGLUniformLocation | null;
let _texture_loc: WebGLUniformLocation | null; let texture_loc: WebGLUniformLocation | null;
let mvp_loc: WebGLUniformLocation | null;
let col_diffuse_loc: WebGLUniformLocation | null;
let current_texture: WebGLTexture | null = null; let current_texture: WebGLTexture | null = null;
export let white_tex: WebGLTexture | null = null; export let white_tex: WebGLTexture | null = null;
const vertex_src = ` export const camera = {
attribute vec2 aPos; x: 3,
attribute vec2 aUV; y: 3,
attribute vec4 aColor; z: 3,
varying vec2 vUV; pitch: 0,
varying vec4 vColor; yaw: 0,
roll: 0,
uniform vec2 uResolution; fov: Math.PI / 3,
uniform vec2 uCameraPos; near: 0.1,
uniform float uCameraZoom; far: 1000,
uniform float uCameraRot; };
uniform vec2 uCameraOffset;
void main(){ let mode3d = false;
let active_camera = camera;
// world → camera space const vertex_src = `#version 300 es
vec2 pos = aPos - uCameraPos; precision mediump float;
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec4 vertexColor;
out vec2 fragTexCoord;
out vec4 fragColor;
uniform mat4 mvp;
// rotation void main() {
float c = cos(uCameraRot); fragTexCoord = vertexTexCoord;
float s = sin(uCameraRot); fragColor = vertexColor;
pos = vec2( gl_Position = mvp*vec4(vertexPosition, 1.0);
pos.x * c - pos.y * s,
pos.x * s + pos.y * c
);
// zoom
pos *= uCameraZoom;
// screen offset (center camera)
pos += uCameraOffset;
// convert to clip space
vec2 zero = pos / uResolution;
vec2 clip = zero * 2.0 - 1.0;
gl_Position = vec4(clip * vec2(1.0,-1.0),0.0,1.0);
vUV = aUV;
vColor = aColor;
} }
`; `;
const fragment_src = ` const fragment_src = `#version 300 es
precision mediump float; precision mediump float;
varying vec2 vUV; in vec2 fragTexCoord;
varying vec4 vColor; in vec4 fragColor;
uniform sampler2D uTex; out vec4 finalColor;
uniform sampler2D texture0;
uniform vec4 colDiffuse;
void main() { void main() {
vec4 texColor = texture2D(uTex, vUV); vec4 texelColor = texture(texture0, fragTexCoord);
gl_FragColor = texColor * vColor; finalColor = texelColor*colDiffuse*fragColor;
} }
`; `;
@@ -88,9 +85,10 @@ export function init_window(canvas_element: HTMLCanvasElement) {
canvas = canvas_element; canvas = canvas_element;
canvas.width = 1800; canvas.width = 1800;
canvas.height = 900; canvas.height = 900;
const ctx = canvas.getContext("webgl");
const ctx = canvas.getContext("webgl2");
if (!ctx) { if (!ctx) {
throw new Error("WebGL not supported"); throw new Error("WebGL2 not supported");
} }
gl = ctx; gl = ctx;
@@ -98,41 +96,41 @@ export function init_window(canvas_element: HTMLCanvasElement) {
program = create_program(vertex_src, fragment_src); program = create_program(vertex_src, fragment_src);
buffer = gl.createBuffer()!; buffer = gl.createBuffer()!;
gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
const stride = FLOATS_PER_VERT * 4; const stride = FLOATS_PER_VERT * 4;
pos_loc = gl.getAttribLocation(program, "aPos"); pos_loc = gl.getAttribLocation(program, "vertexPosition");
gl.enableVertexAttribArray(pos_loc); gl.enableVertexAttribArray(pos_loc);
gl.vertexAttribPointer(pos_loc, 2, gl.FLOAT, false, stride, 0); gl.vertexAttribPointer(pos_loc, 3, gl.FLOAT, false, stride, 0);
uv_loc = gl.getAttribLocation(program, "aUV"); uv_loc = gl.getAttribLocation(program, "vertexTexCoord");
gl.enableVertexAttribArray(uv_loc); gl.enableVertexAttribArray(uv_loc);
gl.vertexAttribPointer(uv_loc, 2, gl.FLOAT, false, stride, 8); gl.vertexAttribPointer(uv_loc, 2, gl.FLOAT, false, stride, 12);
const color_loc = gl.getAttribLocation(program, "aColor"); const color_loc = gl.getAttribLocation(program, "vertexColor");
gl.enableVertexAttribArray(color_loc); gl.enableVertexAttribArray(color_loc);
gl.vertexAttribPointer(color_loc, 4, gl.FLOAT, false, FLOATS_PER_VERT * 4, 16); gl.vertexAttribPointer(color_loc, 4, gl.FLOAT, false, stride, 20);
resolution_loc = gl.getUniformLocation(program, "uResolution"); mvp_loc = gl.getUniformLocation(program, "mvp");
_texture_loc = gl.getUniformLocation(program, "uTex"); texture_loc = gl.getUniformLocation(program, "texture0");
col_diffuse_loc = gl.getUniformLocation(program, "colDiffuse");
camera_pos_loc = gl.getUniformLocation(program, "uCameraPos");
camera_zoom_loc = gl.getUniformLocation(program, "uCameraZoom");
camera_rot_loc = gl.getUniformLocation(program, "uCameraRot");
camera_offset_loc = gl.getUniformLocation(program, "uCameraOffset");
gl.useProgram(program); gl.useProgram(program);
gl.uniform2f(resolution_loc, canvas.width, canvas.height);
gl.enable(gl.BLEND); gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.disable(gl.CULL_FACE);
create_white_texture(); create_white_texture();
update_mvp(canvas.width, canvas.height);
} }
export function begin_drawing() { export function begin_drawing() {
update_2d_mvp();
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
vert_index = 0; vert_index = 0;
} }
@@ -140,13 +138,48 @@ export function end_drawing() {
flush_batch(); flush_batch();
} }
export const ortho_matrix = new Float32Array(16);
export function update_2d_mvp() {
const w = canvas.width;
const h = canvas.height;
const l = 0, r = w, t = 0, b = h, n = -1, f = 1;
ortho_matrix[0] = 2 / (r - l);
ortho_matrix[1] = 0;
ortho_matrix[2] = 0;
ortho_matrix[3] = 0;
ortho_matrix[4] = 0;
ortho_matrix[5] = 2 / (t - b);
ortho_matrix[6] = 0;
ortho_matrix[7] = 0;
ortho_matrix[8] = 0;
ortho_matrix[9] = 0;
ortho_matrix[10] = -2 / (f - n);
ortho_matrix[11] = 0;
ortho_matrix[12] = -(r + l) / (r - l);
ortho_matrix[13] = -(t + b) / (t - b);
ortho_matrix[14] = -(f + n) / (f - n);
ortho_matrix[15] = 1;
}
export function begin_mode_2d(new_camera: Camera) { export function begin_mode_2d(new_camera: Camera) {
camera = new_camera; mode3d = false;
gl.disable(gl.DEPTH_TEST);
vert_index = 0;
update_2d_mvp();
gl.uniformMatrix4fv(mvp_loc, false, ortho_matrix);
} }
export function end_mode_2d() { export function end_mode_2d() {
flush_batch(); flush_batch();
camera = default_camera; // camera = default_camera;
} }
export function begin_clip(x: number, y: number, width: number, height: number) { export function begin_clip(x: number, y: number, width: number, height: number) {
@@ -174,21 +207,20 @@ export function flush_batch() {
gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertex_data.subarray(0, vert_index), gl.STREAM_DRAW); gl.bufferData(gl.ARRAY_BUFFER, vertex_data.subarray(0, vert_index), gl.STREAM_DRAW);
gl.useProgram(program); if (mode3d) {
gl.uniformMatrix4fv(mvp_loc, false, mvp_matrix);
} else {
gl.uniformMatrix4fv(mvp_loc, false, ortho_matrix);
}
// const stride = FLOATS_PER_VERT * 4; gl.uniform4f(col_diffuse_loc, 1, 1, 1, 1);
// gl.enableVertexAttribArray(pos_loc);
// gl.vertexAttribPointer(pos_loc, 2, gl.FLOAT, false, stride, 0);
// gl.enableVertexAttribArray(uv_loc);
// gl.vertexAttribPointer(uv_loc, 2, gl.FLOAT, false, stride, 8);
gl.uniform2f(camera_pos_loc, Math.floor(camera.x), Math.floor(camera.y));
gl.uniform1f(camera_zoom_loc, camera.zoom);
gl.uniform1f(camera_rot_loc, camera.rotation);
gl.uniform2f(camera_offset_loc, camera.offset_x, camera.offset_y);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, current_texture); gl.bindTexture(gl.TEXTURE_2D, current_texture);
gl.drawArrays(gl.TRIANGLES, 0, vert_index / 8); gl.uniform1i(texture_loc, 0);
gl.drawArrays(gl.TRIANGLES, 0, vert_index / FLOATS_PER_VERT);
vert_index = 0; vert_index = 0;
} }
@@ -209,20 +241,71 @@ export function push_quad(
const x2 = dx + dw; const x2 = dx + dw;
const y2 = dy + dh; const y2 = dy + dh;
// deno-fmt-ignore let i = vert_index;
const v = [
dx, dy, u0, v0, r, g, b, a,
x2, dy, u1, v0, r, g, b, a,
dx, y2, u0, v1, r, g, b, a,
x2, dy, u1, v0, r, g, b, a, // triangle 1
x2, y2, u1, v1, r, g, b, a, vertex_data[i++] = dx;
dx, y2, u0, v1, r, g, b, a, vertex_data[i++] = dy;
]; vertex_data[i++] = 0;
vertex_data[i++] = u0;
vertex_data[i++] = v0;
vertex_data[i++] = r;
vertex_data[i++] = g;
vertex_data[i++] = b;
vertex_data[i++] = a;
for (let i = 0; i < v.length; i += 1) { vertex_data[i++] = x2;
vertex_data[vert_index++] = v[i]; vertex_data[i++] = dy;
} vertex_data[i++] = 0;
vertex_data[i++] = u1;
vertex_data[i++] = v0;
vertex_data[i++] = r;
vertex_data[i++] = g;
vertex_data[i++] = b;
vertex_data[i++] = a;
vertex_data[i++] = dx;
vertex_data[i++] = y2;
vertex_data[i++] = 0;
vertex_data[i++] = u0;
vertex_data[i++] = v1;
vertex_data[i++] = r;
vertex_data[i++] = g;
vertex_data[i++] = b;
vertex_data[i++] = a;
// triangle 2
vertex_data[i++] = x2;
vertex_data[i++] = dy;
vertex_data[i++] = 0;
vertex_data[i++] = u1;
vertex_data[i++] = v0;
vertex_data[i++] = r;
vertex_data[i++] = g;
vertex_data[i++] = b;
vertex_data[i++] = a;
vertex_data[i++] = x2;
vertex_data[i++] = y2;
vertex_data[i++] = 0;
vertex_data[i++] = u1;
vertex_data[i++] = v1;
vertex_data[i++] = r;
vertex_data[i++] = g;
vertex_data[i++] = b;
vertex_data[i++] = a;
vertex_data[i++] = dx;
vertex_data[i++] = y2;
vertex_data[i++] = 0;
vertex_data[i++] = u0;
vertex_data[i++] = v1;
vertex_data[i++] = r;
vertex_data[i++] = g;
vertex_data[i++] = b;
vertex_data[i++] = a;
vert_index = i;
} }
export function resize_canvas() { export function resize_canvas() {
@@ -238,7 +321,8 @@ export function resize_canvas() {
gl.viewport(0, 0, width, height); gl.viewport(0, 0, width, height);
gl.useProgram(program); gl.useProgram(program);
gl.uniform2f(resolution_loc, width, height); // gl.uniform2f(resolution_loc, width, height);
update_mvp(canvas.width, canvas.height);
} }
} }
@@ -250,23 +334,34 @@ export function set_current_texture(texture: WebGLTexture) {
current_texture = texture; current_texture = texture;
} }
function create_shader(type: number, src: string): WebGLShader { function compile_shader(type: number, src: string) {
const s = gl.createShader(type)!; const shader = gl.createShader(type)!;
gl.shaderSource(s, src);
gl.compileShader(s); gl.shaderSource(shader, src);
return s; gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(shader));
throw new Error("Shader compile failed");
}
return shader;
} }
function create_program(vs: string, fs: string): WebGLProgram { function create_program(vs_src: string, fs_src: string) {
const program = gl.createProgram(); const vs = compile_shader(gl.VERTEX_SHADER, vs_src);
const fs = compile_shader(gl.FRAGMENT_SHADER, fs_src);
const v = create_shader(gl.VERTEX_SHADER, vs); const program = gl.createProgram()!;
const f = create_shader(gl.FRAGMENT_SHADER, fs); gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.attachShader(program, v);
gl.attachShader(program, f);
gl.linkProgram(program); gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
throw new Error("Program link failed");
}
return program; return program;
} }
@@ -283,3 +378,151 @@ function create_white_texture() {
white_tex = tex; white_tex = tex;
} }
function update_mvp(width: number, height: number) {
const l = 0;
const r = width;
const b = height;
const t = 0;
const n = -1;
const f = 1;
mvp_matrix[0] = 2 / (r - l);
mvp_matrix[1] = 0;
mvp_matrix[2] = 0;
mvp_matrix[3] = 0;
mvp_matrix[4] = 0;
mvp_matrix[5] = 2 / (t - b);
mvp_matrix[6] = 0;
mvp_matrix[7] = 0;
mvp_matrix[8] = 0;
mvp_matrix[9] = 0;
mvp_matrix[10] = -2 / (f - n);
mvp_matrix[11] = 0;
mvp_matrix[12] = -(r + l) / (r - l);
mvp_matrix[13] = -(t + b) / (t - b);
mvp_matrix[14] = -(f + n) / (f - n);
mvp_matrix[15] = 1;
}
export function push_cube(
x: number,
y: number,
z: number,
w: number,
h: number,
d: number,
r = 1,
g = 1,
b = 1,
a = 1,
) {
set_current_texture(white_tex!);
const x2 = x + w;
const y2 = y + h;
const z2 = z + d;
const u0 = 0, v0 = 0;
const u1 = 1, v1 = 1;
let i = vert_index;
function v(px: number, py: number, pz: number, u: number, vv: number) {
vertex_data[i++] = px;
vertex_data[i++] = py;
vertex_data[i++] = pz;
vertex_data[i++] = u;
vertex_data[i++] = vv;
vertex_data[i++] = r;
vertex_data[i++] = g;
vertex_data[i++] = b;
vertex_data[i++] = a;
}
v(x, y, z2, u0, v0);
v(x2, y, z2, u1, v0);
v(x, y2, z2, u0, v1);
v(x2, y, z2, u1, v0);
v(x2, y2, z2, u1, v1);
v(x, y2, z2, u0, v1);
v(x2, y, z, u0, v0);
v(x, y, z, u1, v0);
v(x2, y2, z, u0, v1);
v(x, y, z, u1, v0);
v(x, y2, z, u1, v1);
v(x2, y2, z, u0, v1);
v(x, y, z, u0, v0);
v(x, y, z2, u1, v0);
v(x, y2, z, u0, v1);
v(x, y, z2, u1, v0);
v(x, y2, z2, u1, v1);
v(x, y2, z, u0, v1);
v(x2, y, z2, u0, v0);
v(x2, y, z, u1, v0);
v(x2, y2, z2, u0, v1);
v(x2, y, z, u1, v0);
v(x2, y2, z, u1, v1);
v(x2, y2, z2, u0, v1);
v(x, y2, z2, u0, v0);
v(x2, y2, z2, u1, v0);
v(x, y2, z, u0, v1);
v(x2, y2, z2, u1, v0);
v(x2, y2, z, u1, v1);
v(x, y2, z, u0, v1);
v(x, y, z, u0, v0);
v(x2, y, z, u1, v0);
v(x, y, z2, u0, v1);
v(x2, y, z, u1, v0);
v(x2, y, z2, u1, v1);
v(x, y, z2, u0, v1);
vert_index = i;
}
export function begin_mode_3d() {
flush_batch();
mode3d = true;
active_camera = camera;
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
vert_index = 0;
update_camera();
}
export function end_mode_3d() {
if (!mode3d) {
return;
}
flush_batch();
mode3d = false;
gl.disable(gl.DEPTH_TEST);
}
export function update_camera() {
mat4_perspective(
projection,
camera.fov,
canvas.width / canvas.height,
camera.near,
camera.far,
);
mat4_view(view);
mat4_mul(mvp_matrix, projection, view);
}
+64 -4
View File
@@ -1,6 +1,7 @@
export function perspective(out: Float32Array, fov: number, aspect: number, near: number, far: number) { import { camera } from "./core.ts";
export function mat4_perspective(out: Float32Array, fov: number, aspect: number, near: number, far: number) {
const f = 1 / Math.tan(fov / 2); const f = 1 / Math.tan(fov / 2);
const nf = 1 / (near - far);
out[0] = f / aspect; out[0] = f / aspect;
out[1] = 0; out[1] = 0;
@@ -14,11 +15,70 @@ export function perspective(out: Float32Array, fov: number, aspect: number, near
out[8] = 0; out[8] = 0;
out[9] = 0; out[9] = 0;
out[10] = (far + near) * nf; out[10] = -(far + near) / (far - near);
out[11] = -1; out[11] = -1;
out[12] = 0; out[12] = 0;
out[13] = 0; out[13] = 0;
out[14] = (2 * far * near) * nf; out[14] = -(2 * far * near) / (far - near);
out[15] = 0; out[15] = 0;
} }
export function mat4_view(out: Float32Array) {
const cx = camera.x;
const cy = camera.y;
const cz = camera.z;
const yaw = camera.yaw;
const pitch = camera.pitch;
const cosY = Math.cos(yaw);
const sinY = Math.sin(yaw);
const cosP = Math.cos(pitch);
const sinP = Math.sin(pitch);
const fx = cosP * sinY;
const fy = sinP;
const fz = cosP * cosY;
const rx = cosY;
const rz = -sinY;
const ux = -sinP * sinY;
const uy = cosP;
const uz = -sinP * cosY;
out[0] = rx;
out[1] = ux;
out[2] = -fx;
out[3] = 0;
out[4] = 0;
out[5] = uy;
out[6] = -fy;
out[7] = 0;
out[8] = rz;
out[9] = uz;
out[10] = -fz;
out[11] = 0;
out[12] = -(rx * cx + rz * cz);
out[13] = -(ux * cx + uy * cy + uz * cz);
out[14] = fx * cx + fy * cy + fz * cz;
out[15] = 1;
}
export function mat4_mul(out: Float32Array, a: Float32Array, b: Float32Array) {
for (let i = 0; i < 4; i++) {
const ai0 = a[i];
const ai1 = a[i + 4];
const ai2 = a[i + 8];
const ai3 = a[i + 12];
out[i] = ai0 * b[0] + ai1 * b[1] + ai2 * b[2] + ai3 * b[3];
out[i + 4] = ai0 * b[4] + ai1 * b[5] + ai2 * b[6] + ai3 * b[7];
out[i + 8] = ai0 * b[8] + ai1 * b[9] + ai2 * b[10] + ai3 * b[11];
out[i + 12] = ai0 * b[12] + ai1 * b[13] + ai2 * b[14] + ai3 * b[15];
}
}
+42 -2
View File
@@ -10,6 +10,7 @@ import { render_dimension } from "./rendering/dimension.ts";
import { render_player_hotbar } from "./rendering/player.ts"; import { render_player_hotbar } from "./rendering/player.ts";
import { begin_mode_2d, end_mode_2d } from "../renderer/mod.ts"; import { begin_mode_2d, end_mode_2d } from "../renderer/mod.ts";
import { PlayerComponent } from "../player.ts"; import { PlayerComponent } from "../player.ts";
import { begin_mode_3d, end_mode_3d, push_cube } from "../renderer/core.ts";
export class RenderSystem extends System { export class RenderSystem extends System {
constructor() { constructor() {
@@ -17,7 +18,7 @@ export class RenderSystem extends System {
} }
update(world: World, _delta: number): void { update(world: World, _delta: number): void {
const camera_entity = world.get_entities().values().find((e) => e.get(Camera)?.active); /*const camera_entity = world.get_entities().values().find((e) => e.get(Camera)?.active);
const camera = camera_entity?.get(Camera); const camera = camera_entity?.get(Camera);
if (!camera) { if (!camera) {
@@ -55,6 +56,45 @@ export class RenderSystem extends System {
if (player_component) { if (player_component) {
render_player_hotbar(player_component.player_inventory); render_player_hotbar(player_component.player_inventory);
} }
} }*/
begin_mode_3d();
push_cube(
-0.5,
-0.5,
-0.5,
1,
1,
1,
1,
0,
0,
1,
);
push_cube(
0.5,
0.5,
0.5,
1,
1,
1,
1,
0,
0,
1,
);
push_cube(
0,
0,
0,
1,
1,
1,
1,
0,
0,
1,
);
end_mode_3d();
} }
} }