mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-03-20 10:47:13 +01:00
125 lines
3.6 KiB
TypeScript
125 lines
3.6 KiB
TypeScript
export function compileShader(gl: WebGL2RenderingContext, shaderSource: string, shaderType: GLenum) {
|
|
const shader = gl.createShader(shaderType);
|
|
if (!shader) {
|
|
throw new Error(`failed to create shader of type ${shaderType}`);
|
|
}
|
|
|
|
gl.shaderSource(shader, shaderSource);
|
|
gl.compileShader(shader);
|
|
|
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
throw new Error(`Shader compilation failed: ${gl.getShaderInfoLog(shader)}`);
|
|
}
|
|
|
|
return shader;
|
|
}
|
|
|
|
export function createProgramFromSources(
|
|
gl: WebGL2RenderingContext,
|
|
vertexShaderSource: string,
|
|
fragmentShaderSource: string,
|
|
) {
|
|
const vertexShader = compileShader(gl, vertexShaderSource, gl.VERTEX_SHADER);
|
|
const fragmentShader = compileShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);
|
|
|
|
const program = gl.createProgram();
|
|
if (!program) {
|
|
throw new Error('failed to create vertex + fragment program');
|
|
}
|
|
|
|
gl.attachShader(program, vertexShader);
|
|
gl.attachShader(program, fragmentShader);
|
|
gl.linkProgram(program);
|
|
|
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
throw new Error(`Program link failed: ${gl.getProgramInfoLog(program)}`);
|
|
}
|
|
|
|
return program;
|
|
}
|
|
|
|
export function createOffscreenCanvasRenderingContext(): WebGL2RenderingContext {
|
|
const canvas = document.createElement('canvas');
|
|
const gl = canvas.getContext('webgl2');
|
|
|
|
if (!gl) {
|
|
throw new Error('failed to create WebGL2 context');
|
|
}
|
|
|
|
if (!gl.getExtension('EXT_color_buffer_float')) {
|
|
throw new Error('failed to enable EXT_color_buffer_float extension');
|
|
}
|
|
|
|
return gl;
|
|
}
|
|
|
|
export interface TextureParameters {
|
|
width: number;
|
|
height: number;
|
|
internalFormat: GLenum;
|
|
format: GLenum;
|
|
type: GLenum;
|
|
pixels?: ImageBitmap;
|
|
}
|
|
|
|
export interface Texture extends TextureParameters {
|
|
object: WebGLTexture;
|
|
}
|
|
|
|
export interface Framebuffer {
|
|
object: WebGLFramebuffer;
|
|
texture: Texture;
|
|
}
|
|
|
|
export function createNonMippedLinearTexture(gl: WebGL2RenderingContext, params: TextureParameters): Texture {
|
|
const texture = gl.createTexture();
|
|
if (!texture) {
|
|
throw new Error('failed to create texture');
|
|
}
|
|
|
|
const level = 0;
|
|
const internalFormat = params.internalFormat;
|
|
const border = 0;
|
|
const format = params.format;
|
|
const type = params.type;
|
|
const data = params.pixels;
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
if (data) {
|
|
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, format, type, data);
|
|
} else {
|
|
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, params.width, params.height, border, format, type, null);
|
|
}
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
|
|
return { object: texture, ...params };
|
|
}
|
|
|
|
export function createNonMippedLinearTextureFbo(gl: WebGL2RenderingContext, params: TextureParameters): Framebuffer {
|
|
const texture = createNonMippedLinearTexture(gl, params);
|
|
const fbo = gl.createFramebuffer();
|
|
if (!fbo) {
|
|
throw new Error('failed to create framebuffer object');
|
|
}
|
|
|
|
gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
|
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture.object, 0);
|
|
|
|
return { object: fbo, texture };
|
|
}
|
|
|
|
export function getUniformLocation(
|
|
gl: WebGL2RenderingContext,
|
|
program: WebGLProgram,
|
|
name: string,
|
|
): WebGLUniformLocation {
|
|
const location = gl.getUniformLocation(program, name);
|
|
if (!location) {
|
|
throw new Error('failed to get uniform location');
|
|
}
|
|
|
|
return location;
|
|
}
|