OGL-TypeScript
OGL-TypeScript is a comprehensive TypeScript port of the minimal WebGL library, OGL, designed to enhance development with robust type definitions and essential code completion. Currently stable at version 0.1.40, it meticulously tracks the releases and API changes of its upstream counterpart, OGL (currently mirroring OGL 0.0.71). The library's core focus is to provide a lightweight and unopinionated foundation for building high-performance 3D graphics directly with WebGL in the browser. Its key differentiators include a significantly small bundle size, direct and low-level access to WebGL APIs, and the added benefit of TypeScript's type safety, which makes managing complex WebGL shaders and rendering pipelines more efficient and less prone to runtime errors compared to plain JavaScript OGL. The release cadence is tightly coupled with OGL's updates, typically seeing new minor versions released to align with new OGL features, fixes, or API refinements.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'getContext')
cause The `Renderer` constructor was called without a valid HTMLCanvasElement, or the provided canvas was null/undefined, preventing WebGL context creation.fixEnsure `document.createElement('canvas')` successfully creates an element and it's appended to the DOM, or pass an existing, valid canvas element (e.g., `canvas: document.getElementById('my-canvas')`). -
SyntaxError: The requested module 'ogl-typescript' does not provide an export named 'SomeMissingExport'
cause Attempting to import a named symbol that does not exist or is misspelled within the `ogl-typescript` package, or it was renamed in a new version.fixReview the `ogl-typescript` type definitions or documentation (or the original OGL documentation) to verify the correct symbol name and its export status. Ensure case sensitivity is respected. -
Property 'someProperty' does not exist on type '...' (TypeScript error)
cause A TypeScript compilation error indicating that an accessed property or method is not part of the expected type, often due to an API change in the underlying OGL library that `ogl-typescript` ports, or incorrect usage.fixCheck the version compatibility between your `ogl-typescript` package and the corresponding OGL version's API documentation. Update your code to reflect the current API, or consider upgrading `ogl-typescript` if the feature was added recently.
Warnings
- breaking OGL-TypeScript acts as a direct port of the original OGL library. Consequently, any API changes or breaking updates introduced in upstream OGL versions will directly propagate to ogl-typescript, often leading to breaking changes in minor versions (e.g., 0.1.x).
- gotcha Incorrect or delayed WebGL context initialization, or improper canvas element handling, can lead to rendering failures or errors like 'Cannot read properties of undefined (reading 'getContext')'.
- gotcha Shader compilation errors in the `Program` constructor are common. Issues often stem from GLSL syntax mistakes, undeclared uniforms/attributes, or type mismatches within the shaders.
Install
-
npm install ogl-typescript -
yarn add ogl-typescript -
pnpm add ogl-typescript
Imports
- Renderer
const Renderer = require('ogl-typescript').Rendererimport { Renderer } from 'ogl-typescript' - Camera
import Camera from 'ogl-typescript'
import { Camera } from 'ogl-typescript' - Mesh
import { Mesh } from 'ogl'import { Mesh, Program, Geometry } from 'ogl-typescript'
Quickstart
import { Renderer, Camera, Transform, Program, Geometry, Mesh } from 'ogl-typescript';
// 1. Setup Renderer
const renderer = new Renderer({
canvas: document.createElement('canvas'),
width: window.innerWidth,
height: window.innerHeight,
dpr: Math.min(window.devicePixelRatio, 2),
});
document.body.appendChild(renderer.canvas);
// 2. Setup Camera
const camera = new Camera({ fov: 45 });
camera.position.set(0, 0, 5);
camera.lookAt([0, 0, 0]);
// 3. Create a Scene (as a Transform) to hold objects
const scene = new Transform();
// 4. Create Geometry (a simple plane)
const geometry = new Geometry(renderer.gl, {
position: {
size: 3,
data: new Float32Array([
-1, 1, 0, // Top-left
-1, -1, 0, // Bottom-left
1, -1, 0, // Bottom-right
1, 1, 0, // Top-right
]),
},
uv: {
size: 2,
data: new Float32Array([
0, 1,
0, 0,
1, 0,
1, 1,
]),
},
index: {
data: new Uint16Array([
0, 1, 2,
0, 2, 3,
]),
},
});
// 5. Create a basic Program (shader) to define material properties
const program = new Program(renderer.gl, {
vertex: /* glsl */ `
attribute vec3 position;
attribute vec2 uv;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragment: /* glsl */ `
precision highp float;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(vUv.x, vUv.y, 0.5, 1.0);
}
`,
});
// 6. Create a Mesh by combining geometry and program, then add to scene
const mesh = new Mesh(renderer.gl, { geometry, program });
mesh.setParent(scene);
// 7. Render Loop for animation
function update() {
requestAnimationFrame(update);
// Rotate the mesh for visual interest
mesh.rotation.y -= 0.005;
mesh.rotation.x -= 0.003;
renderer.render({ scene, camera });
}
requestAnimationFrame(update);
// Basic resize handling to keep aspect ratio correct
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.perspective({ aspect: window.innerWidth / window.innerHeight });
});