webgl_game/script.ts

192 lines
5.1 KiB
TypeScript

import { Vec2 } from "./common.js";
import { Graphics } from "./graphics.js";
const vertexShader =
`#version 300 es
in vec2 a_position;
in vec4 a_color;
out vec4 color;
uniform vec2 u_resolution;
void main() {
vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0;
color = a_color;
gl_Position = vec4(clipSpace.xy, 0.0, 1.0);
}
`;
const fragmentShader =
`#version 300 es
precision highp float;
in vec4 color;
out vec4 outColor;
void main() {
outColor = color;
}
`;
function initializeContext(canvasId: string): WebGL2RenderingContext | null {
const canvas = document.getElementById(canvasId) as HTMLCanvasElement;
const ctx = canvas.getContext("webgl2", {antialias: false});
return ctx;
}
function drawTriangle(gfx: Graphics, positions: [Vec2, Vec2, Vec2]) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");
const points: Array<number> = [
positions[0].x, positions[0].y,
positions[1].x, positions[1].y,
positions[2].x, positions[2].y,
]
const color: Array<number> = [
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1,
];
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
a_color.data(gfx.ctx, color, gfx.ctx.STATIC_DRAW);
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
}
function drawTriangleExts(gfx: Graphics, position: Vec2, exts: Vec2) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");
const points: Array<number> = [
position.x, position.y,
position.x + exts.x, position.y,
position.x, position.y + exts.y,
]
const color: Array<number> = [
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1,
];
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
a_color.data(gfx.ctx, color, gfx.ctx.STATIC_DRAW);
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 3);
}
function drawRectangle(gfx: Graphics, position: Vec2, exts: Vec2) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");
const points: Array<number> = [
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,
]
const color: Array<number> = [
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1,
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1,
];
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
a_color.data(gfx.ctx, color, gfx.ctx.STATIC_DRAW);
gfx.ctx.drawArrays(gfx.ctx.TRIANGLES, 0, 6);
}
function drawCircle(gfx: Graphics, position: Vec2, radius: number) {
const points: Array<Vec2> = new Array<Vec2>();
const precision = 40;
const angle = 2.0*Math.PI/precision;
let a = 0;
for (let i = 0; i < precision; ++i) {
var vec = Vec2.angle(a);
vec.mult(radius);
a += angle;
points.push(vec);
}
for (let i = 0; i < points.length; i++) {
const current = points[i];
const next = points[(i + 1) % points.length];
let center = position;
drawTriangle(gfx, [center, center.addNew(current), center.addNew(next)]);
}
}
function drawLine(gfx: Graphics, A: Vec2, B: Vec2) {
const a_position = gfx.getAttribute("a_position");
const a_color = gfx.getAttribute("a_color");
let points: Array<number> = [
A.x, A.y,
B.x, B.y,
];
const color: Array<number> = [
1, 0, 0, 1,
0, 0, 1, 1,
];
a_position.data(gfx.ctx, points, gfx.ctx.STATIC_DRAW);
a_color.data(gfx.ctx, color, gfx.ctx.STATIC_DRAW);
gfx.ctx.drawArrays(gfx.ctx.LINES, 0, 2);
}
function fullscreenCanvas(id: string) {
const canvas = document.getElementById(id) as HTMLCanvasElement;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function draw(gfx: Graphics) {
const position: Vec2 = new Vec2(gfx.ctx.canvas.width / 2 - 100, gfx.ctx.canvas.height / 2 - 100);
gfx.clear(0, 0, 0, 0);
gfx.ctx.uniform2f(gfx.getUniform("u_resolution"), gfx.ctx.canvas.width, gfx.ctx.canvas.height);
drawRectangle(gfx, position, new Vec2(200, 200))
drawTriangle(gfx, [new Vec2(100, 100), new Vec2(200, 100), new Vec2(100, 200)]);
drawTriangleExts(gfx, new Vec2(200, 200), new Vec2(-100, -100));
drawCircle(gfx, new Vec2(400, 200), 100);
drawLine(gfx, new Vec2(100, 600), new Vec2(600, 600));
}
(() => {
const canvasId = "game";
fullscreenCanvas(canvasId);
const ctx = initializeContext(canvasId);
if (ctx === null) return;
const gfx = new Graphics(ctx, vertexShader, fragmentShader);
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);
gfx.createUniform("u_resolution");
draw(gfx);
window.onresize = () => {
fullscreenCanvas(canvasId);
draw(gfx);
}
})();