Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 52 additions & 25 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ export function glsl(literals: TemplateStringsArray, ...placeholders: string[])
}

function addShader(gl: WebGLRenderingContext, program: WebGLProgram, type: number, source: string) {
// fixme: check results, throw error on failure
const shader = gl.createShader(type) as WebGLShader;
gl.shaderSource(shader, source);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
const compilationLog = gl.getShaderInfoLog(shader);
gl.deleteShader(shader);

throw new Error(`Failed compiling shader: ${compilationLog ?? "unknown error"}`);
}

gl.attachShader(program, shader);
return shader;
}
Expand All @@ -33,33 +40,53 @@ export function createShaderProgram<TC extends WebGLRenderingContext, TD extends
fragmentShaderSource: string,
data: TD
): ShaderProgram<TD> {
const program = gl.createProgram() as WebGLProgram;
const setters: any = {};
const vertexShader = addShader(gl, program, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = addShader(gl, program, gl.FRAGMENT_SHADER, fragmentShaderSource);
gl.linkProgram(program);
gl.useProgram(program);
let program = gl.createProgram();
if (!program) throw new Error("Could not create a new program");

for (const key of Object.keys(data)) {
const fn = data[key];
const factory = factoriesGl2[fn];
if (!factory) throw new Error(`Can't handle ${fn}!`);
const location = fn.startsWith("uniform")
? gl.getUniformLocation(program, key)
: gl.getAttribLocation(program, key);
setters[key] = factory(gl as unknown as WebGL2RenderingContext, location as any);
}
let vertexShader: WebGLShader | undefined;
let fragmentShader: WebGLShader | undefined;

return {
...setters,
use() {
gl.useProgram(program);
},
dispose() {
const dispose = () => {
if (program) {
gl.useProgram(null);
gl.deleteShader(fragmentShader);
gl.deleteShader(vertexShader);
if (fragmentShader) gl.deleteShader(fragmentShader);
if (vertexShader) gl.deleteShader(vertexShader);
gl.deleteProgram(program);
},
program = null;
}
};

try {
vertexShader = addShader(gl, program, gl.VERTEX_SHADER, vertexShaderSource);
fragmentShader = addShader(gl, program, gl.FRAGMENT_SHADER, fragmentShaderSource);

gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
const infoLog = gl.getProgramInfoLog(program);
throw new Error(`Failed linking program: ${infoLog ?? "unknown error"}`);
}
gl.useProgram(program);

const setters: any = {};
for (const key of Object.keys(data)) {
const fn = data[key];
const factory = factoriesGl2[fn];
if (!factory) throw new Error(`Can't handle ${fn}!`);
const location = fn.startsWith("uniform")
? gl.getUniformLocation(program, key)
: gl.getAttribLocation(program, key);
setters[key] = factory(gl as unknown as WebGL2RenderingContext, location as any);
}

return {
...setters,
use() {
gl.useProgram(program);
},
dispose,
};
} catch (e) {
dispose();
throw e;
}
}