webgl_game/graphics.js

111 lines
3.6 KiB
JavaScript

function fullscreenCanvas(gfx, id) {
const canvas = document.getElementById(id);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
gfx.ctx.viewport(0, 0, canvas.width, canvas.height);
}
function createShader(ctx, type, source) {
var shader = ctx.createShader(type);
if (!shader) {
throw new Error("Couldn't create shader: " + type);
}
ctx.shaderSource(shader, source);
ctx.compileShader(shader);
var success = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS);
if (!success) {
console.log(ctx.getShaderInfoLog(shader));
ctx.deleteShader(shader);
throw new Error("Couldn't compile shader: " + type);
}
return shader;
}
function createProgram(ctx, vertexShaderSource, fragmentShaderSource) {
var program = ctx.createProgram();
if (vertexShaderSource !== null) {
const vs = createShader(ctx, ctx.VERTEX_SHADER, vertexShaderSource);
ctx.attachShader(program, vs);
}
if (fragmentShaderSource !== null) {
const fs = createShader(ctx, ctx.FRAGMENT_SHADER, fragmentShaderSource);
ctx.attachShader(program, fs);
}
ctx.linkProgram(program);
var success = ctx.getProgramParameter(program, ctx.LINK_STATUS);
if (!success) {
console.log(ctx.getProgramInfoLog(program));
ctx.deleteProgram(program);
throw new Error("Failed to create program!");
}
return program;
}
class Graphics {
ctx;
program;
attribs = new Map();
uniforms = new Map();
vao;
constructor(ctx, vs, fs) {
this.ctx = ctx;
this.program = createProgram(ctx, vs, fs);
this.vao = ctx.createVertexArray();
ctx.bindVertexArray(this.vao);
ctx.viewport(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.useProgram(this.program);
}
clear(r, g, b, a) {
this.ctx.clearColor(r, g, b, a);
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT);
}
createAttribute(name) {
const attrib = new Attribute(this.ctx, this.program, name);
this.attribs.set(name, attrib);
return attrib;
}
getAttribute(name) {
const attrib = this.attribs.get(name);
if (attrib === undefined)
throw new Error("Tried to get uninitialized attribute: " + name);
return attrib;
}
createUniform(name) {
const loc = this.ctx.getUniformLocation(this.program, name);
if (loc === null)
throw new Error("Couldn't get location for uniform: " + name);
this.uniforms.set(name, loc);
}
getUniform(name) {
const loc = this.uniforms.get(name);
if (loc === undefined)
throw new Error("Tried to get uninitialized uniform: " + name);
return loc;
}
}
class Attribute {
loc;
buffer;
// TODO: maybe use undefined as default value?
size = 0;
type = 0;
normalized = false;
stride = 0;
offset = 0;
constructor(ctx, program, name) {
this.loc = ctx.getAttribLocation(program, name);
this.buffer = ctx.createBuffer();
ctx.enableVertexAttribArray(this.loc);
}
format(size, type, normalized, stride, offset) {
this.size = size;
this.type = type;
this.normalized = normalized;
this.stride = stride;
this.offset = offset;
}
data(ctx, data, usage) {
ctx.bindBuffer(ctx.ARRAY_BUFFER, this.buffer);
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(data), usage);
ctx.vertexAttribPointer(this.loc, this.size, this.type, this.normalized, this.stride, this.offset);
}
}
export { fullscreenCanvas, Graphics, Attribute };