mirror of
https://github.com/Terncode/pixel.horse.git
synced 2026-09-25 06:05:52 +02:00
99 lines
2.9 KiB
TypeScript
99 lines
2.9 KiB
TypeScript
type WebGL = WebGLRenderingContext;
|
|
type Pixels = ImageBitmap | ImageData | HTMLVideoElement | HTMLImageElement | HTMLCanvasElement;
|
|
|
|
export interface Texture2D {
|
|
handle: WebGLTexture;
|
|
width: number;
|
|
height: number;
|
|
format: number;
|
|
type: number;
|
|
}
|
|
|
|
export function createEmptyTexture(gl: WebGL, width: number, height: number, format?: number, type?: number): Texture2D {
|
|
if (format === undefined) {
|
|
format = gl.RGBA;
|
|
}
|
|
|
|
if (type === undefined) {
|
|
type = gl.UNSIGNED_BYTE;
|
|
}
|
|
|
|
const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number | null;
|
|
|
|
if (maxTextureSize != null && (width < 0 || width > maxTextureSize || height < 0 || height > maxTextureSize)) {
|
|
throw new Error('Invalid texture shape');
|
|
}
|
|
|
|
if (type === gl.FLOAT && !gl.getExtension('OES_texture_float')) {
|
|
throw new Error('Floating point textures not supported on this platform');
|
|
}
|
|
|
|
const handle = createTextureHandle(gl);
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null);
|
|
return { handle, width, height, format, type };
|
|
}
|
|
|
|
export function createTexture(gl: WebGL, data: Pixels, format?: number, type?: number): Texture2D {
|
|
if (format === undefined) {
|
|
format = gl.RGBA;
|
|
}
|
|
|
|
if (type === undefined) {
|
|
type = gl.UNSIGNED_BYTE;
|
|
}
|
|
|
|
const handle = createTextureHandle(gl);
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, format, format, type, data);
|
|
return { handle, width: data.width, height: data.height, format, type };
|
|
}
|
|
|
|
export function disposeTexture(gl: WebGL | undefined, texture: Texture2D | undefined): undefined {
|
|
try {
|
|
if (gl && texture) {
|
|
gl.deleteTexture(texture.handle);
|
|
}
|
|
} catch (e) {
|
|
DEVELOPMENT && console.error(e);
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
export function bindTexture(gl: WebGL, unit: number, texture: Texture2D | undefined) {
|
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
gl.bindTexture(gl.TEXTURE_2D, texture ? texture.handle : null);
|
|
}
|
|
|
|
export function resizeTexture(gl: WebGL, texture: Texture2D, width: number, height: number) {
|
|
width = width | 0;
|
|
height = height | 0;
|
|
|
|
const { format, type } = texture;
|
|
const maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number | null;
|
|
|
|
if (maxSize != null && (width < 0 || width > maxSize || height < 0 || height > maxSize)) {
|
|
throw new Error('Invalid texture size');
|
|
}
|
|
|
|
texture.width = width;
|
|
texture.height = height;
|
|
gl.bindTexture(gl.TEXTURE_2D, texture.handle);
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null);
|
|
}
|
|
|
|
function createTextureHandle(gl: WebGL) {
|
|
const texture = gl.createTexture();
|
|
|
|
if (!texture) {
|
|
throw new Error('Failed to create texture');
|
|
}
|
|
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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 texture;
|
|
}
|