├── .gitignore ├── test ├── assets │ ├── atlas.png │ ├── emap │ │ ├── nx.png │ │ ├── ny.png │ │ ├── nz.png │ │ ├── px.png │ │ ├── py.png │ │ └── pz.png │ ├── favicon.ico │ └── peppers.png ├── 01-attributes.html ├── 02-indices.html ├── 03-uniforms.html ├── 04-varyings.html └── 05-matrices.html ├── .prettierrc.json ├── src ├── types │ ├── UniformMap.ts │ ├── UniformValue.ts │ ├── VaryingMap.ts │ ├── AttributeMap.ts │ ├── Prism.ts │ ├── BlendEquationSet.ts │ ├── Rectangle.ts │ ├── BlendFunctionSet.ts │ ├── Pair.ts │ ├── ColorMask.ts │ ├── Color.ts │ ├── Stencil.ts │ ├── DebugInfo.ts │ ├── BlendFunctionFullSet.ts │ ├── VaryingValue.ts │ ├── AttributeValue.ts │ └── ExtensionObject.ts ├── constants │ ├── Orientation.ts │ ├── SyncStatus.ts │ ├── TextureCompareMode.ts │ ├── Face.ts │ ├── FramebufferAttachment.ts │ ├── ShaderType.ts │ ├── WrapMode.ts │ ├── TextureTarget.ts │ ├── FramebufferTarget.ts │ ├── SyncClientStatus.ts │ ├── BlendEquation.ts │ ├── CubeFace.ts │ ├── ErrorCode.ts │ ├── TextureFilter.ts │ ├── TestFunction.ts │ ├── Primitive.ts │ ├── BufferTarget.ts │ ├── MipmapTarget.ts │ ├── DataType.ts │ ├── FramebufferStatus.ts │ ├── TextureDataType.ts │ ├── BlendFunction.ts │ ├── BufferUsage.ts │ ├── VariableType.ts │ └── RenderbufferFormat.ts ├── core │ ├── variables │ │ ├── uniforms │ │ │ ├── MatrixUniform.ts │ │ │ ├── MultipleValuedUniform.ts │ │ │ ├── IntegerVector2Uniform.ts │ │ │ ├── IntegerVector3Uniform.ts │ │ │ ├── IntegerVector4Uniform.ts │ │ │ ├── FloatVector2Uniform.ts │ │ │ ├── FloatVector3Uniform.ts │ │ │ ├── FloatVector4Uniform.ts │ │ │ ├── UnsignedIntegerVector2Uniform.ts │ │ │ ├── UnsignedIntegerVector3Uniform.ts │ │ │ ├── UnsignedIntegerVector4Uniform.ts │ │ │ ├── FloatMatrix2x2Uniform.ts │ │ │ ├── FloatMatrix2x3Uniform.ts │ │ │ ├── FloatMatrix2x4Uniform.ts │ │ │ ├── FloatMatrix3x2Uniform.ts │ │ │ ├── FloatMatrix3x3Uniform.ts │ │ │ ├── FloatMatrix4x2Uniform.ts │ │ │ ├── FloatMatrix4x4Uniform.ts │ │ │ ├── FloatMatrix3x4Uniform.ts │ │ │ ├── FloatMatrix4x3Uniform.ts │ │ │ ├── FloatUniform.ts │ │ │ ├── IntegerUniform.ts │ │ │ ├── UnsignedIntegerUniform.ts │ │ │ ├── Vector2Uniform.ts │ │ │ ├── Vector3Uniform.ts │ │ │ ├── MatrixUniform4.ts │ │ │ ├── Vector4Uniform.ts │ │ │ ├── SamplerUniform.ts │ │ │ ├── MatrixUniform6.ts │ │ │ ├── MatrixUniform8.ts │ │ │ ├── ScalarUniform.ts │ │ │ ├── MatrixUniform9.ts │ │ │ ├── Uniform.ts │ │ │ ├── MatrixUniform12.ts │ │ │ ├── MatrixUniform16.ts │ │ │ └── createUniform.ts │ │ ├── attributes │ │ │ ├── IntegerAttribute.ts │ │ │ ├── FloatAttribute.ts │ │ │ ├── MatrixAttribute.ts │ │ │ ├── createAttribute.ts │ │ │ └── Attribute.ts │ │ ├── Variable.ts │ │ └── Varying.ts │ ├── internal │ │ ├── ApiInterface.ts │ │ └── ContextDependent.ts │ ├── Sync.ts │ ├── Renderbuffer.ts │ ├── buffers │ │ └── Buffer.ts │ └── Shader.ts ├── utility │ ├── BadValueError.ts │ ├── ImmutableError.ts │ ├── ProgramLinkError.ts │ ├── ShaderCompileError.ts │ ├── DuplicateContextError.ts │ ├── TextureFormatError.ts │ ├── UnsupportedOperationError.ts │ ├── WebglError.ts │ ├── internal │ │ ├── getDataTypeForTypedArray.ts │ │ ├── getExtensionForRenderbufferFormat.ts │ │ ├── getParameterForFramebufferTarget.ts │ │ ├── getExtensionsForFramebufferAttachmentFormat.ts │ │ ├── getParameterForTextureTarget.ts │ │ ├── getErrorCodeMessage.ts │ │ ├── getSizeOfDataType.ts │ │ ├── getParameterForBufferTarget.ts │ │ ├── getMipmapTargetForCubeFace.ts │ │ ├── getTypedArrayConstructorForTextureDataType.ts │ │ ├── isTextureDataFormatSized.ts │ │ ├── isTextureDataFormatCompressed.ts │ │ ├── getTextureDataTypesForTextureFormat.ts │ │ ├── getExtensionForTextureFormat.ts │ │ └── getChannelsForTextureFormat.ts │ └── makeFullscreenCanvas.ts └── index.ts ├── README.md ├── .github └── workflows │ ├── test.yml │ └── publish.yml ├── LICENSE ├── tsconfig.json ├── package.json └── eslint.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | docs 3 | node_modules 4 | *.tsbuildinfo 5 | -------------------------------------------------------------------------------- /test/assets/atlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/atlas.png -------------------------------------------------------------------------------- /test/assets/emap/nx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/emap/nx.png -------------------------------------------------------------------------------- /test/assets/emap/ny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/emap/ny.png -------------------------------------------------------------------------------- /test/assets/emap/nz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/emap/nz.png -------------------------------------------------------------------------------- /test/assets/emap/px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/emap/px.png -------------------------------------------------------------------------------- /test/assets/emap/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/emap/py.png -------------------------------------------------------------------------------- /test/assets/emap/pz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/emap/pz.png -------------------------------------------------------------------------------- /test/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/favicon.ico -------------------------------------------------------------------------------- /test/assets/peppers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lakuna/ugl/HEAD/test/assets/peppers.png -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "experimentalTernaries": true, 4 | "trailingComma": "none", 5 | "objectWrap": "collapse", 6 | "useTabs": true 7 | } 8 | -------------------------------------------------------------------------------- /src/types/UniformMap.ts: -------------------------------------------------------------------------------- 1 | import type { UniformValue } from "./UniformValue.js"; 2 | 3 | /** 4 | * An object that maps uniform names to values. 5 | * @public 6 | */ 7 | export type UniformMap = Record; 8 | -------------------------------------------------------------------------------- /src/constants/Orientation.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Rotational orientations. 3 | * @public 4 | */ 5 | enum Orientation { 6 | /** Clockwise. */ 7 | CW = 0x0900, 8 | 9 | /** Counter-clockwise. */ 10 | CCW = 0x0901 11 | } 12 | 13 | export default Orientation; 14 | -------------------------------------------------------------------------------- /src/types/UniformValue.ts: -------------------------------------------------------------------------------- 1 | import type Texture from "../core/textures/Texture.js"; 2 | 3 | /** 4 | * A value that can be passed to a uniform. 5 | * @public 6 | */ 7 | export type UniformValue = 8 | | number 9 | | Iterable 10 | | Texture 11 | | Iterable; 12 | -------------------------------------------------------------------------------- /src/constants/SyncStatus.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Sync object statuses. 3 | * @public 4 | */ 5 | enum SyncStatus { 6 | /** The sync has not completed. */ 7 | UNSIGNALED = 0x9118, 8 | 9 | /** The sync has completed. */ 10 | SIGNALED = 0x9119 11 | } 12 | 13 | export default SyncStatus; 14 | -------------------------------------------------------------------------------- /src/types/VaryingMap.ts: -------------------------------------------------------------------------------- 1 | import type VaryingValue from "./VaryingValue.js"; 2 | import type VertexBuffer from "../core/buffers/VertexBuffer.js"; 3 | 4 | /** 5 | * An object that maps varying names to output buffers. 6 | * @public 7 | */ 8 | export type VaryingMap = Record; 9 | -------------------------------------------------------------------------------- /src/types/AttributeMap.ts: -------------------------------------------------------------------------------- 1 | import type AttributeValue from "./AttributeValue.js"; 2 | import type VertexBuffer from "../core/buffers/VertexBuffer.js"; 3 | 4 | /** 5 | * An object that maps attribute names to values. 6 | * @public 7 | */ 8 | export type AttributeMap = Record; 9 | -------------------------------------------------------------------------------- /src/types/Prism.ts: -------------------------------------------------------------------------------- 1 | import type Rectangle from "./Rectangle.js"; 2 | 3 | /** 4 | * A rectangular prism. 5 | * @public 6 | */ 7 | export default interface Prism extends Rectangle { 8 | /** The Z-coordinate of the prism. */ 9 | 4: number; 10 | 11 | /** The depth of the prism. */ 12 | 5: number; 13 | } 14 | -------------------------------------------------------------------------------- /src/constants/TextureCompareMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Comparison modes for textures. 3 | * @public 4 | */ 5 | enum TextureCompareMode { 6 | /** No compare mode. */ 7 | NONE = 0, 8 | 9 | /** Compare the reference to the texture. */ 10 | COMPARE_REF_TO_TEXTURE = 0x884e 11 | } 12 | 13 | export default TextureCompareMode; 14 | -------------------------------------------------------------------------------- /src/types/BlendEquationSet.ts: -------------------------------------------------------------------------------- 1 | import type BlendEquation from "../constants/BlendEquation.js"; 2 | 3 | /** 4 | * A set of an RGB and an alpha blend equation. 5 | * @public 6 | */ 7 | export default interface BlendEquationSet { 8 | /** The RGB blend equation. */ 9 | 0: BlendEquation; 10 | 11 | /** The alpha blend equation. */ 12 | 1: BlendEquation; 13 | } 14 | -------------------------------------------------------------------------------- /src/constants/Face.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Directions that a polygon can face relative to the camera. 3 | * @public 4 | */ 5 | enum Face { 6 | /** A front-facing polygon. */ 7 | FRONT = 0x0404, 8 | 9 | /** A back-facing polygon. */ 10 | BACK = 0x0405, 11 | 12 | /** A polygon that is facing in any direction. */ 13 | FRONT_AND_BACK = 0x0408 14 | } 15 | 16 | export default Face; 17 | -------------------------------------------------------------------------------- /src/types/Rectangle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A rectangle. 3 | * @public 4 | */ 5 | export default interface Rectangle { 6 | /** The X-coordinate of the rectangle. */ 7 | 0: number; 8 | 9 | /** The Y-coordinate of the rectangle. */ 10 | 1: number; 11 | 12 | /** The width of the rectangle. */ 13 | 2: number; 14 | 15 | /** The height of the rectangle. */ 16 | 3: number; 17 | } 18 | -------------------------------------------------------------------------------- /src/constants/FramebufferAttachment.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Non-color framebuffer attachments. 3 | * @public 4 | */ 5 | enum FramebufferAttachment { 6 | /** The depth attachment. */ 7 | Depth = -1, 8 | 9 | /** The stencil attachment. */ 10 | Stencil = -2, 11 | 12 | /** The depth stencil attachment. */ 13 | DepthStencil = -3 14 | } 15 | 16 | export default FramebufferAttachment; 17 | -------------------------------------------------------------------------------- /src/types/BlendFunctionSet.ts: -------------------------------------------------------------------------------- 1 | import type BlendFunction from "../constants/BlendFunction.js"; 2 | 3 | /** 4 | * A set of a source and a destination blend function. 5 | * @public 6 | */ 7 | export default interface BlendFunctionSet { 8 | /** The source blend function. */ 9 | 0: BlendFunction; 10 | 11 | /** The destination blend function. */ 12 | 1: BlendFunction; 13 | } 14 | -------------------------------------------------------------------------------- /src/types/Pair.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A pair of numbers. 3 | * @public 4 | */ 5 | export default interface Pair { 6 | /** The first number in the pair, typically representing the width of a rectangle or the lower end of a range. */ 7 | 0: number; 8 | 9 | /** The second number in the pair, typically representing the height of a rectangle or the upper end of a range. */ 10 | 1: number; 11 | } 12 | -------------------------------------------------------------------------------- /src/constants/ShaderType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Types of shaders. 3 | * @public 4 | */ 5 | enum ShaderType { 6 | /** A fragment shader, which runs once for each fragment and computes the color of the fragment. */ 7 | FRAGMENT_SHADER = 0x8b30, 8 | 9 | /** A vertex shader, which runs once for each vertex and computes the position of the vertex. */ 10 | VERTEX_SHADER = 0x8b31 11 | } 12 | 13 | export default ShaderType; 14 | -------------------------------------------------------------------------------- /src/constants/WrapMode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Wrapping functions for textures. 3 | * @public 4 | */ 5 | enum WrapMode { 6 | /** The texture repeats after it ends. */ 7 | REPEAT = 0x2901, 8 | 9 | /** The last pixel of the texture repeats after it ends. */ 10 | CLAMP_TO_EDGE = 0x812f, 11 | 12 | /** The texture repeats after it ends, mirroring on each repetition. */ 13 | MIRRORED_REPEAT = 0x8370 14 | } 15 | 16 | export default WrapMode; 17 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MatrixUniform.ts: -------------------------------------------------------------------------------- 1 | import MultipleValuedUniform from "./MultipleValuedUniform.js"; 2 | 3 | /** 4 | * A matrix global variable in a WebGL shader program. 5 | * @internal 6 | */ 7 | export default abstract class MatrixUniform extends MultipleValuedUniform { 8 | /** Whether or not to transpose the value of this uniform when passing it to WebGL. Treated as `false` if not set. */ 9 | public transpose?: boolean; 10 | } 11 | -------------------------------------------------------------------------------- /src/types/ColorMask.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A color mask. 3 | * @public 4 | */ 5 | export default interface ColorMask { 6 | /** Whether or not to write to the red component. */ 7 | 0: boolean; 8 | 9 | /** Whether or not to write to the green component. */ 10 | 1: boolean; 11 | 12 | /** Whether or not to write to the blue component. */ 13 | 2: boolean; 14 | 15 | /** Whether or not to write to the alpha component. */ 16 | 3: boolean; 17 | } 18 | -------------------------------------------------------------------------------- /src/types/Color.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A color. 3 | * @public 4 | */ 5 | export default interface Color { 6 | /** The red component of the color in the range `[0,1]`. */ 7 | 0: number; 8 | 9 | /** The green component of the color in the range `[0,1]`. */ 10 | 1: number; 11 | 12 | /** The blue component of the color in the range `[0,1]`. */ 13 | 2: number; 14 | 15 | /** The alpha component of the color in the range `[0,1]`. */ 16 | 3: number; 17 | } 18 | -------------------------------------------------------------------------------- /src/utility/BadValueError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An error that occurs when attempting to use an invalid value for an operation. 3 | * @public 4 | */ 5 | export default class BadValueError extends Error { 6 | /** 7 | * Creates a bad value error. 8 | * @param message - The message of the error. 9 | * @internal 10 | */ 11 | public constructor(message = "Attempted to use an invalid value.") { 12 | super(message); 13 | this.name = "BadValue"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/utility/ImmutableError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An error resulting from attempting to modify an immutable value. 3 | * @public 4 | */ 5 | export default class ImmutableError extends Error { 6 | /** 7 | * Creates an immutable error. 8 | * @param message - The message of the error. 9 | * @internal 10 | */ 11 | public constructor(message = "Attempted to modify an immutable value.") { 12 | super(message); 13 | this.name = "ImmutableError"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/utility/ProgramLinkError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An error that occurs when attempting to link a shader program. 3 | * @public 4 | */ 5 | export default class ProgramLinkError extends Error { 6 | /** 7 | * Creates a program link error. 8 | * @param message - The message of the error. 9 | * @internal 10 | */ 11 | public constructor(message = "Failed to link the shader program.") { 12 | super(message); 13 | this.name = "ProgramLinkError"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/utility/ShaderCompileError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An error that occurs when attempting to compile a shader. 3 | * @public 4 | */ 5 | export default class ShaderCompileError extends Error { 6 | /** 7 | * Creates a shader compile error. 8 | * @param message - The message of the error. 9 | * @internal 10 | */ 11 | public constructor(message = "Failed to compile the shader.") { 12 | super(message); 13 | this.name = "ShaderCompileError"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/constants/TextureTarget.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Binding points for textures. 3 | * @internal 4 | */ 5 | const enum TextureTarget { 6 | /** A two-dimensional texture. */ 7 | TEXTURE_2D = 0x0de1, 8 | 9 | /** A cube-mapped texture. */ 10 | TEXTURE_CUBE_MAP = 0x8513, 11 | 12 | /** A three-dimensional texture. */ 13 | TEXTURE_3D = 0x806f, 14 | 15 | /** A two-dimensional array texture. */ 16 | TEXTURE_2D_ARRAY = 0x8c1a 17 | } 18 | 19 | export default TextureTarget; 20 | -------------------------------------------------------------------------------- /src/types/Stencil.ts: -------------------------------------------------------------------------------- 1 | import type TestFunction from "../constants/TestFunction.js"; 2 | 3 | /** 4 | * A stencil function, reference value, and mask. 5 | * @public 6 | */ 7 | export default interface Stencil { 8 | /** The test function. */ 9 | 0: TestFunction; 10 | 11 | /** The reference value for the stencil test. */ 12 | 1: number; 13 | 14 | /** A bitwise mask that is combined with the reference value and the stored stencil value when the test is performed. */ 15 | 2: number; 16 | } 17 | -------------------------------------------------------------------------------- /src/core/internal/ApiInterface.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An object with direct access to the WebGL2 API. 3 | * @public 4 | */ 5 | export default abstract class ApiInterface { 6 | /** 7 | * Initializes the API interface. 8 | * @param gl - The API interface object. 9 | * @internal 10 | */ 11 | protected constructor(gl: WebGL2RenderingContext) { 12 | this.gl = gl; 13 | } 14 | 15 | /** 16 | * The API interface. 17 | * @internal 18 | */ 19 | public readonly gl: WebGL2RenderingContext; 20 | } 21 | -------------------------------------------------------------------------------- /src/utility/DuplicateContextError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An error resulting from attempting to create more than one `Context` for a single canvas. 3 | * @public 4 | */ 5 | export default class DuplicateContextError extends Error { 6 | /** 7 | * Creates a duplicate context error. 8 | * @param message - The message of the error. 9 | * @internal 10 | */ 11 | public constructor(message = "Attempted to create a duplicate context.") { 12 | super(message); 13 | this.name = "DuplicateContextError"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/types/DebugInfo.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An object representing a debug session of a WebGL rendering context. 3 | * @public 4 | */ 5 | export default interface DebugInfo { 6 | /** Whether or not debug information should be logged. This will make the rendering context very slow. */ 7 | isActive: boolean; 8 | 9 | /** Whether or not the rendering context should be checked for errors after each method call (and whether or not those errors will be logged). This will dramatically reduce the speed of the debugger. */ 10 | doLogErrors: boolean; 11 | } 12 | -------------------------------------------------------------------------------- /src/types/BlendFunctionFullSet.ts: -------------------------------------------------------------------------------- 1 | import type BlendFunction from "../constants/BlendFunction.js"; 2 | 3 | /** 4 | * A set of source and destination RGB and alpha blend functions. 5 | * @public 6 | */ 7 | export default interface BlendFunctionFullSet { 8 | /** The source RGB blend function. */ 9 | 0: BlendFunction; 10 | 11 | /** The destination RGB blend function. */ 12 | 1: BlendFunction; 13 | 14 | /** The source alpha blend function. */ 15 | 2: BlendFunction; 16 | 17 | /** The destination alpha blend function. */ 18 | 3: BlendFunction; 19 | } 20 | -------------------------------------------------------------------------------- /src/types/VaryingValue.ts: -------------------------------------------------------------------------------- 1 | import type VertexBuffer from "../core/buffers/VertexBuffer.js"; 2 | 3 | /** 4 | * An object that contains information about how to write data to a buffer. 5 | * @public 6 | */ 7 | export default interface VaryingValue { 8 | /** The vertex buffer object to push components to. */ 9 | readonly vbo: VertexBuffer; 10 | 11 | /** The offset in bytes of the first component in the buffer. */ 12 | readonly offset?: number; 13 | 14 | /** The amount of data that can be read from the buffer. */ 15 | readonly size?: number; 16 | } 17 | -------------------------------------------------------------------------------- /src/constants/FramebufferTarget.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Binding points for framebuffers. 3 | * @internal 4 | */ 5 | const enum FramebufferTarget { 6 | /** Used as a destination for drawing, rendering, clearing, and writing operations, and as a source for reading operations. */ 7 | FRAMEBUFFER = 0x8d40, 8 | 9 | /** Used as a destination for drawing, rendering, clearing, and writing operations. */ 10 | DRAW_FRAMEBUFFER = 0x8ca9, 11 | 12 | /** Used as a source for reading operations. */ 13 | READ_FRAMEBUFFER = 0x8ca8 14 | } 15 | 16 | export default FramebufferTarget; 17 | -------------------------------------------------------------------------------- /src/utility/TextureFormatError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An error resulting from attempting to use a data format or type that is not compatible with a texture format. 3 | * @public 4 | */ 5 | export default class TextureFormatError extends Error { 6 | /** 7 | * Creates a texture format error. 8 | * @param message - The message of the error. 9 | * @internal 10 | */ 11 | public constructor( 12 | message = "Attempted to use a data format or type that is not compatible with a texture format." 13 | ) { 14 | super(message); 15 | this.name = "TextureFormatError"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/constants/SyncClientStatus.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Sync object statuses. 3 | * @public 4 | */ 5 | enum SyncClientStatus { 6 | /** The sync object was already signaled when the method was called. */ 7 | ALREADY_SIGNALED = 0x911a, 8 | 9 | /** The timeout time passed without the sync object becoming signaled. */ 10 | TIMEOUT_EXPIRED = 0x911b, 11 | 12 | /** The sync object became signaled before the timeout expired. */ 13 | CONDITION_SATISFIED = 0x911c, 14 | 15 | /** An error occurred during execution. */ 16 | WAIT_FAILED = 0x911d 17 | } 18 | 19 | export default SyncClientStatus; 20 | -------------------------------------------------------------------------------- /src/utility/UnsupportedOperationError.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * An error resulting from attempting to use a feature that is not supported by the current environment. 3 | * @public 4 | */ 5 | export default class UnsupportedOperationError extends Error { 6 | /** 7 | * Creates an unsupported operation error. 8 | * @param message - The message of the error. 9 | * @internal 10 | */ 11 | public constructor( 12 | message = "Attempted to use a feature that is not supported by the current environment." 13 | ) { 14 | super(message); 15 | this.name = "UnsupportedOperationError"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/utility/WebglError.ts: -------------------------------------------------------------------------------- 1 | import type ErrorCode from "../constants/ErrorCode.js"; 2 | import getErrorCodeMessage from "./internal/getErrorCodeMessage.js"; 3 | 4 | /** 5 | * A WebGL error. 6 | * @public 7 | */ 8 | export default class WebglError extends Error { 9 | /** 10 | * Creates a WebGL error. 11 | * @param value - The code or message of the error. 12 | * @internal 13 | */ 14 | public constructor( 15 | value: ErrorCode | string = "A WebGL error has occurred." 16 | ) { 17 | super(typeof value === "string" ? value : getErrorCodeMessage(value)); 18 | this.name = "WebglError"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/constants/BlendEquation.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Blending equations. 3 | * @public 4 | */ 5 | enum BlendEquation { 6 | /** Add the destination to the source. */ 7 | FUNC_ADD = 0x8006, 8 | 9 | /** Subtract the destination from the source. */ 10 | FUNC_SUBTRACT = 0x800a, 11 | 12 | /** Subtract the source from the destination. */ 13 | FUNC_REVERSE_SUBTRACT = 0x800b, 14 | 15 | /** Use the minimum color components of the source and destination. */ 16 | MIN = 0x8007, 17 | 18 | /** Use the maximum color components of the source and destination. */ 19 | MAX = 0x8008 20 | } 21 | 22 | export default BlendEquation; 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Test](https://github.com/Lakuna/ugl/actions/workflows/test.yml/badge.svg)](https://github.com/Lakuna/ugl/actions/workflows/test.yml) 2 | 3 | # μGL 4 | 5 | A lightweight WebGL2 library. Includes a variety of classes which are useful for developing two- and three-dimensional games, animations, and simulations. 6 | 7 | Documentation is automatically generated and uploaded to [the website](https://ugl.lakuna.pw/). 8 | 9 | The source code can be found on [the GitHub repository](https://github.com/Lakuna/ugl). 10 | 11 | A complete introductory guide to WebGL2 with μGL is available on [my website](https://www.lakuna.pw/a/webgl). 12 | -------------------------------------------------------------------------------- /src/constants/CubeFace.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Faces of a cubemapped texture. 3 | * @public 4 | */ 5 | enum CubeFace { 6 | /** The face on the X-axis in the positive direction. */ 7 | PositiveX, 8 | 9 | /** The face on the Y-axis in the positive direction. */ 10 | PositiveY, 11 | 12 | /** The face on the Z-axis in the positive direction. */ 13 | PositiveZ, 14 | 15 | /** The face on the X-axis in the negative direction. */ 16 | NegativeX, 17 | 18 | /** The face on the Y-axis in the negative direction. */ 19 | NegativeY, 20 | 21 | /** The face on the Z-axis in the negative direction. */ 22 | NegativeZ 23 | } 24 | 25 | export default CubeFace; 26 | -------------------------------------------------------------------------------- /src/core/internal/ContextDependent.ts: -------------------------------------------------------------------------------- 1 | import ApiInterface from "./ApiInterface.js"; 2 | import type Context from "../Context.js"; 3 | 4 | /** 5 | * An object with direct access to the WebGL2 API that requires an existing rendering context to instantiate. 6 | * @public 7 | */ 8 | export default abstract class ContextDependent extends ApiInterface { 9 | /** 10 | * Initializes the context-dependent API interface. 11 | * @param context - The rendering context. 12 | * @internal 13 | */ 14 | protected constructor(context: Context) { 15 | super(context.gl); 16 | this.context = context; 17 | } 18 | 19 | /** The rendering context. */ 20 | public readonly context: Context; 21 | } 22 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MultipleValuedUniform.ts: -------------------------------------------------------------------------------- 1 | import Uniform from "./Uniform.js"; 2 | import UnsupportedOperationError from "../../../utility/UnsupportedOperationError.js"; 3 | 4 | /** 5 | * A global variable that can only hold multiple values in a WebGL shader program. 6 | * @internal 7 | */ 8 | export default abstract class MultipleValuedUniform extends Uniform { 9 | /** 10 | * Set the value of this uniform if the value is not iterable. 11 | * @throws {@link UnsupportedOperationError} always. 12 | * @internal 13 | */ 14 | public override setter(): never { 15 | throw new UnsupportedOperationError( 16 | `${this.name} cannot be set to a non-iterable value.` 17 | ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - edited 8 | push: 9 | 10 | jobs: 11 | test: 12 | name: Test 13 | permissions: {} 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Check-Out Repository 17 | uses: actions/checkout@v4 18 | - name: Set Up Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: latest 22 | - name: Install Dependencies 23 | run: npm ci 24 | - name: Lint 25 | run: npm run lint --if-present 26 | - name: Build 27 | run: npm run build --if-present 28 | - name: Build Documentation 29 | run: npm run doc --if-present 30 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/IntegerVector2Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector2Uniform from "./Vector2Uniform.js"; 2 | 3 | /** 4 | * An integer 2D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class IntegerVector2Uniform extends Vector2Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform2iv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/IntegerVector3Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector3Uniform from "./Vector3Uniform.js"; 2 | 3 | /** 4 | * An integer 3D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class IntegerVector3Uniform extends Vector3Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform3iv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/IntegerVector4Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector4Uniform from "./Vector4Uniform.js"; 2 | 3 | /** 4 | * An integer 4D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class IntegerVector4Uniform extends Vector4Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform4iv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatVector2Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector2Uniform from "./Vector2Uniform.js"; 2 | 3 | /** 4 | * A floating-point 2D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatVector2Uniform extends Vector2Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform2fv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatVector3Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector3Uniform from "./Vector3Uniform.js"; 2 | 3 | /** 4 | * A floating-point 3D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatVector3Uniform extends Vector3Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform3fv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatVector4Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector4Uniform from "./Vector4Uniform.js"; 2 | 3 | /** 4 | * A floating-point 4D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatVector4Uniform extends Vector4Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform4fv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/UnsignedIntegerVector2Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector2Uniform from "./Vector2Uniform.js"; 2 | 3 | /** 4 | * An unsigned integer 2D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class UnsignedIntegerVector2Uniform extends Vector2Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform2uiv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/UnsignedIntegerVector3Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector3Uniform from "./Vector3Uniform.js"; 2 | 3 | /** 4 | * An unsigned integer 3D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class UnsignedIntegerVector3Uniform extends Vector3Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform3uiv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/UnsignedIntegerVector4Uniform.ts: -------------------------------------------------------------------------------- 1 | import Vector4Uniform from "./Vector4Uniform.js"; 2 | 3 | /** 4 | * An unsigned integer 4D vector global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class UnsignedIntegerVector4Uniform extends Vector4Uniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform4uiv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/constants/ErrorCode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * WebGL error codes. 3 | * @public 4 | */ 5 | enum ErrorCode { 6 | /** No error has been recorded. */ 7 | NO_ERROR = 0, 8 | 9 | /** An unacceptable value has been specified for an enumerated argument. */ 10 | INVALID_ENUM = 0x0500, 11 | 12 | /** A numeric argument is out of range. */ 13 | INVALID_VALUE = 0x0501, 14 | 15 | /** The specified command is not allowed for the current state. */ 16 | INVALID_OPERATION = 0x0502, 17 | 18 | /** The currently-bound framebuffer is not framebuffer complete. */ 19 | INVALID_FRAMEBUFFER_OPERATION = 0x0506, 20 | 21 | /** Not enough memory is left to execute the command. */ 22 | OUT_OF_MEMORY = 0x0505, 23 | 24 | /** The context is lost. */ 25 | CONTEXT_LOST_WEBGL = 0x9242 26 | } 27 | 28 | export default ErrorCode; 29 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix2x2Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform4 from "./MatrixUniform4.js"; 2 | 3 | /** 4 | * A floating-point 2x2 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix2x2Uniform extends MatrixUniform4 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix2fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix2x3Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform6 from "./MatrixUniform6.js"; 2 | 3 | /** 4 | * A floating-point 2x3 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix2x3Uniform extends MatrixUniform6 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix2x3fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix2x4Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform8 from "./MatrixUniform8.js"; 2 | 3 | /** 4 | * A floating-point 2x4 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix2x4Uniform extends MatrixUniform8 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix2x4fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix3x2Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform6 from "./MatrixUniform6.js"; 2 | 3 | /** 4 | * A floating-point 3x2 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix3x2Uniform extends MatrixUniform6 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix3x2fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix3x3Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform9 from "./MatrixUniform9.js"; 2 | 3 | /** 4 | * A floating-point 3x3 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix3x3Uniform extends MatrixUniform9 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix3fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix4x2Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform8 from "./MatrixUniform8.js"; 2 | 3 | /** 4 | * A floating-point 4x2 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix4x2Uniform extends MatrixUniform8 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix4x2fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix4x4Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform16 from "./MatrixUniform16.js"; 2 | 3 | /** 4 | * A floating-point 4x4 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix4x4Uniform extends MatrixUniform16 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix4fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix3x4Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform12 from "./MatrixUniform12.js"; 2 | 3 | /** 4 | * A floating-point 3x4 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix3x4Uniform extends MatrixUniform12 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix3x4fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatMatrix4x3Uniform.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform12 from "./MatrixUniform12.js"; 2 | 3 | /** 4 | * A floating-point 4x3 matrix global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatMatrix4x3Uniform extends MatrixUniform12 { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniformMatrix | uniformMatrix[234]x[234]fv} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniformMatrix4x3fv( 16 | this.location, 17 | this.transpose ?? false, 18 | value, 19 | this.sourceOffset, 20 | this.sourceLength 21 | ); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/constants/TextureFilter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Minification and magnification filters for textures. 3 | * @public 4 | */ 5 | enum TextureFilter { 6 | /** Choose one pixel from the largest mip. */ 7 | NEAREST = 0x2600, 8 | 9 | /** Choose four pixels from the largest mip and blends them. */ 10 | LINEAR = 0x2601, 11 | 12 | /** Choose the best mip, then picks one pixel from that mip. */ 13 | NEAREST_MIPMAP_NEAREST = 0x2700, 14 | 15 | /** Choose the best mip, then blends four pixels from that mip. */ 16 | LINEAR_MIPMAP_NEAREST = 0x2701, 17 | 18 | /** Choose the best two mips, then chooses one pixel from each and blends them. */ 19 | NEAREST_MIPMAP_LINEAR = 0x2702, 20 | 21 | /** Choose the best two mips, then chooses four pixels from each and blends them. */ 22 | LINEAR_MIPMAP_LINEAR = 0x2703 23 | } 24 | 25 | export default TextureFilter; 26 | -------------------------------------------------------------------------------- /src/constants/TestFunction.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Testing functions. 3 | * @public 4 | */ 5 | enum TestFunction { 6 | /** Never passes. */ 7 | NEVER = 0x0200, 8 | 9 | /** Passes if the incoming value is less than the buffer value. */ 10 | LESS = 0x0201, 11 | 12 | /** Passes if the incoming value is equal to the buffer value. */ 13 | EQUAL = 0x0202, 14 | 15 | /** Passes if the incoming value is less than or equal to the buffer value. */ 16 | LEQUAL = 0x0203, 17 | 18 | /** Passes if the incoming value is greater than the buffer value. */ 19 | GREATER = 0x0204, 20 | 21 | /** Passes if the incoming value is not equal to the buffer value. */ 22 | NOTEQUAL = 0x0205, 23 | 24 | /** Passes if the incoming value is greater than or equal to the buffer value. */ 25 | GEQUAL = 0x0206, 26 | 27 | /** Always passes. */ 28 | ALWAYS = 0x0207 29 | } 30 | 31 | export default TestFunction; 32 | -------------------------------------------------------------------------------- /src/constants/Primitive.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Types of primitives that can be rasterized. 3 | * @public 4 | */ 5 | enum Primitive { 6 | /** Draws a dot at each vertex. */ 7 | POINTS = 0x0000, 8 | 9 | /** Draws a line between each vertex. */ 10 | LINE_STRIP = 0x0003, 11 | 12 | /** Draws a line between each vertex, then draws a line between the first and last vertices. */ 13 | LINE_LOOP = 0x0002, 14 | 15 | /** Draws lines between each pair of vertices. */ 16 | LINES = 0x0001, 17 | 18 | /** Draws triangles from each vertex and the previous two, starting at the third vertex. */ 19 | TRIANGLE_STRIP = 0x0005, 20 | 21 | /** Draws triangles from each vertex, the previous vertex, and the first vertex, starting at the third vertex. */ 22 | TRIANGLE_FAN = 0x0006, 23 | 24 | /** Draws triangles between every three vertices. */ 25 | TRIANGLES = 0x0004 26 | } 27 | 28 | export default Primitive; 29 | -------------------------------------------------------------------------------- /src/core/variables/attributes/IntegerAttribute.ts: -------------------------------------------------------------------------------- 1 | import Attribute from "./Attribute.js"; 2 | import type AttributeValue from "../../../types/AttributeValue.js"; 3 | 4 | /** 5 | * An integer, unsigned integer, or boolean input variable in a vertex shader. 6 | * @internal 7 | */ 8 | export default class IntegerAttribute extends Attribute { 9 | /** 10 | * Set the value of this attribute. 11 | * @param value - The value to pass to the attribute. 12 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/vertexAttribIPointer | vertexAttribIPointer} 13 | * @internal 14 | */ 15 | protected override setterInternal(value: AttributeValue): void { 16 | this.gl.vertexAttribIPointer( 17 | this.location, 18 | value.size ?? 3, 19 | value.vbo.type, 20 | value.stride ?? 0, 21 | value.offset ?? 0 22 | ); 23 | 24 | this.valueCache = value; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/core/variables/attributes/FloatAttribute.ts: -------------------------------------------------------------------------------- 1 | import Attribute from "./Attribute.js"; 2 | import type AttributeValue from "../../../types/AttributeValue.js"; 3 | 4 | /** 5 | * A floating-point input variable in a WebGL vertex shader. 6 | * @internal 7 | */ 8 | export default class FloatAttribute extends Attribute { 9 | /** 10 | * Set the value of this attribute. 11 | * @param value - The value to pass to the attribute. 12 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer | vertexAttribPointer} 13 | * @internal 14 | */ 15 | protected override setterInternal(value: AttributeValue): void { 16 | this.gl.vertexAttribPointer( 17 | this.location, 18 | value.size ?? 3, 19 | value.vbo.type, 20 | value.normalized ?? false, 21 | value.stride ?? 0, 22 | value.offset ?? 0 23 | ); 24 | 25 | this.valueCache = value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/utility/internal/getDataTypeForTypedArray.ts: -------------------------------------------------------------------------------- 1 | import DataType from "../../constants/DataType.js"; 2 | 3 | /** 4 | * Get a default buffer data type for the given typed array. 5 | * @param array - The typed array. 6 | * @returns A default buffer data type for the given typed array. 7 | * @internal 8 | */ 9 | export default function getDataTypeForTypedArray( 10 | array: ArrayBufferView 11 | ): DataType { 12 | return ( 13 | array instanceof Int8Array ? DataType.BYTE 14 | : array instanceof Uint8Array || array instanceof Uint8ClampedArray ? 15 | DataType.UNSIGNED_BYTE 16 | : array instanceof Int16Array ? DataType.SHORT 17 | : array instanceof Uint16Array ? DataType.UNSIGNED_SHORT 18 | : array instanceof Int32Array ? DataType.INT 19 | : array instanceof Uint32Array ? DataType.UNSIGNED_INT 20 | : array instanceof Float16Array ? DataType.HALF_FLOAT 21 | : DataType.FLOAT 22 | ); // `Float32Array`. 23 | } 24 | -------------------------------------------------------------------------------- /src/utility/internal/getExtensionForRenderbufferFormat.ts: -------------------------------------------------------------------------------- 1 | import Extension from "../../constants/Extension.js"; 2 | import RenderbufferFormat from "../../constants/RenderbufferFormat.js"; 3 | 4 | /** 5 | * Get the extension that is associated with the given renderbuffer format. 6 | * @param format - The renderbuffer format. 7 | * @returns The extension that is associated with the renderbuffer format. 8 | * @internal 9 | */ 10 | export default function getExtensionForRenderbufferFormat( 11 | format: RenderbufferFormat 12 | ): Extension | null { 13 | switch (format) { 14 | case RenderbufferFormat.R16F: 15 | case RenderbufferFormat.RG16F: 16 | case RenderbufferFormat.RGBA16F: 17 | case RenderbufferFormat.R32F: 18 | case RenderbufferFormat.RG32F: 19 | case RenderbufferFormat.RGBA32F: 20 | case RenderbufferFormat.R11F_G11F_B10F: 21 | return Extension.ExtColorBufferFloat; 22 | default: 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/utility/internal/getParameterForFramebufferTarget.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DRAW_FRAMEBUFFER_BINDING, 3 | FRAMEBUFFER_BINDING, 4 | READ_FRAMEBUFFER_BINDING 5 | } from "../../constants/constants.js"; 6 | import FramebufferTarget from "../../constants/FramebufferTarget.js"; 7 | 8 | /** 9 | * Get the constant value representing the context property of the given buffer binding point. 10 | * @param target - The buffer binding point. 11 | * @returns The constant value. 12 | * @internal 13 | */ 14 | export default function getParameterForFramebufferTarget( 15 | target: FramebufferTarget 16 | ): number { 17 | switch (target) { 18 | case FramebufferTarget.DRAW_FRAMEBUFFER: 19 | return DRAW_FRAMEBUFFER_BINDING; 20 | case FramebufferTarget.FRAMEBUFFER: 21 | return FRAMEBUFFER_BINDING; 22 | case FramebufferTarget.READ_FRAMEBUFFER: 23 | default: // Not possible as long as TypeScript is obeyed. 24 | return READ_FRAMEBUFFER_BINDING; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/utility/internal/getExtensionsForFramebufferAttachmentFormat.ts: -------------------------------------------------------------------------------- 1 | import Extension from "../../constants/Extension.js"; 2 | import TextureFormat from "../../constants/TextureFormat.js"; 3 | 4 | /** 5 | * Get the extension that is associated with the given framebuffer attachment format. 6 | * @param format - The framebuffer attachment format. 7 | * @returns The extension that is associated with the framebuffer attachment format. 8 | * @internal 9 | */ 10 | export default function getExtensionsForFramebufferAttachmentFormat( 11 | format: TextureFormat 12 | ): Extension[] { 13 | switch (format) { 14 | case TextureFormat.R16F: 15 | case TextureFormat.RG16F: 16 | case TextureFormat.RGBA16F: 17 | case TextureFormat.R32F: 18 | case TextureFormat.RG32F: 19 | case TextureFormat.RGBA32F: 20 | case TextureFormat.R11F_G11F_B10F: 21 | return [Extension.ExtColorBufferFloat, Extension.FloatBlend]; 22 | default: 23 | return []; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/constants/BufferTarget.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Binding points for buffers. 3 | * @internal 4 | */ 5 | const enum BufferTarget { 6 | /** A buffer containing vertex attributes. */ 7 | ARRAY_BUFFER = 0x8892, 8 | 9 | /** A buffer containing element indices. Not compatible with the rest of the buffer targets. */ 10 | ELEMENT_ARRAY_BUFFER = 0x8893, 11 | 12 | /** A buffer for copying from one buffer to another. */ 13 | COPY_READ_BUFFER = 0x8f36, 14 | 15 | /** A buffer for copying from one buffer to another. */ 16 | COPY_WRITE_BUFFER = 0x8f37, 17 | 18 | /** A buffer for transform feedback operations. */ 19 | TRANSFORM_FEEDBACK_BUFFER = 0x8c8e, 20 | 21 | /** A buffer used for storing uniform blocks. */ 22 | UNIFORM_BUFFER = 0x8a11, 23 | 24 | /** A buffer used for pixel transfer operations. */ 25 | PIXEL_PACK_BUFFER = 0x88eb, 26 | 27 | /** A buffer used for pixel transfer operations. */ 28 | PIXEL_UNPACK_BUFFER = 0x88ec 29 | } 30 | 31 | export default BufferTarget; 32 | -------------------------------------------------------------------------------- /src/utility/internal/getParameterForTextureTarget.ts: -------------------------------------------------------------------------------- 1 | import { 2 | TEXTURE_BINDING_2D, 3 | TEXTURE_BINDING_2D_ARRAY, 4 | TEXTURE_BINDING_3D, 5 | TEXTURE_BINDING_CUBE_MAP 6 | } from "../../constants/constants.js"; 7 | import TextureTarget from "../../constants/TextureTarget.js"; 8 | 9 | /** 10 | * Get the constant value representing the context property of the given texture binding point. 11 | * @param target - The texture binding point. 12 | * @returns The constant value. 13 | * @internal 14 | */ 15 | export default function getParameterForTextureTarget( 16 | target: TextureTarget 17 | ): number { 18 | switch (target) { 19 | case TextureTarget.TEXTURE_2D: 20 | return TEXTURE_BINDING_2D; 21 | case TextureTarget.TEXTURE_2D_ARRAY: 22 | return TEXTURE_BINDING_2D_ARRAY; 23 | case TextureTarget.TEXTURE_3D: 24 | return TEXTURE_BINDING_3D; 25 | case TextureTarget.TEXTURE_CUBE_MAP: 26 | default: // Impossible as long as this function is only called internally. 27 | return TEXTURE_BINDING_CUBE_MAP; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/constants/MipmapTarget.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Binding points for mipmaps. 3 | * @internal 4 | */ 5 | const enum MipmapTarget { 6 | /** A two-dimensional texture. */ 7 | TEXTURE_2D = 0x0de1, 8 | 9 | /** A three-dimensional texture. */ 10 | TEXTURE_3D = 0x806f, 11 | 12 | /** A two-dimensional array texture. */ 13 | TEXTURE_2D_ARRAY = 0x8c1a, 14 | 15 | /** The positive X-axis face for a cube-mapped texture. */ 16 | TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515, 17 | 18 | /** The negative X-axis face for a cube-mapped texture. */ 19 | TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516, 20 | 21 | /** The positive Y-axis face for a cube-mapped texture. */ 22 | TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517, 23 | 24 | /** The negative Y-axis face for a cube-mapped texture. */ 25 | TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518, 26 | 27 | /** The positive Z-axis face for a cube-mapped texture. */ 28 | TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519, 29 | 30 | /** The negative Z-axis face for a cube-mapped texture. */ 31 | TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851a 32 | } 33 | 34 | export default MipmapTarget; 35 | -------------------------------------------------------------------------------- /src/utility/internal/getErrorCodeMessage.ts: -------------------------------------------------------------------------------- 1 | import ErrorCode from "../../constants/ErrorCode.js"; 2 | 3 | /** 4 | * Get the description of an error code. 5 | * @param code - The error code. 6 | * @returns The message. 7 | * @internal 8 | */ 9 | export default function getErrorCodeMessage(code: ErrorCode): string { 10 | switch (code) { 11 | case ErrorCode.CONTEXT_LOST_WEBGL: 12 | return "The context is lost."; 13 | case ErrorCode.INVALID_ENUM: 14 | return "An unacceptable value has been specified for an enumerated argument."; 15 | case ErrorCode.INVALID_FRAMEBUFFER_OPERATION: 16 | return "The currently-bound framebuffer is not framebuffer complete."; 17 | case ErrorCode.INVALID_OPERATION: 18 | return "The specified command is not allowed for the current state."; 19 | case ErrorCode.INVALID_VALUE: 20 | return "A numeric argument is out of range."; 21 | case ErrorCode.NO_ERROR: 22 | return "No error has been recorded."; 23 | case ErrorCode.OUT_OF_MEMORY: 24 | return "Not enough memory is left to execute the command."; 25 | default: 26 | return "Unknown error code."; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/types/AttributeValue.ts: -------------------------------------------------------------------------------- 1 | import type VertexBuffer from "../core/buffers/VertexBuffer.js"; 2 | 3 | /** 4 | * An object that contains information about how to read the data in a buffer. 5 | * @public 6 | */ 7 | export default interface AttributeValue { 8 | /** The vertex buffer object to pull components from. */ 9 | readonly vbo: VertexBuffer; 10 | 11 | /** The number of components to read per vertex attribute. Three components are read per vertex attribute if this is not defined. */ 12 | readonly size?: 1 | 2 | 3 | 4; 13 | 14 | /** Whether or not to normalize the data after getting it from the buffer. The data is not normalized if this is `false` or not defined. */ 15 | readonly normalized?: boolean; 16 | 17 | /** The offset in bytes between the beginnings of consecutive vertex attributes. Must not exceed `0xFF`. The data is treated as being tightly-packed if this is zero or not defined. */ 18 | readonly stride?: number; 19 | 20 | /** The offset in bytes of the first component in the buffer. The data is treated as starting at the beginning of the buffer if this is zero or not defined. */ 21 | readonly offset?: number; 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Travis Martin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/constants/DataType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Types of data that can be stored as components in a buffer. 3 | * @public 4 | */ 5 | enum DataType { 6 | /** An 8-bit signed integer with values in the range `[-0x80,0x80)`. */ 7 | BYTE = 0x1400, 8 | 9 | /** A 16-bit signed integer with values in the range `[-0x8000,0x8000)`. */ 10 | SHORT = 0x1402, 11 | 12 | /** An 8-bit unsigned integer with values in the range `[0x0,0x100)`. */ 13 | UNSIGNED_BYTE = 0x1401, 14 | 15 | /** A 16-bit unsigned integer with values in the range `[0x0,0x10000)`. */ 16 | UNSIGNED_SHORT = 0x1403, 17 | 18 | /** A 32-bit signed floating-point number. */ 19 | FLOAT = 0x1406, 20 | 21 | /** A 16-bit signed floating-point number. */ 22 | HALF_FLOAT = 0x140b, 23 | 24 | /** A 32-bit signed integer. */ 25 | INT = 0x1404, 26 | 27 | /** A 32-bit unsigned integer. */ 28 | UNSIGNED_INT = 0x1405, 29 | 30 | /** A 32-bit signed integer with values in the range `[-0x200,0x200)`. */ 31 | INT_2_10_10_10_REV = 0x8d9f, 32 | 33 | /** A 32-bit unsigned integer with values in the range `[0x0,0x400)`. */ 34 | UNSIGNED_INT_2_10_10_10_REV = 0x8368 35 | } 36 | 37 | export default DataType; 38 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/FloatUniform.ts: -------------------------------------------------------------------------------- 1 | import ScalarUniform from "./ScalarUniform.js"; 2 | 3 | /** 4 | * A floating-point global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class FloatUniform extends ScalarUniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform1fv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | 23 | /** 24 | * Set the value of this uniform if the value is not iterable. 25 | * @param value - The value to pass to the uniform. 26 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 27 | * @internal 28 | */ 29 | public override setterInternal(value: number): void { 30 | this.gl.uniform1f(this.location, value); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/IntegerUniform.ts: -------------------------------------------------------------------------------- 1 | import ScalarUniform from "./ScalarUniform.js"; 2 | 3 | /** 4 | * An integer global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class IntegerUniform extends ScalarUniform { 8 | /** 9 | * Set the value of this uniform if the value is not iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform1iv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | 23 | /** 24 | * Set the value of this uniform if the value is not iterable. 25 | * @param value - The value to pass to the uniform. 26 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 27 | * @internal 28 | */ 29 | public override setterInternal(value: number): void { 30 | this.gl.uniform1i(this.location, value); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/UnsignedIntegerUniform.ts: -------------------------------------------------------------------------------- 1 | import ScalarUniform from "./ScalarUniform.js"; 2 | 3 | /** 4 | * An unsigned integer global variable in a shader program. 5 | * @internal 6 | */ 7 | export default class UnsignedIntegerUniform extends ScalarUniform { 8 | /** 9 | * Set the value of this uniform if the value is iterable. 10 | * @param value - The value to pass to the uniform. 11 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 12 | * @internal 13 | */ 14 | public override iterableSetterInternal(value: Iterable): void { 15 | this.gl.uniform1uiv( 16 | this.location, 17 | value, 18 | this.sourceOffset, 19 | this.sourceLength 20 | ); 21 | } 22 | 23 | /** 24 | * Set the value of this uniform if the value is not iterable. 25 | * @param value - The value to pass to the uniform. 26 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 27 | * @internal 28 | */ 29 | public override setterInternal(value: number): void { 30 | this.gl.uniform1ui(this.location, value); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/constants/FramebufferStatus.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Framebuffer statuses. 3 | * @public 4 | */ 5 | enum FramebufferStatus { 6 | /** The framebuffer is ready to display. */ 7 | FRAMEBUFFER_COMPLETE = 0x8cd5, 8 | 9 | /** The attachment types are mismatched or not all of the framebuffer attachment points are framebuffer attachment complete. */ 10 | FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8cd6, 11 | 12 | /** There is no attachment. */ 13 | FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8cd7, 14 | 15 | /** The dimensions of the attachments do not match. */ 16 | FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8cd9, 17 | 18 | /** The format of the attachment is not supported or the depth and stencil attachments are not the same renderbuffer. */ 19 | FRAMEBUFFER_UNSUPPORTED = 0x8cdd, 20 | 21 | /** The values of the renderbuffer samples are different among attached renderbuffers, or are non-zero if the attached images are a mix of renderbuffers and textures. */ 22 | FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8d56, 23 | 24 | /** The base view index is not the same for all framebuffer attachment points where the object type is not none. */ 25 | FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR = 0x9633 26 | } 27 | 28 | export default FramebufferStatus; 29 | -------------------------------------------------------------------------------- /src/utility/makeFullscreenCanvas.ts: -------------------------------------------------------------------------------- 1 | import UnsupportedOperationError from "./UnsupportedOperationError.js"; 2 | 3 | const recursiveFullscreen = (element: HTMLElement) => { 4 | element.style.width = "100%"; 5 | element.style.height = "100%"; 6 | element.style.margin = "0px"; 7 | element.style.padding = "0px"; 8 | element.style.display = "block"; 9 | 10 | if (element.parentElement) { 11 | recursiveFullscreen(element.parentElement); 12 | } 13 | }; 14 | 15 | /** 16 | * Create a canvas that fills the entire browser window, destroying all other content in the document body in the process. 17 | * @returns A canvas that fills the entire browser window. 18 | * @throws {@link UnsupportedOperationError} if called in a headless environment. 19 | * @public 20 | */ 21 | export default function makeFullscreenCanvas(): HTMLCanvasElement { 22 | if (!(document as Document | undefined)) { 23 | throw new UnsupportedOperationError( 24 | "Cannot make a fullscreen canvas in a headless environment." 25 | ); 26 | } 27 | 28 | const canvas = document.createElement("canvas"); 29 | canvas.style.touchAction = "none"; 30 | 31 | document.body = document.createElement("body"); 32 | document.body.appendChild(canvas); 33 | 34 | recursiveFullscreen(canvas); 35 | 36 | return canvas; 37 | } 38 | -------------------------------------------------------------------------------- /src/utility/internal/getSizeOfDataType.ts: -------------------------------------------------------------------------------- 1 | import DataType from "../../constants/DataType.js"; 2 | import TextureDataType from "../../constants/TextureDataType.js"; 3 | 4 | /** 5 | * Get the size of a data type in bytes. 6 | * @param type - The data type. 7 | * @returns The size of the data type in bytes. 8 | * @internal 9 | */ 10 | export default function getSizeOfDataType( 11 | type: DataType | TextureDataType 12 | ): number { 13 | switch (type) { 14 | case DataType.HALF_FLOAT: 15 | case DataType.SHORT: 16 | case DataType.UNSIGNED_SHORT: 17 | case TextureDataType.HALF_FLOAT_OES: 18 | case TextureDataType.UNSIGNED_SHORT_4_4_4_4: 19 | case TextureDataType.UNSIGNED_SHORT_5_5_5_1: 20 | case TextureDataType.UNSIGNED_SHORT_5_6_5: 21 | return 2; 22 | case DataType.FLOAT: 23 | case DataType.INT: 24 | case DataType.INT_2_10_10_10_REV: 25 | case DataType.UNSIGNED_INT: 26 | case DataType.UNSIGNED_INT_2_10_10_10_REV: 27 | case TextureDataType.FLOAT_32_UNSIGNED_INT_24_8_REV: 28 | case TextureDataType.UNSIGNED_INT_10F_11F_11F_REV: 29 | case TextureDataType.UNSIGNED_INT_24_8: 30 | case TextureDataType.UNSIGNED_INT_5_9_9_9_REV: 31 | return 4; 32 | case DataType.BYTE: 33 | case DataType.UNSIGNED_BYTE: 34 | default: // Not possible if TypeScript is obeyed. 35 | return 1; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["dist", "docs", "node_modules"], 3 | "compilerOptions": { 4 | // Type Checking 5 | "allowUnreachableCode": false, 6 | "allowUnusedLabels": false, 7 | "exactOptionalPropertyTypes": true, 8 | "noFallthroughCasesInSwitch": true, 9 | "noImplicitAny": true, 10 | "noImplicitOverride": true, 11 | "noImplicitReturns": true, 12 | "noPropertyAccessFromIndexSignature": true, 13 | "noUncheckedIndexedAccess": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "strict": true, 17 | 18 | // Modules 19 | "module": "nodenext", 20 | "rootDir": "src", 21 | 22 | // Emit 23 | "declarationMap": true, 24 | "outDir": "dist", 25 | "sourceMap": true, 26 | "stripInternal": true, // Remove if switching to [API Extractor](https://api-extractor.com/). 27 | 28 | // JavaScript Support 29 | // N/A 30 | 31 | // Editor Support 32 | // N/A 33 | 34 | // Interop Constraints 35 | "isolatedDeclarations": true, 36 | "verbatimModuleSyntax": true, 37 | 38 | // Backwards Compatibility 39 | // N/A 40 | 41 | // Language and Environment 42 | "target": "esnext", 43 | 44 | // Projects 45 | "composite": true, 46 | 47 | // Output Formatting 48 | // N/A 49 | 50 | // Completeness 51 | "skipLibCheck": true 52 | 53 | // Command Line 54 | // N/A 55 | 56 | // Watch Options 57 | // N/A 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/core/variables/Variable.ts: -------------------------------------------------------------------------------- 1 | import ContextDependent from "../internal/ContextDependent.js"; 2 | import type Program from "../Program.js"; 3 | import type VariableType from "../../constants/VariableType.js"; 4 | 5 | /** 6 | * A variable in a WebGL shader program. 7 | * @public 8 | */ 9 | export default abstract class Variable extends ContextDependent { 10 | /** 11 | * Create a variable. 12 | * @param program - The shader program that this variable belongs to. 13 | * @internal 14 | */ 15 | protected constructor(program: Program, activeInfo: WebGLActiveInfo) { 16 | super(program.context); 17 | this.program = program; 18 | this.activeInfo = activeInfo; 19 | } 20 | 21 | /** 22 | * The shader program that this variable belongs to. 23 | * @internal 24 | */ 25 | protected readonly program: Program; 26 | 27 | /** 28 | * The value that is stored in this variable. 29 | * @internal 30 | */ 31 | public abstract value: unknown; 32 | 33 | /** 34 | * The active information of this variable. 35 | * @internal 36 | */ 37 | protected readonly activeInfo: WebGLActiveInfo; 38 | 39 | /** The name of this variable. */ 40 | public get name(): string { 41 | return this.activeInfo.name; 42 | } 43 | 44 | /** The type of this variable. */ 45 | public get type(): VariableType { 46 | return this.activeInfo.type; 47 | } 48 | 49 | /** The size of this variable in memory in bytes. */ 50 | public get size(): number { 51 | return this.activeInfo.size; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/constants/TextureDataType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Data types for texel data. 3 | * @public 4 | */ 5 | enum TextureDataType { 6 | /** Unsigned 8-bit integer data. */ 7 | UNSIGNED_BYTE = 0x1401, 8 | 9 | /** Unsigned 16-bit integer data. */ 10 | UNSIGNED_SHORT_5_6_5 = 0x8363, 11 | 12 | /** Unsigned 16-bit integer data. */ 13 | UNSIGNED_SHORT_4_4_4_4 = 0x8033, 14 | 15 | /** Unsigned 16-bit integer data. */ 16 | UNSIGNED_SHORT_5_5_5_1 = 0x8034, 17 | 18 | /** Unsigned 16-bit integer data. */ 19 | UNSIGNED_SHORT = 0x1403, 20 | 21 | /** Unsigned 32-bit integer data. */ 22 | UNSIGNED_INT = 0x1405, 23 | 24 | /** 32-bit floating-point data. */ 25 | FLOAT = 0x1406, 26 | 27 | /** Unsigned 16-bit integer data. */ 28 | HALF_FLOAT_OES = 0x8d61, 29 | 30 | /** Signed 8-bit integer data. */ 31 | BYTE = 0x1400, 32 | 33 | /** Signed 16-bit integer data. */ 34 | SHORT = 0x1402, 35 | 36 | /** Signed 32-bit integer data. */ 37 | INT = 0x1404, 38 | 39 | /** Unsigned 16-bit integer data. */ 40 | HALF_FLOAT = 0x140b, 41 | 42 | /** Unsigned 32-bit integer data. */ 43 | UNSIGNED_INT_2_10_10_10_REV = 0x8368, 44 | 45 | /** Unsigned 32-bit integer data. */ 46 | UNSIGNED_INT_10F_11F_11F_REV = 0x8c3b, 47 | 48 | /** Unsigned 32-bit integer data. */ 49 | UNSIGNED_INT_5_9_9_9_REV = 0x8c3e, 50 | 51 | /** Unsigned 32-bit integer data. */ 52 | UNSIGNED_INT_24_8 = 0x84fa, 53 | 54 | /** Null data. Unusable in WebGL. */ 55 | FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8dad 56 | } 57 | 58 | export default TextureDataType; 59 | -------------------------------------------------------------------------------- /src/utility/internal/getParameterForBufferTarget.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ARRAY_BUFFER_BINDING, 3 | COPY_READ_BUFFER_BINDING, 4 | COPY_WRITE_BUFFER_BINDING, 5 | ELEMENT_ARRAY_BUFFER_BINDING, 6 | PIXEL_PACK_BUFFER_BINDING, 7 | PIXEL_UNPACK_BUFFER_BINDING, 8 | TRANSFORM_FEEDBACK_BUFFER_BINDING, 9 | UNIFORM_BUFFER_BINDING 10 | } from "../../constants/constants.js"; 11 | import BufferTarget from "../../constants/BufferTarget.js"; 12 | 13 | /** 14 | * Get the constant value representing the context property of the given buffer binding point. 15 | * @param target - The buffer binding point. 16 | * @returns The constant value. 17 | * @internal 18 | */ 19 | export default function getParameterForBufferTarget( 20 | target: BufferTarget 21 | ): number { 22 | switch (target) { 23 | case BufferTarget.ARRAY_BUFFER: 24 | return ARRAY_BUFFER_BINDING; 25 | case BufferTarget.COPY_READ_BUFFER: 26 | return COPY_READ_BUFFER_BINDING; 27 | case BufferTarget.COPY_WRITE_BUFFER: 28 | return COPY_WRITE_BUFFER_BINDING; 29 | case BufferTarget.ELEMENT_ARRAY_BUFFER: 30 | return ELEMENT_ARRAY_BUFFER_BINDING; 31 | case BufferTarget.PIXEL_PACK_BUFFER: 32 | return PIXEL_PACK_BUFFER_BINDING; 33 | case BufferTarget.PIXEL_UNPACK_BUFFER: 34 | return PIXEL_UNPACK_BUFFER_BINDING; 35 | case BufferTarget.TRANSFORM_FEEDBACK_BUFFER: 36 | return TRANSFORM_FEEDBACK_BUFFER_BINDING; 37 | case BufferTarget.UNIFORM_BUFFER: 38 | default: // Not possible as long as TypeScript is obeyed. 39 | return UNIFORM_BUFFER_BINDING; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/utility/internal/getMipmapTargetForCubeFace.ts: -------------------------------------------------------------------------------- 1 | import CubeFace from "../../constants/CubeFace.js"; 2 | import MipmapTarget from "../../constants/MipmapTarget.js"; 3 | import TextureTarget from "../../constants/TextureTarget.js"; 4 | 5 | /** 6 | * Get a mipmap target for the given cubemap face. 7 | * @param face - The cubemap face. 8 | * @param target - The texture target. 9 | * @returns The mipmap target. 10 | * @internal 11 | */ 12 | export default function getMipmapTargetForCubeFace( 13 | face?: CubeFace, 14 | target: TextureTarget = TextureTarget.TEXTURE_CUBE_MAP 15 | ): MipmapTarget { 16 | switch (target) { 17 | case TextureTarget.TEXTURE_2D_ARRAY: 18 | return MipmapTarget.TEXTURE_2D_ARRAY; 19 | case TextureTarget.TEXTURE_3D: 20 | return MipmapTarget.TEXTURE_3D; 21 | case TextureTarget.TEXTURE_CUBE_MAP: 22 | switch (face) { 23 | case CubeFace.NegativeX: 24 | return MipmapTarget.TEXTURE_CUBE_MAP_NEGATIVE_X; 25 | case CubeFace.NegativeY: 26 | return MipmapTarget.TEXTURE_CUBE_MAP_NEGATIVE_Y; 27 | case CubeFace.NegativeZ: 28 | return MipmapTarget.TEXTURE_CUBE_MAP_NEGATIVE_Z; 29 | case CubeFace.PositiveX: 30 | return MipmapTarget.TEXTURE_CUBE_MAP_POSITIVE_X; 31 | case CubeFace.PositiveY: 32 | return MipmapTarget.TEXTURE_CUBE_MAP_POSITIVE_Y; 33 | case CubeFace.PositiveZ: 34 | default: 35 | return MipmapTarget.TEXTURE_CUBE_MAP_POSITIVE_Z; 36 | } 37 | case TextureTarget.TEXTURE_2D: 38 | default: 39 | return MipmapTarget.TEXTURE_2D; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lakuna/ugl", 3 | "version": "26.1.4", 4 | "description": "A lightweight WebGL2 library.", 5 | "keywords": [ 6 | "front-end" 7 | ], 8 | "homepage": "https://ugl.lakuna.pw", 9 | "bugs": { 10 | "url": "https://github.com/Lakuna/ugl/issues", 11 | "email": "travis@lakuna.pw" 12 | }, 13 | "license": "MIT", 14 | "author": { 15 | "name": "Travis Martin", 16 | "email": "travis@lakuna.pw", 17 | "url": "https://www.lakuna.pw/" 18 | }, 19 | "funding": { 20 | "type": "individual", 21 | "url": "https://github.com/sponsors/Lakuna" 22 | }, 23 | "files": [ 24 | "dist", 25 | "src" 26 | ], 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/Lakuna/ugl.git" 30 | }, 31 | "scripts": { 32 | "build": "tsc", 33 | "lint": "eslint src", 34 | "test": "serve", 35 | "doc": "typedoc src", 36 | "beautify": "prettier . --write" 37 | }, 38 | "devDependencies": { 39 | "@eslint/js": "^9.39.1", 40 | "@lakuna/umath": "^1.4.3", 41 | "@types/eslint": "^9.6.1", 42 | "@types/eslint-config-prettier": "^6.11.3", 43 | "@types/offscreencanvas": "^2019.7.3", 44 | "@types/webgl2": "^0.0.12", 45 | "@types/webxr": "^0.5.24", 46 | "eslint": "^9.39.1", 47 | "eslint-config-prettier": "^10.1.8", 48 | "eslint-plugin-prettier": "^5.5.4", 49 | "eslint-plugin-tsdoc": "^0.5.0", 50 | "prettier": "^3.6.2", 51 | "serve": "^14.2.5", 52 | "typedoc": "^0.28.14", 53 | "typescript": "^5.9.3", 54 | "typescript-eslint": "^8.47.0" 55 | }, 56 | "exports": "./dist/index.js", 57 | "typings": "./dist/index.d.ts", 58 | "type": "module", 59 | "sideEffects": false 60 | } 61 | -------------------------------------------------------------------------------- /src/constants/BlendFunction.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Blending functions. 3 | * @public 4 | */ 5 | enum BlendFunction { 6 | /** Multiply all colors by zero. */ 7 | ZERO = 0, 8 | 9 | /** Multiply all colors by one. */ 10 | ONE = 1, 11 | 12 | /** Multiply all colors by the source colors. */ 13 | SRC_COLOR = 0x0300, 14 | 15 | /** Multiply all colors by one minus each source color. */ 16 | ONE_MINUS_SRC_COLOR = 0x0301, 17 | 18 | /** Multiply all colors by the destination color. */ 19 | DST_COLOR = 0x0306, 20 | 21 | /** Multiply all colors by one minus the destination color. */ 22 | ONE_MINUS_DST_COLOR = 0x0307, 23 | 24 | /** Multiply all colors by the source alpha value. */ 25 | SRC_ALPHA = 0x0302, 26 | 27 | /** Multiply all colors by one minus the source alpha value. */ 28 | ONE_MINUS_SRC_ALPHA = 0x0303, 29 | 30 | /** Multiply all colors by the destination alpha value. */ 31 | DST_ALPHA = 0x0304, 32 | 33 | /** Multiply all colors by one minus the destination alpha value. */ 34 | ONE_MINUS_DST_ALPHA = 0x0305, 35 | 36 | /** Multiply all colors by a constant color. */ 37 | CONSTANT_COLOR = 0x8001, 38 | 39 | /** Multiply all colors by one minus a constant color. */ 40 | ONE_MINUS_CONSTANT_COLOR = 0x8002, 41 | 42 | /** Multiply all colors by a constant alpha value. */ 43 | CONSTANT_ALPHA = 0x8003, 44 | 45 | /** Multiply all colors by one minus a constant alpha value. */ 46 | ONE_MINUS_CONSTANT_ALPHA = 0x8004, 47 | 48 | /** Multiply the RGB colors by the smaller of either the source alpha value or the value of one minus the destination alpha value. Multiply the alpha value by one. */ 49 | SRC_ALPHA_SATURATE = 0x0308 50 | } 51 | 52 | export default BlendFunction; 53 | -------------------------------------------------------------------------------- /src/utility/internal/getTypedArrayConstructorForTextureDataType.ts: -------------------------------------------------------------------------------- 1 | import DataType from "../../constants/DataType.js"; 2 | import TextureDataType from "../../constants/TextureDataType.js"; 3 | 4 | /** 5 | * Get the constructor for the typed array corresponding to the given data type. 6 | * @param dataType - The data type. 7 | * @returns A typed array constructor. 8 | * @internal 9 | */ 10 | export default function getTypedArrayConstructorForDataType( 11 | dataType: TextureDataType | DataType 12 | ): 13 | | Int8ArrayConstructor 14 | | Int16ArrayConstructor 15 | | Int32ArrayConstructor 16 | | Uint8ArrayConstructor 17 | | Uint16ArrayConstructor 18 | | Uint32ArrayConstructor 19 | | Float16ArrayConstructor 20 | | Float32ArrayConstructor { 21 | switch (dataType) { 22 | case DataType.BYTE: 23 | return Int8Array; 24 | case DataType.SHORT: 25 | return Int16Array; 26 | case DataType.INT: 27 | case DataType.INT_2_10_10_10_REV: 28 | return Int32Array; 29 | case DataType.UNSIGNED_SHORT: 30 | case TextureDataType.UNSIGNED_SHORT_4_4_4_4: 31 | case TextureDataType.UNSIGNED_SHORT_5_5_5_1: 32 | case TextureDataType.UNSIGNED_SHORT_5_6_5: 33 | return Uint16Array; 34 | case DataType.UNSIGNED_INT: 35 | case DataType.UNSIGNED_INT_2_10_10_10_REV: 36 | case TextureDataType.UNSIGNED_INT_10F_11F_11F_REV: 37 | case TextureDataType.UNSIGNED_INT_24_8: 38 | case TextureDataType.UNSIGNED_INT_5_9_9_9_REV: 39 | return Uint32Array; 40 | case DataType.HALF_FLOAT: 41 | case TextureDataType.HALF_FLOAT_OES: 42 | return Float16Array; 43 | case DataType.FLOAT: 44 | case TextureDataType.FLOAT_32_UNSIGNED_INT_24_8_REV: 45 | return Float32Array; 46 | case DataType.UNSIGNED_BYTE: 47 | default: // Not possible if TypeScript is obeyed. 48 | return Uint8Array; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/core/variables/attributes/MatrixAttribute.ts: -------------------------------------------------------------------------------- 1 | import Attribute from "./Attribute.js"; 2 | import type AttributeValue from "../../../types/AttributeValue.js"; 3 | import type Program from "../../Program.js"; 4 | import getSizeOfDataType from "../../../utility/internal/getSizeOfDataType.js"; 5 | 6 | /** 7 | * A matrix input variable in a vertex shader. 8 | * @internal 9 | */ 10 | export default class MatrixAttribute extends Attribute { 11 | /** 12 | * Create a matrix attribute. 13 | * @param program - The shader program that the attribute belongs to. 14 | * @param activeInfo - The information of the attribute. 15 | * @param dim - The side length of the matrix. 16 | * @internal 17 | */ 18 | public constructor( 19 | program: Program, 20 | activeInfo: WebGLActiveInfo, 21 | dim: 1 | 2 | 3 | 4 22 | ) { 23 | super(program, activeInfo); 24 | this.dim = dim; 25 | } 26 | 27 | /** 28 | * The side length of values passed to this attribute. 29 | * @internal 30 | */ 31 | private readonly dim: 1 | 2 | 3 | 4; 32 | 33 | /** 34 | * Set the value of this attribute. 35 | * @param value - The value to pass to the attribute. 36 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer | vertexAttribPointer} 37 | * @internal 38 | */ 39 | protected override setterInternal(value: AttributeValue): void { 40 | const normalized = value.normalized ?? false; 41 | const stride = value.stride ?? 0; 42 | const offset = value.offset ?? 0; 43 | const actualStride = stride || getSizeOfDataType(value.vbo.type); 44 | for (let i = 0; i < this.dim; i++) { 45 | this.gl.vertexAttribPointer( 46 | this.location + i, 47 | this.dim, 48 | value.vbo.type, 49 | normalized, 50 | stride, 51 | offset + actualStride * this.dim * i 52 | ); 53 | } 54 | 55 | this.valueCache = value; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/constants/BufferUsage.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Usage patterns of a buffer's data store for optimization purposes. 3 | * @public 4 | */ 5 | enum BufferUsage { 6 | /** The contents are intended to be specified once by the application, and used many times as the source for WebGL drawing and image specification commands. */ 7 | STATIC_DRAW = 0x88e4, 8 | 9 | /** The contents are intended to be respecified repeatedly by the application, and used many times as the source for WebGL drawing and image specification commands. */ 10 | DYNAMIC_DRAW = 0x88e8, 11 | 12 | /** The contents are intended to be specified once by the application, and used at most a few times as the source for WebGL drawing and image specification commands. */ 13 | STREAM_DRAW = 0x88e0, 14 | 15 | /** The contents are intended to be specified once by reading data from WebGL, and queried many times by the application. */ 16 | STATIC_READ = 0x88e5, 17 | 18 | /** The contents are intended to be respecified repeatedly by reading data from WebGL, and queried many times by the application. */ 19 | DYNAMIC_READ = 0x88e9, 20 | 21 | /** The contents are intended to be specified once by reading data from WebGL, and queried at most a few times by the application. */ 22 | STREAM_READ = 0x88e1, 23 | 24 | /** The contents are intended to be specified once by reading data from WebGL, and used many times as the source for WebGL drawing and image specification commands. */ 25 | STATIC_COPY = 0x88e6, 26 | 27 | /** The contents are intended to be respecified repeatedly by reading data from WebGL, and used many times as the source for WebGL drawing and image specification commands. */ 28 | DYNAMIC_COPY = 0x88ea, 29 | 30 | /** The contents are intended to be specified once by reading data from WebGL, and used at most a few times as the source for WebGL drawing and image specification commands. */ 31 | STREAM_COPY = 0x88e2 32 | } 33 | 34 | export default BufferUsage; 35 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import { configs, parser, plugin } from "typescript-eslint"; 2 | import { defineConfig } from "eslint/config"; 3 | import eslint from "@eslint/js"; 4 | import prettier from "eslint-plugin-prettier/recommended"; 5 | import tsdoc from "eslint-plugin-tsdoc"; 6 | 7 | export default defineConfig( 8 | // Enable all ESLint rules. 9 | eslint.configs.all, 10 | 11 | // Disable specific rules. 12 | { 13 | rules: { 14 | // Possible Problems 15 | // N/A 16 | 17 | // Suggestions 18 | complexity: "off", 19 | "id-length": "off", 20 | "max-depth": "off", 21 | "max-lines": "off", 22 | "max-lines-per-function": "off", 23 | "max-nested-callbacks": "off", 24 | "max-params": "off", 25 | "max-statements": "off", 26 | "no-bitwise": "off", 27 | "no-continue": "off", 28 | "no-div-regex": "off", 29 | "no-inline-comments": "off", 30 | "no-label-var": "off", 31 | "no-labels": "off", 32 | "no-magic-numbers": "off", 33 | "no-nested-ternary": "off", 34 | "no-plusplus": "off", 35 | "no-shadow": "off", // Must use `@typescript-eslint/no-shadow` instead. 36 | "no-ternary": "off", 37 | "no-undef-init": "off", 38 | "no-void": "off", 39 | "no-warning-comments": "off", 40 | "one-var": ["error", "never"] 41 | 42 | // Layout and Formatting 43 | // N/A 44 | } 45 | }, 46 | 47 | // Enable type checking and related rules. 48 | ...configs.strictTypeChecked, 49 | ...configs.stylisticTypeChecked, 50 | { 51 | languageOptions: { 52 | parser, 53 | parserOptions: { ecmaVersion: "latest", project: true } 54 | }, 55 | plugins: { "@typescript-eslint": plugin }, 56 | rules: { "@typescript-eslint/no-shadow": "error" } 57 | }, 58 | 59 | // Enable the TSDoc plugin. 60 | { plugins: { tsdoc }, rules: { "tsdoc/syntax": "error" } }, 61 | 62 | // Enable the Prettier plugin. 63 | prettier // Includes `eslint-config-prettier` and `eslint-plugin-prettier`. 64 | ); 65 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/Vector2Uniform.ts: -------------------------------------------------------------------------------- 1 | import MultipleValuedUniform from "./MultipleValuedUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A two-dimensional vector global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class Vector2Uniform extends MultipleValuedUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0]; 20 | this.vectorValueCache = [0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this vector uniform. 25 | * @internal 26 | */ 27 | protected vectorValueCache: [number, number]; 28 | 29 | /** 30 | * Set the value of this uniform if the value is iterable. 31 | * @param value - The value to pass to the uniform. 32 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 33 | * @internal 34 | */ 35 | public override iterableSetter(value: Iterable): void { 36 | // Can only accept two values. 37 | const [x, y] = [...value]; 38 | if ( 39 | (x === this.vectorValueCache[0] && y === this.vectorValueCache[1]) || 40 | typeof x === "undefined" || 41 | typeof y === "undefined" 42 | ) { 43 | return; 44 | } 45 | 46 | this.iterableSetterInternal(value); 47 | this.vectorValueCache = [x, y]; 48 | } 49 | 50 | /** 51 | * Set the value of this uniform if the value is iterable. 52 | * @param value - The value to pass to the uniform. 53 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 54 | * @internal 55 | */ 56 | public abstract iterableSetterInternal(value: Iterable): void; 57 | } 58 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/Vector3Uniform.ts: -------------------------------------------------------------------------------- 1 | import MultipleValuedUniform from "./MultipleValuedUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A three-dimensional vector global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class Vector3Uniform extends MultipleValuedUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0]; 20 | this.vectorValueCache = [0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this vector uniform. 25 | * @internal 26 | */ 27 | protected vectorValueCache: [number, number, number]; 28 | 29 | /** 30 | * Set the value of this uniform if the value is iterable. 31 | * @param value - The value to pass to the uniform. 32 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 33 | * @internal 34 | */ 35 | public override iterableSetter(value: Iterable): void { 36 | // Can only accept three values. 37 | const [x, y, z] = [...value]; 38 | if ( 39 | (x === this.vectorValueCache[0] && 40 | y === this.vectorValueCache[1] && 41 | z === this.vectorValueCache[2]) || 42 | typeof x === "undefined" || 43 | typeof y === "undefined" || 44 | typeof z === "undefined" 45 | ) { 46 | return; 47 | } 48 | 49 | this.iterableSetterInternal(value); 50 | this.vectorValueCache = [x, y, z]; 51 | } 52 | 53 | /** 54 | * Set the value of this uniform if the value is iterable. 55 | * @param value - The value to pass to the uniform. 56 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 57 | * @internal 58 | */ 59 | public abstract iterableSetterInternal(value: Iterable): void; 60 | } 61 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MatrixUniform4.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform from "./MatrixUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A four-value matrix global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class MatrixUniform4 extends MatrixUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0, 0]; 20 | this.matrixValueCache = [0, 0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this matrix uniform. 25 | * @internal 26 | */ 27 | protected matrixValueCache: [number, number, number, number]; 28 | 29 | /** 30 | * Set the value of this uniform if the value is iterable. 31 | * @param value - The value to pass to the uniform. 32 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 33 | * @internal 34 | */ 35 | public override iterableSetter(value: Iterable): void { 36 | // Can only accept four values. 37 | const [i0, i1, i2, i3] = [...value]; 38 | if ( 39 | (i0 === this.matrixValueCache[0] && 40 | i1 === this.matrixValueCache[1] && 41 | i2 === this.matrixValueCache[2] && 42 | i3 === this.matrixValueCache[3]) || 43 | typeof i0 === "undefined" || 44 | typeof i1 === "undefined" || 45 | typeof i2 === "undefined" || 46 | typeof i3 === "undefined" 47 | ) { 48 | return; 49 | } 50 | 51 | this.iterableSetterInternal(value); 52 | this.matrixValueCache = [i0, i1, i2, i3]; 53 | } 54 | 55 | /** 56 | * Set the value of this uniform if the value is iterable. 57 | * @param value - The value to pass to the uniform. 58 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 59 | * @internal 60 | */ 61 | public abstract iterableSetterInternal(value: Iterable): void; 62 | } 63 | -------------------------------------------------------------------------------- /src/core/variables/attributes/createAttribute.ts: -------------------------------------------------------------------------------- 1 | import type Attribute from "./Attribute.js"; 2 | import FloatAttribute from "./FloatAttribute.js"; 3 | import IntegerAttribute from "./IntegerAttribute.js"; 4 | import MatrixAttribute from "./MatrixAttribute.js"; 5 | import type Program from "../../Program.js"; 6 | import UnsupportedOperationError from "../../../utility/UnsupportedOperationError.js"; 7 | import VariableType from "../../../constants/VariableType.js"; 8 | 9 | /** 10 | * Create a wrapper object for an attribute. 11 | * @param program - The shader program that the attribute belongs to. 12 | * @param index - The index of the attribute. 13 | * @returns The attribute. 14 | * @throws {@link UnsupportedOperationError} if the active information of the attribute cannot be retrieved. 15 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getActiveAttrib | getActiveAttrib} 16 | * @internal 17 | */ 18 | export default function createAttribute( 19 | program: Program, 20 | index: number 21 | ): Attribute { 22 | const activeInfo = program.gl.getActiveAttrib(program.internal, index); 23 | if (!activeInfo) { 24 | throw new UnsupportedOperationError( 25 | "The environment does not support active information." 26 | ); 27 | } 28 | 29 | switch (activeInfo.type as VariableType) { 30 | case VariableType.FLOAT: 31 | case VariableType.FLOAT_VEC2: 32 | case VariableType.FLOAT_VEC3: 33 | case VariableType.FLOAT_VEC4: 34 | return new FloatAttribute(program, activeInfo); 35 | case VariableType.INT: 36 | case VariableType.INT_VEC2: 37 | case VariableType.INT_VEC3: 38 | case VariableType.INT_VEC4: 39 | case VariableType.UNSIGNED_INT: 40 | case VariableType.UNSIGNED_INT_VEC2: 41 | case VariableType.UNSIGNED_INT_VEC3: 42 | case VariableType.UNSIGNED_INT_VEC4: 43 | case VariableType.BOOL: 44 | case VariableType.BOOL_VEC2: 45 | case VariableType.BOOL_VEC3: 46 | case VariableType.BOOL_VEC4: 47 | return new IntegerAttribute(program, activeInfo); 48 | case VariableType.FLOAT_MAT2: 49 | return new MatrixAttribute(program, activeInfo, 2); 50 | case VariableType.FLOAT_MAT3: 51 | return new MatrixAttribute(program, activeInfo, 3); 52 | case VariableType.FLOAT_MAT4: 53 | default: // Not possible as long as this function is only called internally. 54 | return new MatrixAttribute(program, activeInfo, 4); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/Vector4Uniform.ts: -------------------------------------------------------------------------------- 1 | import MultipleValuedUniform from "./MultipleValuedUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A four-dimensional vector global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class Vector4Uniform extends MultipleValuedUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0, 0]; 20 | this.vectorValueCache = [0, 0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this vector uniform. 25 | * @internal 26 | */ 27 | protected vectorValueCache: [number, number, number, number]; 28 | 29 | /** 30 | * Set the value of this uniform if the value is iterable. 31 | * @param value - The value to pass to the uniform. 32 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 33 | * @internal 34 | */ 35 | public override iterableSetter(value: Iterable): void { 36 | // Can only accept four values. 37 | const [x, y, z, w] = [...value]; 38 | if ( 39 | (x === this.vectorValueCache[0] && 40 | y === this.vectorValueCache[1] && 41 | z === this.vectorValueCache[2] && 42 | w === this.vectorValueCache[3]) || 43 | typeof x === "undefined" || 44 | typeof y === "undefined" || 45 | typeof z === "undefined" || 46 | typeof w === "undefined" 47 | ) { 48 | return; 49 | } 50 | 51 | this.iterableSetterInternal(value); 52 | this.vectorValueCache = [x, y, z, w]; 53 | } 54 | 55 | /** 56 | * Set the value of this uniform if the value is iterable. 57 | * @param value - The value to pass to the uniform. 58 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 59 | * @internal 60 | */ 61 | public abstract iterableSetterInternal(value: Iterable): void; 62 | } 63 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/SamplerUniform.ts: -------------------------------------------------------------------------------- 1 | import IntegerUniform from "./IntegerUniform.js"; 2 | import type Texture from "../../textures/Texture.js"; 3 | 4 | /** A sampler global variable in a WebGL shader program. */ 5 | export default class SamplerUniform extends IntegerUniform { 6 | /** 7 | * Set the value of this uniform if the value is iterable. 8 | * @param value - The value to pass to the uniform. 9 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 10 | * @internal 11 | */ 12 | public override iterableSetter( 13 | value: Iterable | Iterable 14 | ): void { 15 | const textureUnits = []; 16 | for (const texture of value) { 17 | // If a texture unit was passed, just fall back to integer behavior. 18 | if (typeof texture === "number") { 19 | super.iterableSetter(value as Iterable); 20 | return; 21 | } 22 | 23 | // Ensure that the texture is texture complete. 24 | if (!texture.isTextureComplete) { 25 | texture.generateMipmap(); 26 | } 27 | 28 | textureUnits.push(texture.bind(void 0, true)); 29 | } 30 | 31 | // Can only accept one value. 32 | const [textureUnit] = [...textureUnits]; 33 | if ( 34 | textureUnit === this.scalarValueCache || 35 | typeof textureUnit === "undefined" 36 | ) { 37 | return; 38 | } 39 | 40 | // Pass the texture units to the shader program. 41 | this.iterableSetterInternal(textureUnits); 42 | this.scalarValueCache = textureUnit; 43 | } 44 | 45 | /** 46 | * Set the value of this uniform if the value is not iterable. 47 | * @param value - The value to pass to the uniform. 48 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 49 | * @internal 50 | */ 51 | public override setter(value: number | Texture): void { 52 | // If a texture unit was passed, just fall back to integer behavior. 53 | if (typeof value === "number") { 54 | super.setter(value); 55 | return; 56 | } 57 | 58 | // Ensure that the texture is texture complete. 59 | if (!value.isTextureComplete) { 60 | value.generateMipmap(); 61 | } 62 | 63 | const textureUnit = value.bind(void 0, true); 64 | if (textureUnit === this.scalarValueCache) { 65 | return; 66 | } 67 | 68 | // Pass the texture unit to the shader program. 69 | this.setterInternal(textureUnit); 70 | this.scalarValueCache = textureUnit; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MatrixUniform6.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform from "./MatrixUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A six-value matrix global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class MatrixUniform6 extends MatrixUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0, 0, 0, 0]; 20 | this.matrixValueCache = [0, 0, 0, 0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this matrix uniform. 25 | * @internal 26 | */ 27 | protected matrixValueCache: [number, number, number, number, number, number]; 28 | 29 | /** 30 | * Set the value of this uniform if the value is iterable. 31 | * @param value - The value to pass to the uniform. 32 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 33 | * @internal 34 | */ 35 | public override iterableSetter(value: Iterable): void { 36 | // Can only accept six values. 37 | const [i0, i1, i2, i3, i4, i5] = [...value]; 38 | if ( 39 | (i0 === this.matrixValueCache[0] && 40 | i1 === this.matrixValueCache[1] && 41 | i2 === this.matrixValueCache[2] && 42 | i3 === this.matrixValueCache[3] && 43 | i4 === this.matrixValueCache[4] && 44 | i5 === this.matrixValueCache[5]) || 45 | typeof i0 === "undefined" || 46 | typeof i1 === "undefined" || 47 | typeof i2 === "undefined" || 48 | typeof i3 === "undefined" || 49 | typeof i4 === "undefined" || 50 | typeof i5 === "undefined" 51 | ) { 52 | return; 53 | } 54 | 55 | this.iterableSetterInternal(value); 56 | this.matrixValueCache = [i0, i1, i2, i3, i4, i5]; 57 | } 58 | 59 | /** 60 | * Set the value of this uniform if the value is iterable. 61 | * @param value - The value to pass to the uniform. 62 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 63 | * @internal 64 | */ 65 | public abstract iterableSetterInternal(value: Iterable): void; 66 | } 67 | -------------------------------------------------------------------------------- /src/core/variables/Varying.ts: -------------------------------------------------------------------------------- 1 | import BufferTarget from "../../constants/BufferTarget.js"; 2 | import type Program from "../Program.js"; 3 | import UnsupportedOperationError from "../../utility/UnsupportedOperationError.js"; 4 | import Variable from "./Variable.js"; 5 | import type VaryingValue from "../../types/VaryingValue.js"; 6 | import type VertexBuffer from "../buffers/VertexBuffer.js"; 7 | 8 | /** 9 | * An input variable in a WebGL fragment shader used for transform feedback. 10 | * @public 11 | */ 12 | export default class Varying extends Variable { 13 | /** 14 | * Create a transform feedback varying. 15 | * @param program - The shader program that this transform feedback varying belongs to. 16 | * @param index - The index of this transform feedback varying. 17 | * @throws {@link UnsupportedOperationError} if the active information of the varying cannot be retrieved. 18 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/getTransformFeedbackVarying | getTransformFeedbackVarying} 19 | * @internal 20 | */ 21 | public constructor(program: Program, index: number) { 22 | const activeInfo = program.context.gl.getTransformFeedbackVarying( 23 | program.internal, 24 | index 25 | ); 26 | if (!activeInfo) { 27 | throw new UnsupportedOperationError( 28 | "The environment does not support active information." 29 | ); 30 | } 31 | 32 | super(program, activeInfo); 33 | } 34 | 35 | /** 36 | * The value of this varying. 37 | * @internal 38 | */ 39 | private valueCache?: VaryingValue; 40 | 41 | /** The value that is stored in this varying. */ 42 | public override get value(): Readonly | undefined { 43 | return this.valueCache; 44 | } 45 | 46 | // Should only be called from within `TransformFeedback`. 47 | /** @internal */ 48 | public override set value(value: VaryingValue | VertexBuffer | undefined) { 49 | if (!value) { 50 | return; 51 | } 52 | 53 | const realValue = "vbo" in value ? { ...value } : { vbo: value }; 54 | realValue.offset ??= 0; 55 | 56 | if (realValue.size) { 57 | this.gl.bindBufferRange( 58 | BufferTarget.TRANSFORM_FEEDBACK_BUFFER, 59 | this.program.varyings 60 | .keys() 61 | .toArray() 62 | .findIndex((name) => name === this.name), 63 | realValue.vbo.internal, 64 | realValue.offset, 65 | realValue.size 66 | ); 67 | } else { 68 | this.gl.bindBufferBase( 69 | BufferTarget.TRANSFORM_FEEDBACK_BUFFER, 70 | this.program.varyings 71 | .keys() 72 | .toArray() 73 | .findIndex((name) => name === this.name), 74 | realValue.vbo.internal 75 | ); 76 | } 77 | 78 | this.valueCache = realValue; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/types/ExtensionObject.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * WebGL extension implementations. 3 | * @public 4 | */ 5 | export type ExtensionObject = 6 | // eslint-disable-next-line camelcase 7 | | ANGLE_instanced_arrays 8 | // eslint-disable-next-line camelcase 9 | | EXT_blend_minmax 10 | // eslint-disable-next-line camelcase 11 | | EXT_color_buffer_float 12 | // eslint-disable-next-line camelcase 13 | | EXT_color_buffer_half_float 14 | // EXT_disjoint_timer_query 15 | // eslint-disable-next-line camelcase 16 | | EXT_float_blend 17 | // eslint-disable-next-line camelcase 18 | | EXT_frag_depth 19 | // eslint-disable-next-line camelcase 20 | | EXT_shader_texture_lod 21 | // eslint-disable-next-line camelcase 22 | | EXT_sRGB 23 | // eslint-disable-next-line camelcase 24 | | EXT_texture_compression_bptc 25 | // eslint-disable-next-line camelcase 26 | | EXT_texture_compression_rgtc 27 | // eslint-disable-next-line camelcase 28 | | EXT_texture_filter_anisotropic 29 | // eslint-disable-next-line camelcase 30 | | EXT_texture_norm16 31 | // eslint-disable-next-line camelcase 32 | | KHR_parallel_shader_compile 33 | // eslint-disable-next-line camelcase 34 | | OES_draw_buffers_indexed 35 | // eslint-disable-next-line camelcase 36 | | OES_element_index_uint 37 | // eslint-disable-next-line camelcase 38 | | OES_fbo_render_mipmap 39 | // eslint-disable-next-line camelcase 40 | | OES_standard_derivatives 41 | // eslint-disable-next-line camelcase 42 | | OES_texture_float 43 | // eslint-disable-next-line camelcase 44 | | OES_texture_float_linear 45 | // eslint-disable-next-line camelcase 46 | | OES_texture_half_float 47 | // eslint-disable-next-line camelcase 48 | | OES_texture_half_float_linear 49 | // eslint-disable-next-line camelcase 50 | | OES_vertex_array_object 51 | // eslint-disable-next-line camelcase 52 | | OVR_multiview2 53 | // eslint-disable-next-line camelcase 54 | | WEBGL_color_buffer_float 55 | // eslint-disable-next-line camelcase 56 | | WEBGL_compressed_texture_astc 57 | // eslint-disable-next-line camelcase 58 | | WEBGL_compressed_texture_etc 59 | // eslint-disable-next-line camelcase 60 | | WEBGL_compressed_texture_etc1 61 | // eslint-disable-next-line camelcase 62 | | WEBGL_compressed_texture_pvrtc 63 | // eslint-disable-next-line camelcase 64 | | WEBGL_compressed_texture_s3tc 65 | // eslint-disable-next-line camelcase 66 | | WEBGL_compressed_texture_s3tc_srgb 67 | // eslint-disable-next-line camelcase 68 | | WEBGL_debug_renderer_info 69 | // eslint-disable-next-line camelcase 70 | | WEBGL_debug_shaders 71 | // eslint-disable-next-line camelcase 72 | | WEBGL_depth_texture 73 | // eslint-disable-next-line camelcase 74 | | WEBGL_draw_buffers 75 | // eslint-disable-next-line camelcase 76 | | WEBGL_lose_context 77 | // eslint-disable-next-line camelcase 78 | | WEBGL_multi_draw; 79 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MatrixUniform8.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform from "./MatrixUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * An eight-value matrix global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class MatrixUniform8 extends MatrixUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0, 0, 0, 0, 0, 0]; 20 | this.matrixValueCache = [0, 0, 0, 0, 0, 0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this matrix uniform. 25 | * @internal 26 | */ 27 | protected matrixValueCache: [ 28 | number, 29 | number, 30 | number, 31 | number, 32 | number, 33 | number, 34 | number, 35 | number 36 | ]; 37 | 38 | /** 39 | * Set the value of this uniform if the value is iterable. 40 | * @param value - The value to pass to the uniform. 41 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 42 | * @internal 43 | */ 44 | public override iterableSetter(value: Iterable): void { 45 | // Can only accept eight values. 46 | const [i0, i1, i2, i3, i4, i5, i6, i7] = [...value]; 47 | if ( 48 | (i0 === this.matrixValueCache[0] && 49 | i1 === this.matrixValueCache[1] && 50 | i2 === this.matrixValueCache[2] && 51 | i3 === this.matrixValueCache[3] && 52 | i4 === this.matrixValueCache[4] && 53 | i5 === this.matrixValueCache[5] && 54 | i6 === this.matrixValueCache[6] && 55 | i7 === this.matrixValueCache[7]) || 56 | typeof i0 === "undefined" || 57 | typeof i1 === "undefined" || 58 | typeof i2 === "undefined" || 59 | typeof i3 === "undefined" || 60 | typeof i4 === "undefined" || 61 | typeof i5 === "undefined" || 62 | typeof i6 === "undefined" || 63 | typeof i7 === "undefined" 64 | ) { 65 | return; 66 | } 67 | 68 | this.iterableSetterInternal(value); 69 | this.matrixValueCache = [i0, i1, i2, i3, i4, i5, i6, i7]; 70 | } 71 | 72 | /** 73 | * Set the value of this uniform if the value is iterable. 74 | * @param value - The value to pass to the uniform. 75 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 76 | * @internal 77 | */ 78 | public abstract iterableSetterInternal(value: Iterable): void; 79 | } 80 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/ScalarUniform.ts: -------------------------------------------------------------------------------- 1 | import type Program from "../../Program.js"; 2 | import Uniform from "./Uniform.js"; 3 | 4 | /** 5 | * A scalar global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class ScalarUniform extends Uniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = 0; 20 | this.scalarValueCache = 0; 21 | } 22 | 23 | /** 24 | * The value that is stored in this scalar uniform. 25 | * @internal 26 | */ 27 | protected scalarValueCache: number; 28 | 29 | /** 30 | * Set the value of this uniform if the value is iterable. 31 | * @param value - The value to pass to the uniform. 32 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 33 | * @internal 34 | */ 35 | public override iterableSetter(value: Iterable): void { 36 | // Can only accept one value. 37 | const [x] = [...value]; 38 | if (typeof x === "undefined" || x === this.scalarValueCache) { 39 | return; 40 | } 41 | 42 | this.iterableSetterInternal(value); 43 | this.scalarValueCache = x; 44 | } 45 | 46 | /** 47 | * Set the value of this uniform if the value is iterable. 48 | * @param value - The value to pass to the uniform. 49 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 50 | * @internal 51 | */ 52 | public abstract iterableSetterInternal(value: Iterable): void; 53 | 54 | /** 55 | * Set the value of this uniform if the value is not iterable. 56 | * @param value - The value to pass to the uniform. 57 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 58 | * @internal 59 | */ 60 | public override setter(value: number): void { 61 | if (value === this.scalarValueCache) { 62 | return; 63 | } 64 | 65 | this.setterInternal(value); 66 | this.scalarValueCache = value; 67 | } 68 | 69 | /** 70 | * Set the value of this uniform if the value is not iterable. 71 | * @param value - The value to pass to the uniform. 72 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 73 | * @internal 74 | */ 75 | public abstract setterInternal(value: number): void; 76 | } 77 | -------------------------------------------------------------------------------- /src/utility/internal/isTextureDataFormatSized.ts: -------------------------------------------------------------------------------- 1 | import TextureFormat from "../../constants/TextureFormat.js"; 2 | 3 | /** 4 | * Determine whether or not the given texture format is sized. 5 | * @param format - The texture format. 6 | * @returns Whether or not the given texture format is sized. 7 | * @internal 8 | */ 9 | export default function isTextureFormatSized(format: TextureFormat): boolean { 10 | switch (format) { 11 | case TextureFormat.R8: 12 | case TextureFormat.R8_SNORM: 13 | case TextureFormat.R16F: 14 | case TextureFormat.R32F: 15 | case TextureFormat.R8UI: 16 | case TextureFormat.R8I: 17 | case TextureFormat.R16UI: 18 | case TextureFormat.R16I: 19 | case TextureFormat.R32UI: 20 | case TextureFormat.R32I: 21 | case TextureFormat.RG8: 22 | case TextureFormat.RG8_SNORM: 23 | case TextureFormat.RG16F: 24 | case TextureFormat.RG32F: 25 | case TextureFormat.RG8UI: 26 | case TextureFormat.RG8I: 27 | case TextureFormat.RG16UI: 28 | case TextureFormat.RG16I: 29 | case TextureFormat.RG32UI: 30 | case TextureFormat.RG32I: 31 | case TextureFormat.RGB8: 32 | case TextureFormat.SRGB8: 33 | case TextureFormat.RGB565: 34 | case TextureFormat.RGB8_SNORM: 35 | case TextureFormat.R11F_G11F_B10F: 36 | case TextureFormat.RGB9_E5: 37 | case TextureFormat.RGB16F: 38 | case TextureFormat.RGB32F: 39 | case TextureFormat.RGB8UI: 40 | case TextureFormat.RGB8I: 41 | case TextureFormat.RGB16UI: 42 | case TextureFormat.RGB16I: 43 | case TextureFormat.RGB32UI: 44 | case TextureFormat.RGB32I: 45 | case TextureFormat.RGBA8: 46 | case TextureFormat.SRGB8_ALPHA8: 47 | case TextureFormat.RGBA8_SNORM: 48 | case TextureFormat.RGB5_A1: 49 | case TextureFormat.RGBA4: 50 | case TextureFormat.RGB10_A2: 51 | case TextureFormat.RGBA16F: 52 | case TextureFormat.RGBA32F: 53 | case TextureFormat.RGBA8UI: 54 | case TextureFormat.RGBA8I: 55 | case TextureFormat.RGB10_A2UI: 56 | case TextureFormat.RGBA16UI: 57 | case TextureFormat.RGBA16I: 58 | case TextureFormat.RGBA32I: 59 | case TextureFormat.RGBA32UI: 60 | case TextureFormat.DEPTH_COMPONENT16: 61 | case TextureFormat.DEPTH_COMPONENT24: 62 | case TextureFormat.DEPTH_COMPONENT32F: 63 | case TextureFormat.DEPTH24_STENCIL8: 64 | case TextureFormat.DEPTH32F_STENCIL8: 65 | case TextureFormat.COMPRESSED_R11_EAC: 66 | case TextureFormat.COMPRESSED_SIGNED_R11_EAC: 67 | case TextureFormat.COMPRESSED_RG11_EAC: 68 | case TextureFormat.COMPRESSED_SIGNED_RG11_EAC: 69 | case TextureFormat.COMPRESSED_RGB8_ETC2: 70 | case TextureFormat.COMPRESSED_RGBA8_ETC2_EAC: 71 | case TextureFormat.COMPRESSED_SRGB8_ETC2: 72 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 73 | case TextureFormat.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 74 | case TextureFormat.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 75 | return true; 76 | default: 77 | return false; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MatrixUniform9.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform from "./MatrixUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A nine-value matrix global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class MatrixUniform9 extends MatrixUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0, 0, 0, 0, 0, 0, 0]; 20 | this.matrixValueCache = [0, 0, 0, 0, 0, 0, 0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this matrix uniform. 25 | * @internal 26 | */ 27 | protected matrixValueCache: [ 28 | number, 29 | number, 30 | number, 31 | number, 32 | number, 33 | number, 34 | number, 35 | number, 36 | number 37 | ]; 38 | 39 | /** 40 | * Set the value of this uniform if the value is iterable. 41 | * @param value - The value to pass to the uniform. 42 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 43 | * @internal 44 | */ 45 | public override iterableSetter(value: Iterable): void { 46 | // Can only accept nine values. 47 | const [i0, i1, i2, i3, i4, i5, i6, i7, i8] = [...value]; 48 | if ( 49 | (i0 === this.matrixValueCache[0] && 50 | i1 === this.matrixValueCache[1] && 51 | i2 === this.matrixValueCache[2] && 52 | i3 === this.matrixValueCache[3] && 53 | i4 === this.matrixValueCache[4] && 54 | i5 === this.matrixValueCache[5] && 55 | i6 === this.matrixValueCache[6] && 56 | i7 === this.matrixValueCache[7] && 57 | i8 === this.matrixValueCache[8]) || 58 | typeof i0 === "undefined" || 59 | typeof i1 === "undefined" || 60 | typeof i2 === "undefined" || 61 | typeof i3 === "undefined" || 62 | typeof i4 === "undefined" || 63 | typeof i5 === "undefined" || 64 | typeof i6 === "undefined" || 65 | typeof i7 === "undefined" || 66 | typeof i8 === "undefined" 67 | ) { 68 | return; 69 | } 70 | 71 | this.iterableSetterInternal(value); 72 | this.matrixValueCache = [i0, i1, i2, i3, i4, i5, i6, i7, i8]; 73 | } 74 | 75 | /** 76 | * Set the value of this uniform if the value is iterable. 77 | * @param value - The value to pass to the uniform. 78 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 79 | * @internal 80 | */ 81 | public abstract iterableSetterInternal(value: Iterable): void; 82 | } 83 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: 6 | - created 7 | 8 | jobs: 9 | build: 10 | name: Build 11 | permissions: {} 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Check-Out Repository 15 | uses: actions/checkout@v4 16 | - name: Set up Node.js 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: latest 20 | - name: Install Dependencies 21 | run: npm ci 22 | - name: Lint 23 | run: npm run lint --if-present 24 | - name: Build 25 | run: npm run build --if-present 26 | - name: Test 27 | run: npm run test --if-present 28 | - name: Build Documentation 29 | run: npm run doc --if-present 30 | - name: Upload Package Artifact 31 | uses: actions/upload-artifact@v4 32 | with: 33 | name: package 34 | path: | 35 | dist 36 | src 37 | LICENSE 38 | README.md 39 | package.json 40 | - name: Upload Documentation Artifact 41 | uses: actions/upload-pages-artifact@v3 42 | with: 43 | path: docs 44 | 45 | publish-npm: 46 | name: Publish to npm 47 | permissions: 48 | id-token: write 49 | needs: build 50 | runs-on: ubuntu-latest 51 | steps: 52 | - name: Check-Out Repository 53 | uses: actions/checkout@v4 54 | - name: Download Package Artifact 55 | uses: actions/download-artifact@v4 56 | with: 57 | name: package 58 | - name: Set up Node.js 59 | uses: actions/setup-node@v4 60 | with: 61 | node-version: latest 62 | registry-url: https://registry.npmjs.org 63 | - name: Publish 64 | run: npm publish --access public 65 | 66 | publish-gpr: 67 | name: Publish to GitHub Packages 68 | permissions: 69 | packages: write 70 | needs: build 71 | runs-on: ubuntu-latest 72 | steps: 73 | - name: Check-Out Repository 74 | uses: actions/checkout@v4 75 | - name: Download Package Artifact 76 | uses: actions/download-artifact@v4 77 | with: 78 | name: package 79 | - name: Set up Node.js 80 | uses: actions/setup-node@v4 81 | with: 82 | node-version: latest 83 | registry-url: https://npm.pkg.github.com 84 | - name: Publish 85 | run: npm publish --access public 86 | env: 87 | NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 88 | 89 | publish-documentation: 90 | name: Publish Documentation 91 | permissions: 92 | pages: write 93 | id-token: write 94 | needs: 95 | - publish-npm 96 | - publish-gpr 97 | runs-on: ubuntu-latest 98 | steps: 99 | - name: Publish 100 | uses: actions/deploy-pages@v4 101 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/Uniform.ts: -------------------------------------------------------------------------------- 1 | import type Program from "../../Program.js"; 2 | import Texture from "../../textures/Texture.js"; 3 | import type { UniformValue } from "../../../types/UniformValue.js"; 4 | import UnsupportedOperationError from "../../../utility/UnsupportedOperationError.js"; 5 | import Variable from "../Variable.js"; 6 | 7 | /** 8 | * A global variable in a shader program. 9 | * @public 10 | */ 11 | export default abstract class Uniform extends Variable { 12 | /** 13 | * Create a uniform. 14 | * @param program - The shader program that the uniform belongs to. 15 | * @param activeInfo - The information of the uniform. 16 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 17 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 18 | * @internal 19 | */ 20 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 21 | super(program, activeInfo); 22 | 23 | const location = this.gl.getUniformLocation( 24 | program.internal, 25 | this.activeInfo.name 26 | ); 27 | if (!location) { 28 | throw new UnsupportedOperationError( 29 | "The environment does not support uniform locations." 30 | ); 31 | } 32 | 33 | this.location = location; 34 | } 35 | 36 | /** 37 | * The location of this uniform. 38 | * @internal 39 | */ 40 | public readonly location: WebGLUniformLocation; 41 | 42 | /** The offset from the start of the given value to pass to WebGL. */ 43 | public sourceOffset?: number; 44 | 45 | /** The length of the given value. Data is assumed to be tightly-packed if not set or set to zero. */ 46 | public sourceLength?: number; 47 | 48 | /** 49 | * Set the value of this uniform if the value is not iterable. 50 | * @param value - The value to pass to the uniform. 51 | * @internal 52 | */ 53 | public abstract setter(value: number | Texture): void; 54 | 55 | /** 56 | * Set the value of this uniform if the value is iterable. 57 | * @param value - The value to pass to the uniform. 58 | * @internal 59 | */ 60 | public abstract iterableSetter(value: Iterable): void; 61 | 62 | /** 63 | * The value that is stored in this uniform. 64 | * @internal 65 | */ 66 | protected valueCache?: UniformValue; 67 | 68 | /** 69 | * The value that is stored in this uniform. 70 | * @throws Error if the uniform value has not been cached. 71 | */ 72 | public override get value(): UniformValue { 73 | if (typeof this.valueCache === "undefined") { 74 | throw new Error("Attempted to access uncached uniform value."); 75 | } 76 | 77 | return this.valueCache; 78 | } 79 | 80 | public override set value(value: UniformValue) { 81 | this.program.bind(); 82 | 83 | if (typeof value !== "number" && Symbol.iterator in value) { 84 | this.iterableSetter(value); 85 | } else { 86 | this.setter(value); 87 | } 88 | 89 | this.valueCache = value; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MatrixUniform12.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform from "./MatrixUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A twelve-value matrix global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class MatrixUniform12 extends MatrixUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 20 | this.matrixValueCache = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this matrix uniform. 25 | * @internal 26 | */ 27 | protected matrixValueCache: [ 28 | number, 29 | number, 30 | number, 31 | number, 32 | number, 33 | number, 34 | number, 35 | number, 36 | number, 37 | number, 38 | number, 39 | number 40 | ]; 41 | 42 | /** 43 | * Set the value of this uniform if the value is iterable. 44 | * @param value - The value to pass to the uniform. 45 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 46 | * @internal 47 | */ 48 | public override iterableSetter(value: Iterable): void { 49 | // Can only accept twelve values. 50 | const [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11] = [...value]; 51 | if ( 52 | (i0 === this.matrixValueCache[0] && 53 | i1 === this.matrixValueCache[1] && 54 | i2 === this.matrixValueCache[2] && 55 | i3 === this.matrixValueCache[3] && 56 | i4 === this.matrixValueCache[4] && 57 | i5 === this.matrixValueCache[5] && 58 | i6 === this.matrixValueCache[6] && 59 | i7 === this.matrixValueCache[7] && 60 | i8 === this.matrixValueCache[8] && 61 | i9 === this.matrixValueCache[9] && 62 | i10 === this.matrixValueCache[10] && 63 | i11 === this.matrixValueCache[11]) || 64 | typeof i0 === "undefined" || 65 | typeof i1 === "undefined" || 66 | typeof i2 === "undefined" || 67 | typeof i3 === "undefined" || 68 | typeof i4 === "undefined" || 69 | typeof i5 === "undefined" || 70 | typeof i6 === "undefined" || 71 | typeof i7 === "undefined" || 72 | typeof i8 === "undefined" || 73 | typeof i9 === "undefined" || 74 | typeof i10 === "undefined" || 75 | typeof i11 === "undefined" 76 | ) { 77 | return; 78 | } 79 | 80 | this.iterableSetterInternal(value); 81 | this.matrixValueCache = [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11]; 82 | } 83 | 84 | /** 85 | * Set the value of this uniform if the value is iterable. 86 | * @param value - The value to pass to the uniform. 87 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 88 | * @internal 89 | */ 90 | public abstract iterableSetterInternal(value: Iterable): void; 91 | } 92 | -------------------------------------------------------------------------------- /src/constants/VariableType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Types of attributes. 3 | * @public 4 | */ 5 | enum VariableType { 6 | // Attribute or Uniform Types 7 | 8 | /** A 32-bit signed floating-point value. */ 9 | FLOAT = 0x1406, 10 | 11 | /** A two-dimensional vector of 32-bit signed floating-point values. */ 12 | FLOAT_VEC2 = 0x8b50, 13 | 14 | /** A three-dimensional vector of 32-bit signed floating-point values. */ 15 | FLOAT_VEC3 = 0x8b51, 16 | 17 | /** A four-dimensional vector of 32-bit signed floating-point values. */ 18 | FLOAT_VEC4 = 0x8b52, 19 | 20 | /** A boolean value. */ 21 | BOOL = 0x8b56, 22 | 23 | /** A 32-bit signed integer value. */ 24 | INT = 0x1404, 25 | 26 | /** A two-dimensional vector of boolean values. */ 27 | BOOL_VEC2 = 0x8b57, 28 | 29 | /** A two-dimensional vector of 32-bit signed integer values. */ 30 | INT_VEC2 = 0x8b53, 31 | 32 | /** A three-dimensional vector of boolean values. */ 33 | BOOL_VEC3 = 0x8b58, 34 | 35 | /** A three-dimensional vector of 32-bit signed integer values. */ 36 | INT_VEC3 = 0x8b54, 37 | 38 | /** A four-dimensional vector of boolean values. */ 39 | BOOL_VEC4 = 0x8b59, 40 | 41 | /** A four-dimensional vector of 32-bit signed integer values. */ 42 | INT_VEC4 = 0x8b55, 43 | 44 | /** A 32-bit signed uninteger value. */ 45 | UNSIGNED_INT = 0x1405, 46 | 47 | /** A two-dimensional vector of 32-bit unsigned integer values. */ 48 | UNSIGNED_INT_VEC2 = 0x8dc6, 49 | 50 | /** A three-dimensional vector of 32-bit unsigned integer values. */ 51 | UNSIGNED_INT_VEC3 = 0x8dc7, 52 | 53 | /** A four-dimensional vector of 32-bit unsigned integer values. */ 54 | UNSIGNED_INT_VEC4 = 0x8dc8, 55 | 56 | /** A matrix of 32-bit signed floating-point values with two rows and two columns. */ 57 | FLOAT_MAT2 = 0x8b5a, 58 | 59 | /** A matrix of 32-bit signed floating-point values with three rows and three columns. */ 60 | FLOAT_MAT3 = 0x8b5b, 61 | 62 | /** A matrix of 32-bit signed floating-point values with four rows and four columns. */ 63 | FLOAT_MAT4 = 0x8b5c, 64 | 65 | // Uniform-Only Types 66 | 67 | /** A sampler of a 2D texture. */ 68 | SAMPLER_2D = 0x8b5e, 69 | 70 | /** A sampler of a 3D texture. */ 71 | SAMPLER_3D = 0x8b5f, 72 | 73 | /** A sampler of a cube texture. */ 74 | SAMPLER_CUBE = 0x8b60, 75 | 76 | /** A sampler of a 2D shadow texture. */ 77 | SAMPLER_2D_SHADOW = 0x8b62, 78 | 79 | /** A sampler of a 2D array texture. */ 80 | SAMPLER_2D_ARRAY = 0x8dc1, 81 | 82 | /** A sampler of a 2D array shadow texture. */ 83 | SAMPLER_2D_ARRAY_SHADOW = 0x8dc4, 84 | 85 | /** A sampler of a cube shadow texture. */ 86 | SAMPLER_CUBE_SHADOW = 0x8dc5, 87 | 88 | /** An integer sampler of a 2D texture. */ 89 | INT_SAMPLER_2D = 0x8dca, 90 | 91 | /** An integer sampler of a 3D texture. */ 92 | INT_SAMPLER_3D = 0x8dcb, 93 | 94 | /** An integer sampler of a cube texture. */ 95 | INT_SAMPLER_CUBE = 0x8dcc, 96 | 97 | /** An integer sampler of a 2D array texture. */ 98 | INT_SAMPLER_2D_ARRAY = 0x8dcf, 99 | 100 | /** A matrix of 32-bit signed floating-point values with two rows and three columns. */ 101 | FLOAT_MAT2x3 = 0x8b65, 102 | 103 | /** A matrix of 32-bit signed floating-point values with two rows and four columns. */ 104 | FLOAT_MAT2x4 = 0x8b66, 105 | 106 | /** A matrix of 32-bit signed floating-point values with three rows and two columns. */ 107 | FLOAT_MAT3x2 = 0x8b67, 108 | 109 | /** A matrix of 32-bit signed floating-point values with three rows and four columns. */ 110 | FLOAT_MAT3x4 = 0x8b68, 111 | 112 | /** A matrix of 32-bit signed floating-point values with four rows and two columns. */ 113 | FLOAT_MAT4x2 = 0x8b69, 114 | 115 | /** A matrix of 32-bit signed floating-point values with four rows and three columns. */ 116 | FLOAT_MAT4x3 = 0x8b6a 117 | } 118 | 119 | export default VariableType; 120 | -------------------------------------------------------------------------------- /src/core/variables/attributes/Attribute.ts: -------------------------------------------------------------------------------- 1 | import type AttributeValue from "../../../types/AttributeValue.js"; 2 | import BufferTarget from "../../../constants/BufferTarget.js"; 3 | import type Program from "../../Program.js"; 4 | import Variable from "../Variable.js"; 5 | import VertexArray from "../../VertexArray.js"; 6 | import type VertexBuffer from "../../buffers/VertexBuffer.js"; 7 | 8 | /** 9 | * An input variable for a vertex shader. 10 | * @public 11 | */ 12 | export default abstract class Attribute extends Variable { 13 | /** 14 | * Create an attribute. 15 | * @param program - The shader program that the attribute belongs to. 16 | * @param activeInfo - The information of the attribute. 17 | * @internal 18 | */ 19 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 20 | super(program, activeInfo); 21 | this.location = this.gl.getAttribLocation(program.internal, this.name); 22 | this.enabledVaosCache = []; 23 | } 24 | 25 | /** 26 | * The location of this attribute. 27 | * @internal 28 | */ 29 | public readonly location: number; 30 | 31 | /** 32 | * Set the value of this attribute. 33 | * @param value - The value to pass to the attribute. 34 | * @internal 35 | */ 36 | protected abstract setterInternal(value: AttributeValue): void; 37 | 38 | /** 39 | * The VAOs for which this attribute can read data from a buffer. 40 | * @internal 41 | */ 42 | private enabledVaosCache: WebGLVertexArrayObject[]; 43 | 44 | /** 45 | * Whether or not this attribute can read data from a buffer. 46 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/enableVertexAttribArray | enableVertexAttribArray} 47 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/disableVertexAttribArray | disableVertexAttribArray} 48 | */ 49 | public get enabled(): boolean { 50 | const vao = VertexArray.getBound(this.context); 51 | if (!vao) { 52 | return false; 53 | } 54 | 55 | return this.enabledVaosCache.includes(vao); 56 | } 57 | 58 | public set enabled(value: boolean) { 59 | if (this.enabled === value) { 60 | return; 61 | } 62 | 63 | const vao = VertexArray.getBound(this.context); 64 | 65 | // Enable. 66 | if (value) { 67 | this.gl.enableVertexAttribArray(this.location); 68 | if (vao && !this.enabledVaosCache.includes(vao)) { 69 | this.enabledVaosCache.push(vao); 70 | } 71 | 72 | return; 73 | } 74 | 75 | // Disable. 76 | this.gl.disableVertexAttribArray(this.location); 77 | if (vao && this.enabledVaosCache.includes(vao)) { 78 | this.enabledVaosCache.splice(this.enabledVaosCache.indexOf(vao), 1); 79 | } 80 | } 81 | 82 | /** 83 | * The value of this attribute. 84 | * @internal 85 | */ 86 | protected valueCache?: AttributeValue; 87 | 88 | /** The value that is stored in this attribute. */ 89 | public override get value(): Readonly | undefined { 90 | return this.valueCache; 91 | } 92 | 93 | // Should only be called from within `VertexArray`. 94 | /** @internal */ 95 | public override set value(value: AttributeValue | VertexBuffer | undefined) { 96 | if (!value) { 97 | if (!this.value) { 98 | return; 99 | } 100 | 101 | this.enabled = false; 102 | delete this.valueCache; 103 | return; 104 | } 105 | 106 | const realValue = "vbo" in value ? { ...value } : { vbo: value }; 107 | realValue.size ??= 3; 108 | realValue.normalized ??= false; 109 | realValue.stride ??= 0; 110 | realValue.offset ??= 0; 111 | 112 | if ( 113 | realValue.vbo === this.value?.vbo && 114 | realValue.size === this.value.size && 115 | realValue.normalized === this.value.normalized && 116 | realValue.stride === this.value.stride && 117 | realValue.offset === this.value.offset 118 | ) { 119 | return; 120 | } 121 | 122 | this.enabled = true; 123 | realValue.vbo.bind(BufferTarget.ARRAY_BUFFER, false); 124 | this.setterInternal(realValue); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/utility/internal/isTextureDataFormatCompressed.ts: -------------------------------------------------------------------------------- 1 | import TextureDataFormat from "../../constants/TextureDataFormat.js"; 2 | 3 | /** 4 | * Determine whether or not the given texture format is compressed. 5 | * @param format - The texture format. 6 | * @returns Whether or not the given texture format is compressed. 7 | * @internal 8 | */ 9 | export default function isTextureDataFormatCompressed( 10 | format: TextureDataFormat 11 | ): boolean { 12 | switch (format) { 13 | case TextureDataFormat.COMPRESSED_R11_EAC: 14 | case TextureDataFormat.COMPRESSED_RED_GREEN_RGTC2_EXT: 15 | case TextureDataFormat.COMPRESSED_RED_RGTC1_EXT: 16 | case TextureDataFormat.COMPRESSED_RG11_EAC: 17 | case TextureDataFormat.COMPRESSED_RGB8_ETC2: 18 | case TextureDataFormat.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 19 | case TextureDataFormat.COMPRESSED_RGBA8_ETC2_EAC: 20 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x10_KHR: 21 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x5_KHR: 22 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x6_KHR: 23 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x8_KHR: 24 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_12x10_KHR: 25 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_12x12_KHR: 26 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_4x4_KHR: 27 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_5x4_KHR: 28 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_5x5_KHR: 29 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_6x5_KHR: 30 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_6x6_KHR: 31 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_8x5_KHR: 32 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_8x6_KHR: 33 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_8x8_KHR: 34 | case TextureDataFormat.COMPRESSED_RGBA_BPTC_UNORM_EXT: 35 | case TextureDataFormat.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: 36 | case TextureDataFormat.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: 37 | case TextureDataFormat.COMPRESSED_RGBA_S3TC_DXT1_EXT: 38 | case TextureDataFormat.COMPRESSED_RGBA_S3TC_DXT3_EXT: 39 | case TextureDataFormat.COMPRESSED_RGBA_S3TC_DXT5_EXT: 40 | case TextureDataFormat.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 41 | case TextureDataFormat.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 42 | case TextureDataFormat.COMPRESSED_RGB_PVRTC_2BPPV1_IMG: 43 | case TextureDataFormat.COMPRESSED_RGB_PVRTC_4BPPV1_IMG: 44 | case TextureDataFormat.COMPRESSED_RGB_S3TC_DXT1_EXT: 45 | case TextureDataFormat.COMPRESSED_SIGNED_R11_EAC: 46 | case TextureDataFormat.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 47 | case TextureDataFormat.COMPRESSED_SIGNED_RED_RGTC1_EXT: 48 | case TextureDataFormat.COMPRESSED_SIGNED_RG11_EAC: 49 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: 50 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: 51 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: 52 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: 53 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: 54 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: 55 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: 56 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: 57 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: 58 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: 59 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: 60 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: 61 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: 62 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: 63 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 64 | case TextureDataFormat.COMPRESSED_SRGB8_ETC2: 65 | case TextureDataFormat.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 66 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 67 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 68 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 69 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 70 | case TextureDataFormat.COMPRESSED_SRGB_S3TC_DXT1_EXT: 71 | return true; 72 | default: 73 | return false; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/MatrixUniform16.ts: -------------------------------------------------------------------------------- 1 | import MatrixUniform from "./MatrixUniform.js"; 2 | import type Program from "../../Program.js"; 3 | 4 | /** 5 | * A sixteen-value matrix global variable in a shader program. 6 | * @internal 7 | */ 8 | export default abstract class MatrixUniform16 extends MatrixUniform { 9 | /** 10 | * Create a scalar uniform. 11 | * @param program - The shader program that the uniform belongs to. 12 | * @param activeInfo - The information of the uniform. 13 | * @throws {@link UnsupportedOperationError} if the location of the uniform cannot be retrieved. 14 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getUniformLocation | getUniformLocation} 15 | * @internal 16 | */ 17 | public constructor(program: Program, activeInfo: WebGLActiveInfo) { 18 | super(program, activeInfo); 19 | this.valueCache = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 20 | this.matrixValueCache = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 21 | } 22 | 23 | /** 24 | * The value that is stored in this matrix uniform. 25 | * @internal 26 | */ 27 | protected matrixValueCache: [ 28 | number, 29 | number, 30 | number, 31 | number, 32 | number, 33 | number, 34 | number, 35 | number, 36 | number, 37 | number, 38 | number, 39 | number, 40 | number, 41 | number, 42 | number, 43 | number 44 | ]; 45 | 46 | /** 47 | * Set the value of this uniform if the value is iterable. 48 | * @param value - The value to pass to the uniform. 49 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 50 | * @internal 51 | */ 52 | public override iterableSetter(value: Iterable): void { 53 | // Can only accept sixteen values. 54 | const [ 55 | i0, 56 | i1, 57 | i2, 58 | i3, 59 | i4, 60 | i5, 61 | i6, 62 | i7, 63 | i8, 64 | i9, 65 | i10, 66 | i11, 67 | i12, 68 | i13, 69 | i14, 70 | i15 71 | ] = [...value]; 72 | if ( 73 | (i0 === this.matrixValueCache[0] && 74 | i1 === this.matrixValueCache[1] && 75 | i2 === this.matrixValueCache[2] && 76 | i3 === this.matrixValueCache[3] && 77 | i4 === this.matrixValueCache[4] && 78 | i5 === this.matrixValueCache[5] && 79 | i6 === this.matrixValueCache[6] && 80 | i7 === this.matrixValueCache[7] && 81 | i8 === this.matrixValueCache[8] && 82 | i9 === this.matrixValueCache[9] && 83 | i10 === this.matrixValueCache[10] && 84 | i11 === this.matrixValueCache[11] && 85 | i12 === this.matrixValueCache[12] && 86 | i13 === this.matrixValueCache[13] && 87 | i14 === this.matrixValueCache[14] && 88 | i15 === this.matrixValueCache[15]) || 89 | typeof i0 === "undefined" || 90 | typeof i1 === "undefined" || 91 | typeof i2 === "undefined" || 92 | typeof i3 === "undefined" || 93 | typeof i4 === "undefined" || 94 | typeof i5 === "undefined" || 95 | typeof i6 === "undefined" || 96 | typeof i7 === "undefined" || 97 | typeof i8 === "undefined" || 98 | typeof i9 === "undefined" || 99 | typeof i10 === "undefined" || 100 | typeof i11 === "undefined" || 101 | typeof i12 === "undefined" || 102 | typeof i13 === "undefined" || 103 | typeof i14 === "undefined" || 104 | typeof i15 === "undefined" 105 | ) { 106 | return; 107 | } 108 | 109 | this.iterableSetterInternal(value); 110 | this.matrixValueCache = [ 111 | i0, 112 | i1, 113 | i2, 114 | i3, 115 | i4, 116 | i5, 117 | i6, 118 | i7, 119 | i8, 120 | i9, 121 | i10, 122 | i11, 123 | i12, 124 | i13, 125 | i14, 126 | i15 127 | ]; 128 | } 129 | 130 | /** 131 | * Set the value of this uniform if the value is iterable. 132 | * @param value - The value to pass to the uniform. 133 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/uniform | uniform[1234][uif][v]} 134 | * @internal 135 | */ 136 | public abstract iterableSetterInternal(value: Iterable): void; 137 | } 138 | -------------------------------------------------------------------------------- /src/constants/RenderbufferFormat.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Formats for a renderbuffer. 3 | * @public 4 | */ 5 | enum RenderbufferFormat { 6 | /** 4 bits each for red, green, blue, and alpha. */ 7 | RGBA4 = 0x8056, 8 | 9 | /** 5 red bits, 6 green bits, and 5 blue bits. */ 10 | RGB565 = 0x8d62, 11 | 12 | /** 5 bits each for red, green, and blue, and 1 bit for alpha. */ 13 | RGB5_A1 = 0x8057, 14 | 15 | /** 16 depth bits. */ 16 | DEPTH_COMPONENT16 = 0x81a5, 17 | 18 | /** 8 stencil bits. */ 19 | STENCIL_INDEX8 = 0x8d48, 20 | 21 | /** A depth stencil. */ 22 | DEPTH_STENCIL = 0x84f9, 23 | 24 | /** 8 red bits. */ 25 | R8 = 0x8229, 26 | 27 | /** An 8-bit unsigned integer for red. */ 28 | R8UI = 0x8232, 29 | 30 | /** An 8-bit integer for red. */ 31 | R8I = 0x8231, 32 | 33 | /** A 16-bit unsigned integer for red. */ 34 | R16UI = 0x8234, 35 | 36 | /** A 16-bit integer for red. */ 37 | R16I = 0x8233, 38 | 39 | /** A 32-bit unsigned integer for red. */ 40 | R32UI = 0x8236, 41 | 42 | /** A 32-bit integer for red. */ 43 | R32I = 0x8235, 44 | 45 | /** 8 bits each for red and green. */ 46 | RG8 = 0x822b, 47 | 48 | /** An 8-bit unsigned integer each for red and green. */ 49 | RG8UI = 0x8238, 50 | 51 | /** An 8-bit integer each for red and green. */ 52 | RG8I = 0x8237, 53 | 54 | /** A 16-bit unsigned integer each for red and green. */ 55 | RG16UI = 0x823a, 56 | 57 | /** A 16-bit integer each for red and green. */ 58 | RG16I = 0x8239, 59 | 60 | /** A 32-bit unsigned integer each for red and green. */ 61 | RG32UI = 0x823c, 62 | 63 | /** A 32-bit integer each for red and green. */ 64 | RG32I = 0x823b, 65 | 66 | /** 8 bits each for red, green, and blue. */ 67 | RGB8 = 0x8051, 68 | 69 | /** 8 bits each for red, green, blue, and alpha. */ 70 | RGBA8 = 0x8058, 71 | 72 | /** 8 bits each for red, green, blue, and alpha. */ 73 | SRGB8_ALPHA8 = 0x8c43, 74 | 75 | /** 10 bits each for red, green, and blue, and 2 bits for alpha. */ 76 | RGB10_A2 = 0x8059, 77 | 78 | /** An 8-bit unsigned integer each for red, green, blue, and alpha. */ 79 | RGBA8UI = 0x8d7c, 80 | 81 | /** An 8-bit integer each for red, green, blue, and alpha. */ 82 | RGBA8I = 0x8d8e, 83 | 84 | /** A 10-bit unsigned integer each for red, green, and blue, and a 2-bit unsigned integer for alpha. */ 85 | RGB10_A2UI = 0x906f, 86 | 87 | /** A 16-bit unsigned integer each for red, green, blue, and alpha. */ 88 | RGBA16UI = 0x8d76, 89 | 90 | /** A 16-bit integer each for red, green, blue, and alpha. */ 91 | RGBA16I = 0x8d88, 92 | 93 | /** A 32-bit integer each for red, green, blue, and alpha. */ 94 | RGBA32I = 0x8d82, 95 | 96 | /** A 32-bit unsigned integer each for red, green, blue, and alpha. */ 97 | RGBA32UI = 0x8d70, 98 | 99 | /** 24 bits for depth. */ 100 | DEPTH_COMPONENT24 = 0x81a6, 101 | 102 | /** A 32-bit floating-point number for depth. */ 103 | DEPTH_COMPONENT32F = 0x8cac, 104 | 105 | /** 24 bits for depth and 8 bits for stencil. */ 106 | DEPTH24_STENCIL8 = 0x88f0, 107 | 108 | /** A 32-bit floating-point number for depth and 8 bits for stencil. */ 109 | DEPTH32F_STENCIL8 = 0x8cad, 110 | 111 | /** 112 | * A 32-bit floating-point number each for red, green, and blue. 113 | * @deprecated Use the constant from {@link Extension.ExtColorBufferFloat} instead. 114 | */ 115 | RGB32F_EXT = 0x8815, 116 | 117 | /** A 16-bit floating-point number for red. */ 118 | R16F = 0x822d, 119 | 120 | /** A 16-bit floating-point number each for red and green. */ 121 | RG16F = 0x822f, 122 | 123 | /** A 16-bit floating-point number each for red, green, blue, and alpha. */ 124 | RGBA16F = 0x881a, 125 | 126 | /** A 32-bit floating-point number for red. */ 127 | R32F = 0x822e, 128 | 129 | /** A 32-bit floating-point number each for red and green. */ 130 | RG32F = 0x8230, 131 | 132 | /** A 32-bit floating-point number each for red, green, blue, and alpha. */ 133 | RGBA32F = 0x8814, 134 | 135 | /** An 11-bit floating-point number each for red and green, and a 10-bit floating-point number for blue. */ 136 | R11F_G11F_B10F = 0x8c3a 137 | } 138 | 139 | export default RenderbufferFormat; 140 | -------------------------------------------------------------------------------- /src/utility/internal/getTextureDataTypesForTextureFormat.ts: -------------------------------------------------------------------------------- 1 | import TextureDataType from "../../constants/TextureDataType.js"; 2 | import TextureFormat from "../../constants/TextureFormat.js"; 3 | 4 | /** 5 | * Get a list of data types that can be supplied to the given texture internal format. 6 | * @param internalFormat - The texture internal format. 7 | * @returns A list of data types. The first data type in the list is a sensible default. 8 | * @internal 9 | */ 10 | export default function getTextureDataTypesForTextureFormat( 11 | internalFormat: TextureFormat 12 | ): TextureDataType[] { 13 | switch (internalFormat) { 14 | case TextureFormat.RGB: 15 | case TextureFormat.RGB565: 16 | return [ 17 | TextureDataType.UNSIGNED_BYTE, 18 | TextureDataType.UNSIGNED_SHORT_5_6_5 19 | ]; 20 | case TextureFormat.RGBA: 21 | return [ 22 | TextureDataType.UNSIGNED_BYTE, 23 | TextureDataType.UNSIGNED_SHORT_4_4_4_4, 24 | TextureDataType.UNSIGNED_SHORT_5_5_5_1 25 | ]; 26 | case TextureFormat.LUMINANCE_ALPHA: 27 | case TextureFormat.LUMINANCE: 28 | case TextureFormat.ALPHA: 29 | case TextureFormat.R8: 30 | case TextureFormat.R8UI: 31 | case TextureFormat.RG8: 32 | case TextureFormat.RG8UI: 33 | case TextureFormat.RGB8: 34 | case TextureFormat.SRGB8: 35 | case TextureFormat.RGB8UI: 36 | case TextureFormat.RGBA8: 37 | case TextureFormat.SRGB8_ALPHA8: 38 | case TextureFormat.RGBA8UI: 39 | return [TextureDataType.UNSIGNED_BYTE]; 40 | case TextureFormat.R8_SNORM: 41 | case TextureFormat.R8I: 42 | case TextureFormat.RG8_SNORM: 43 | case TextureFormat.RG8I: 44 | case TextureFormat.RGB8_SNORM: 45 | case TextureFormat.RGB8I: 46 | case TextureFormat.RGBA8_SNORM: 47 | case TextureFormat.RGBA8I: 48 | return [TextureDataType.BYTE]; 49 | case TextureFormat.R16F: 50 | case TextureFormat.RG16F: 51 | case TextureFormat.RGB16F: 52 | case TextureFormat.RGBA16F: 53 | return [TextureDataType.FLOAT, TextureDataType.HALF_FLOAT]; 54 | case TextureFormat.R32F: 55 | case TextureFormat.RG32F: 56 | case TextureFormat.RGB32F: 57 | case TextureFormat.RGBA32F: 58 | case TextureFormat.DEPTH_COMPONENT32F: 59 | return [TextureDataType.FLOAT]; 60 | case TextureFormat.R16UI: 61 | case TextureFormat.RG16UI: 62 | case TextureFormat.RGB16UI: 63 | case TextureFormat.RGBA16UI: 64 | return [TextureDataType.UNSIGNED_SHORT]; 65 | case TextureFormat.R16I: 66 | case TextureFormat.RG16I: 67 | case TextureFormat.RGB16I: 68 | case TextureFormat.RGBA16I: 69 | return [TextureDataType.SHORT]; 70 | case TextureFormat.R32UI: 71 | case TextureFormat.RG32UI: 72 | case TextureFormat.RGB32UI: 73 | case TextureFormat.RGBA32UI: 74 | case TextureFormat.DEPTH_COMPONENT24: 75 | return [TextureDataType.UNSIGNED_INT]; 76 | case TextureFormat.R32I: 77 | case TextureFormat.RG32I: 78 | case TextureFormat.RGB32I: 79 | case TextureFormat.RGBA32I: 80 | return [TextureDataType.INT]; 81 | case TextureFormat.R11F_G11F_B10F: 82 | return [ 83 | TextureDataType.FLOAT, 84 | TextureDataType.UNSIGNED_INT_10F_11F_11F_REV, 85 | TextureDataType.HALF_FLOAT 86 | ]; 87 | case TextureFormat.RGB9_E5: 88 | return [ 89 | TextureDataType.FLOAT, 90 | TextureDataType.UNSIGNED_INT_5_9_9_9_REV, 91 | TextureDataType.HALF_FLOAT 92 | ]; 93 | case TextureFormat.RGB5_A1: 94 | return [ 95 | TextureDataType.UNSIGNED_BYTE, 96 | TextureDataType.UNSIGNED_SHORT_5_5_5_1, 97 | TextureDataType.UNSIGNED_INT_2_10_10_10_REV 98 | ]; 99 | case TextureFormat.RGBA4: 100 | return [ 101 | TextureDataType.UNSIGNED_BYTE, 102 | TextureDataType.UNSIGNED_SHORT_4_4_4_4 103 | ]; 104 | case TextureFormat.RGB10_A2: 105 | case TextureFormat.RGB10_A2UI: 106 | return [TextureDataType.UNSIGNED_INT_2_10_10_10_REV]; 107 | case TextureFormat.DEPTH_COMPONENT16: 108 | return [TextureDataType.UNSIGNED_SHORT, TextureDataType.UNSIGNED_INT]; 109 | case TextureFormat.DEPTH24_STENCIL8: 110 | return [TextureDataType.UNSIGNED_INT_24_8]; 111 | case TextureFormat.DEPTH32F_STENCIL8: 112 | return [TextureDataType.FLOAT_32_UNSIGNED_INT_24_8_REV]; 113 | default: 114 | return []; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/utility/internal/getExtensionForTextureFormat.ts: -------------------------------------------------------------------------------- 1 | import Extension from "../../constants/Extension.js"; 2 | import TextureFormat from "../../constants/TextureFormat.js"; 3 | 4 | /** 5 | * Get the extension that is associated with the given texture internal format. 6 | * @param format - The texture internal format. 7 | * @returns The extension that is associated with the texture internal format. 8 | * @internal 9 | */ 10 | export default function getExtensionForTextureFormat( 11 | format: TextureFormat 12 | ): Extension | null { 13 | switch (format) { 14 | case TextureFormat.COMPRESSED_RGB_S3TC_DXT1_EXT: 15 | case TextureFormat.COMPRESSED_RGBA_S3TC_DXT1_EXT: 16 | case TextureFormat.COMPRESSED_RGBA_S3TC_DXT3_EXT: 17 | case TextureFormat.COMPRESSED_RGBA_S3TC_DXT5_EXT: 18 | return Extension.CompressedTextureS3tc; 19 | case TextureFormat.COMPRESSED_SRGB_S3TC_DXT1_EXT: 20 | case TextureFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 21 | case TextureFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 22 | case TextureFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 23 | return Extension.CompressedTextureS3tcSrgb; 24 | case TextureFormat.COMPRESSED_R11_EAC: 25 | case TextureFormat.COMPRESSED_SIGNED_R11_EAC: 26 | case TextureFormat.COMPRESSED_RG11_EAC: 27 | case TextureFormat.COMPRESSED_SIGNED_RG11_EAC: 28 | case TextureFormat.COMPRESSED_RGB8_ETC2: 29 | case TextureFormat.COMPRESSED_RGBA8_ETC2_EAC: 30 | case TextureFormat.COMPRESSED_SRGB8_ETC2: 31 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 32 | case TextureFormat.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 33 | case TextureFormat.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 34 | return Extension.CompressedTextureEtc; 35 | case TextureFormat.COMPRESSED_RGB_PVRTC_4BPPV1_IMG: 36 | case TextureFormat.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: 37 | case TextureFormat.COMPRESSED_RGB_PVRTC_2BPPV1_IMG: 38 | case TextureFormat.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: 39 | return Extension.CompressedTexturePvrtc; 40 | case TextureFormat.COMPRESSED_RGBA_ASTC_4x4_KHR: 41 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: 42 | case TextureFormat.COMPRESSED_RGBA_ASTC_5x4_KHR: 43 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: 44 | case TextureFormat.COMPRESSED_RGBA_ASTC_5x5_KHR: 45 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: 46 | case TextureFormat.COMPRESSED_RGBA_ASTC_6x5_KHR: 47 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: 48 | case TextureFormat.COMPRESSED_RGBA_ASTC_6x6_KHR: 49 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: 50 | case TextureFormat.COMPRESSED_RGBA_ASTC_8x5_KHR: 51 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: 52 | case TextureFormat.COMPRESSED_RGBA_ASTC_8x6_KHR: 53 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: 54 | case TextureFormat.COMPRESSED_RGBA_ASTC_8x8_KHR: 55 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: 56 | case TextureFormat.COMPRESSED_RGBA_ASTC_10x5_KHR: 57 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: 58 | case TextureFormat.COMPRESSED_RGBA_ASTC_10x6_KHR: 59 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: 60 | case TextureFormat.COMPRESSED_RGBA_ASTC_10x8_KHR: 61 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: 62 | case TextureFormat.COMPRESSED_RGBA_ASTC_10x10_KHR: 63 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: 64 | case TextureFormat.COMPRESSED_RGBA_ASTC_12x10_KHR: 65 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: 66 | case TextureFormat.COMPRESSED_RGBA_ASTC_12x12_KHR: 67 | case TextureFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: 68 | return Extension.CompressedTextureAstc; 69 | case TextureFormat.COMPRESSED_RGBA_BPTC_UNORM_EXT: 70 | case TextureFormat.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 71 | case TextureFormat.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 72 | case TextureFormat.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 73 | return Extension.TextureCompressionBptc; 74 | case TextureFormat.COMPRESSED_RED_RGTC1_EXT: 75 | case TextureFormat.COMPRESSED_SIGNED_RED_RGTC1_EXT: 76 | case TextureFormat.COMPRESSED_RED_GREEN_RGTC2_EXT: 77 | case TextureFormat.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 78 | return Extension.TextureCompressionRgtc; 79 | default: 80 | return null; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/01-attributes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Attributes 6 | 7 | 8 | 9 | 10 | 11 | 12 | 134 | 135 | 136 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /src/utility/internal/getChannelsForTextureFormat.ts: -------------------------------------------------------------------------------- 1 | import TextureDataFormat from "../../constants/TextureDataFormat.js"; 2 | 3 | /** 4 | * Get the number of channels for a texture format. 5 | * @param format - The format. 6 | * @returns The texture format. 7 | * @internal 8 | */ 9 | export default function getChannelsForTextureFormat( 10 | format: TextureDataFormat 11 | ): 1 | 2 | 3 | 4 { 12 | switch (format) { 13 | case TextureDataFormat.ALPHA: 14 | case TextureDataFormat.COMPRESSED_R11_EAC: 15 | case TextureDataFormat.COMPRESSED_RED_RGTC1_EXT: 16 | case TextureDataFormat.COMPRESSED_SIGNED_R11_EAC: 17 | case TextureDataFormat.COMPRESSED_SIGNED_RED_RGTC1_EXT: 18 | case TextureDataFormat.DEPTH_COMPONENT: 19 | case TextureDataFormat.LUMINANCE: 20 | case TextureDataFormat.RED: 21 | case TextureDataFormat.RED_INTEGER: 22 | return 1; 23 | case TextureDataFormat.COMPRESSED_RED_GREEN_RGTC2_EXT: 24 | case TextureDataFormat.COMPRESSED_RG11_EAC: 25 | case TextureDataFormat.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT: 26 | case TextureDataFormat.COMPRESSED_SIGNED_RG11_EAC: 27 | case TextureDataFormat.DEPTH_STENCIL: 28 | case TextureDataFormat.LUMINANCE_ALPHA: 29 | case TextureDataFormat.RG: 30 | case TextureDataFormat.RG_INTEGER: 31 | return 2; 32 | case TextureDataFormat.COMPRESSED_RGB8_ETC2: 33 | case TextureDataFormat.COMPRESSED_RGBA8_ETC2_EAC: 34 | case TextureDataFormat.COMPRESSED_RGB_PVRTC_2BPPV1_IMG: 35 | case TextureDataFormat.COMPRESSED_RGB_PVRTC_4BPPV1_IMG: 36 | case TextureDataFormat.COMPRESSED_RGB_S3TC_DXT1_EXT: 37 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 38 | case TextureDataFormat.COMPRESSED_SRGB8_ETC2: 39 | case TextureDataFormat.COMPRESSED_SRGB_S3TC_DXT1_EXT: 40 | case TextureDataFormat.RGB: 41 | case TextureDataFormat.RGB_INTEGER: 42 | case TextureDataFormat.SRGB: 43 | return 3; 44 | case TextureDataFormat.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 45 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x10_KHR: 46 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x5_KHR: 47 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x6_KHR: 48 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_10x8_KHR: 49 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_12x10_KHR: 50 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_12x12_KHR: 51 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_4x4_KHR: 52 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_5x4_KHR: 53 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_5x5_KHR: 54 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_6x5_KHR: 55 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_6x6_KHR: 56 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_8x5_KHR: 57 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_8x6_KHR: 58 | case TextureDataFormat.COMPRESSED_RGBA_ASTC_8x8_KHR: 59 | case TextureDataFormat.COMPRESSED_RGBA_BPTC_UNORM_EXT: 60 | case TextureDataFormat.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: 61 | case TextureDataFormat.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: 62 | case TextureDataFormat.COMPRESSED_RGBA_S3TC_DXT1_EXT: 63 | case TextureDataFormat.COMPRESSED_RGBA_S3TC_DXT3_EXT: 64 | case TextureDataFormat.COMPRESSED_RGBA_S3TC_DXT5_EXT: 65 | case TextureDataFormat.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT: 66 | case TextureDataFormat.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT: 67 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: 68 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: 69 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: 70 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: 71 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: 72 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: 73 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: 74 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: 75 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: 76 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: 77 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: 78 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: 79 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: 80 | case TextureDataFormat.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: 81 | case TextureDataFormat.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 82 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT: 83 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 84 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 85 | case TextureDataFormat.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 86 | case TextureDataFormat.RGBA: 87 | case TextureDataFormat.RGBA_INTEGER: 88 | case TextureDataFormat.SRGB_ALPHA: 89 | return 4; 90 | default: 91 | return format; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /test/02-indices.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Indices 6 | 7 | 8 | 9 | 10 | 11 | 12 | 145 | 146 | 147 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /test/03-uniforms.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Uniforms 6 | 7 | 8 | 9 | 10 | 11 | 12 | 149 | 150 | 151 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /src/core/Sync.ts: -------------------------------------------------------------------------------- 1 | import { 2 | OBJECT_TYPE, 3 | SYNC_CONDITION, 4 | SYNC_FENCE, 5 | SYNC_FLAGS, 6 | SYNC_FLUSH_COMMANDS_BIT, 7 | SYNC_GPU_COMMANDS_COMPLETE, 8 | SYNC_STATUS, 9 | TIMEOUT_IGNORED 10 | } from "../constants/constants.js"; 11 | import BadValueError from "../utility/BadValueError.js"; 12 | import type Context from "./Context.js"; 13 | import ContextDependent from "./internal/ContextDependent.js"; 14 | import SyncClientStatus from "../constants/SyncClientStatus.js"; 15 | import type SyncStatus from "../constants/SyncStatus.js"; 16 | import UnsupportedOperationError from "../utility/UnsupportedOperationError.js"; 17 | 18 | /** 19 | * A sync object. 20 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLSync | WebGLSync} 21 | * @public 22 | */ 23 | export default class Sync extends ContextDependent { 24 | /** 25 | * Create a sync object. 26 | * @param context - The rendering context. 27 | * @throws {@link UnsupportedOperationError} if the sync object can't be created. 28 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/fenceSync | fenceSync} 29 | */ 30 | public constructor(context: Context) { 31 | super(context); 32 | 33 | const internal = this.gl.fenceSync(SYNC_GPU_COMMANDS_COMPLETE, 0); 34 | if (!internal) { 35 | throw new UnsupportedOperationError( 36 | "The environment does not support sync objects." 37 | ); 38 | } 39 | 40 | this.internal = internal; 41 | } 42 | 43 | private internal: WebGLSync; 44 | 45 | /** Whether or not this is a valid sync object. */ 46 | public get isValid(): boolean { 47 | return this.gl.isSync(this.internal); 48 | } 49 | 50 | /** The type of this sync object. Always `SYNC_FENCE`. */ 51 | public get type(): typeof SYNC_FENCE { 52 | return this.context.doPrefillCache ? 53 | SYNC_FENCE 54 | : (this.gl.getSyncParameter( 55 | this.internal, 56 | OBJECT_TYPE 57 | ) as typeof SYNC_FENCE); 58 | } 59 | 60 | /** The status of this sync object. */ 61 | public get status(): SyncStatus { 62 | return this.gl.getSyncParameter(this.internal, SYNC_STATUS) as SyncStatus; 63 | } 64 | 65 | /** The condition of this sync object. Always `SYNC_GPU_COMMANDS_COMPLETE`. */ 66 | public get condition(): typeof SYNC_GPU_COMMANDS_COMPLETE { 67 | return this.context.doPrefillCache ? 68 | SYNC_GPU_COMMANDS_COMPLETE 69 | : (this.gl.getSyncParameter( 70 | this.internal, 71 | SYNC_CONDITION 72 | ) as typeof SYNC_GPU_COMMANDS_COMPLETE); 73 | } 74 | 75 | /** The flags with which this sync object was created. Always `0` since no flags are supported. */ 76 | public get flags(): 0 { 77 | return this.context.doPrefillCache ? 78 | 0 79 | : (this.gl.getSyncParameter(this.internal, SYNC_FLAGS) as 0); 80 | } 81 | 82 | /** 83 | * Wait on the client for this sync object to become signaled or for the given timeout to be passed. 84 | * @param flush - Whether or not to flush commands. 85 | * @param timeout - The timeout in nanoseconds to wait for the sync object to become signaled. 86 | * @returns This sync object's status. 87 | * @throws {@link BadValueError} if `timeout` exceeds the maximum client wait timeout. 88 | */ 89 | public clientWait(flush = false, timeout = 0): SyncClientStatus { 90 | if (timeout > this.context.maxClientWaitTimeout) { 91 | throw new BadValueError( 92 | `Sync object client wait timeout may not exceed ${this.context.maxClientWaitTimeout.toString()}.` 93 | ); 94 | } 95 | 96 | this.gl.flush(); 97 | return this.gl.clientWaitSync( 98 | this.internal, 99 | flush ? SYNC_FLUSH_COMMANDS_BIT : 0, 100 | timeout 101 | ); 102 | } 103 | 104 | /** 105 | * Client wait until passing. 106 | * @param flush - Whether or not to flush commands. 107 | * @param timeout - The timeout in nanoseconds to wait for the sync object to become signaled. 108 | * @returns The sync object's status. 109 | * @throws {@link BadValueError} if `timeout` exceeds the maximum client wait timeout. 110 | */ 111 | public async clientWaitUntil( 112 | flush?: boolean, 113 | timeout?: number 114 | ): Promise { 115 | return new Promise((resolve) => { 116 | const f = () => { 117 | const out = this.clientWait(flush, timeout); 118 | 119 | // If the timeout expired, try again next update. 120 | if (out === SyncClientStatus.TIMEOUT_EXPIRED) { 121 | setTimeout(f); 122 | return; 123 | } 124 | 125 | // Otherwise, return the status. 126 | resolve(out); 127 | }; 128 | setTimeout(f); 129 | }); 130 | } 131 | 132 | /** 133 | * Wait on the GL server for this sync object to become signaled. 134 | * @returns This sync object's status. 135 | */ 136 | public wait(): void { 137 | this.gl.flush(); 138 | this.gl.waitSync(this.internal, 0, TIMEOUT_IGNORED); 139 | } 140 | 141 | /** 142 | * Delete this sync object. 143 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/deleteSync | deleteSync} 144 | */ 145 | public delete(): void { 146 | this.gl.deleteSync(this.internal); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/core/Renderbuffer.ts: -------------------------------------------------------------------------------- 1 | import { RENDERBUFFER, RENDERBUFFER_BINDING } from "../constants/constants.js"; 2 | import Context from "./Context.js"; 3 | import ContextDependent from "./internal/ContextDependent.js"; 4 | import type RenderbufferFormat from "../constants/RenderbufferFormat.js"; 5 | import getExtensionForRenderbufferFormat from "../utility/internal/getExtensionForRenderbufferFormat.js"; 6 | 7 | /** 8 | * An object that contains an image and is optimized as a rendering target. 9 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer | WebGLRenderbuffer} 10 | * @public 11 | */ 12 | export default class Renderbuffer extends ContextDependent { 13 | /** 14 | * The currently-bound renderbuffer cache. 15 | * @internal 16 | */ 17 | private static bindingsCache = new Map< 18 | WebGL2RenderingContext, 19 | WebGLRenderbuffer | null 20 | >(); 21 | 22 | /** 23 | * Get the currently-bound renderbuffer. 24 | * @param context - The rendering context. 25 | * @returns The renderbuffer. 26 | * @internal 27 | */ 28 | public static getBound(context: Context): WebGLRenderbuffer | null { 29 | // Get the bound renderbuffer. 30 | let boundRenderbuffer = Renderbuffer.bindingsCache.get(context.gl); 31 | if (typeof boundRenderbuffer === "undefined") { 32 | boundRenderbuffer = 33 | context.doPrefillCache ? null : ( 34 | (context.gl.getParameter( 35 | RENDERBUFFER_BINDING 36 | ) as WebGLRenderbuffer | null) 37 | ); 38 | Renderbuffer.bindingsCache.set(context.gl, boundRenderbuffer); 39 | } 40 | 41 | return boundRenderbuffer; 42 | } 43 | 44 | /** 45 | * Bind a renderbuffer. 46 | * @param context - The rendering context. 47 | * @param renderbuffer - The renderbuffer. 48 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindRenderbuffer | bindRenderbuffer} 49 | * @internal 50 | */ 51 | public static bindGl( 52 | context: Context, 53 | renderbuffer: WebGLRenderbuffer | null 54 | ): void { 55 | // Do nothing if the binding is already correct. 56 | if (Renderbuffer.getBound(context) === renderbuffer) { 57 | return; 58 | } 59 | 60 | // Bind the renderbuffer to the target. 61 | context.gl.bindRenderbuffer(RENDERBUFFER, renderbuffer); 62 | Renderbuffer.bindingsCache.set(context.gl, renderbuffer); 63 | } 64 | 65 | /** 66 | * Unbind the renderbuffer that is bound. 67 | * @param context - The rendering context. 68 | * @param renderbuffer - The renderbuffer to unbind, or `undefined` to unbind any renderbuffer. 69 | * @internal 70 | */ 71 | public static unbindGl( 72 | context: Context, 73 | renderbuffer?: WebGLRenderbuffer 74 | ): void { 75 | // Do nothing if the renderbuffer is already unbound. 76 | if (renderbuffer && Renderbuffer.getBound(context) !== renderbuffer) { 77 | return; 78 | } 79 | 80 | // Unbind the renderbuffer. 81 | Renderbuffer.bindGl(context, null); 82 | } 83 | 84 | /** 85 | * Create a renderbuffer. 86 | * @param context - The rendering context. 87 | * @param format - The format of the renderbuffer. 88 | * @param width - The width of the renderbuffer. 89 | * @param height - The height of the renderbuffer. 90 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/createRenderbuffer | createRenderbuffer} 91 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/renderbufferStorage | renderbufferStorage} 92 | */ 93 | public constructor( 94 | context: Context, 95 | format: RenderbufferFormat, 96 | width: number, 97 | height: number 98 | ) { 99 | super(context); 100 | 101 | this.internal = this.gl.createRenderbuffer(); 102 | 103 | // Enable the extension that is required for the given format, if any. 104 | const extension = getExtensionForRenderbufferFormat(format); 105 | if (extension) { 106 | this.context.enableExtension(extension); 107 | } 108 | 109 | this.bind(); 110 | this.gl.renderbufferStorage(RENDERBUFFER, format, width, height); 111 | this.format = format; 112 | this.width = width; 113 | this.height = height; 114 | } 115 | 116 | /** 117 | * The API interface of this renderbuffer. 118 | * @internal 119 | */ 120 | public readonly internal: WebGLRenderbuffer; 121 | 122 | /** The format of this renderbuffer. */ 123 | public readonly format: RenderbufferFormat; 124 | 125 | /** The width of this renderbuffer. */ 126 | public readonly width: number; 127 | 128 | /** The height of this renderbuffer. */ 129 | public readonly height: number; 130 | 131 | /** 132 | * Delete this renderbuffer. 133 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/deleteRenderbuffer | deleteRenderbuffer} 134 | */ 135 | public delete(): void { 136 | this.gl.deleteRenderbuffer(this.internal); 137 | } 138 | 139 | /** 140 | * Bind this renderbuffer. 141 | * @internal 142 | */ 143 | public bind(): void { 144 | Renderbuffer.bindGl(this.context, this.internal); 145 | } 146 | 147 | /** 148 | * Unbind this renderbuffer. 149 | * @internal 150 | */ 151 | public unbind(): void { 152 | Renderbuffer.unbindGl(this.context, this.internal); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // Constants 2 | export { default as BlendEquation } from "./constants/BlendEquation.js"; 3 | export { default as BlendFunction } from "./constants/BlendFunction.js"; 4 | export { default as BufferUsage } from "./constants/BufferUsage.js"; 5 | export { default as CubeFace } from "./constants/CubeFace.js"; 6 | export { default as DataType } from "./constants/DataType.js"; 7 | export { default as ErrorCode } from "./constants/ErrorCode.js"; 8 | export { default as Extension } from "./constants/Extension.js"; 9 | export { default as Face } from "./constants/Face.js"; 10 | export { default as FramebufferAttachment } from "./constants/FramebufferAttachment.js"; 11 | export { default as FramebufferStatus } from "./constants/FramebufferStatus.js"; 12 | export { default as Orientation } from "./constants/Orientation.js"; 13 | export { default as Primitive } from "./constants/Primitive.js"; 14 | export { default as RenderbufferFormat } from "./constants/RenderbufferFormat.js"; 15 | export { default as ShaderType } from "./constants/ShaderType.js"; 16 | export { default as SyncClientStatus } from "./constants/SyncClientStatus.js"; 17 | export { default as SyncStatus } from "./constants/SyncStatus.js"; 18 | export { default as TestFunction } from "./constants/TestFunction.js"; 19 | export { default as TextureCompareMode } from "./constants/TextureCompareMode.js"; 20 | export { default as TextureDataType } from "./constants/TextureDataType.js"; 21 | export { default as TextureFilter } from "./constants/TextureFilter.js"; 22 | export { default as TextureFormat } from "./constants/TextureFormat.js"; 23 | export { default as VariableType } from "./constants/VariableType.js"; 24 | export { default as WrapMode } from "./constants/WrapMode.js"; 25 | 26 | // Core - Buffers 27 | export { default as Buffer } from "./core/buffers/Buffer.js"; 28 | export { default as ElementBuffer } from "./core/buffers/ElementBuffer.js"; 29 | export { default as VertexBuffer } from "./core/buffers/VertexBuffer.js"; 30 | 31 | // Core - Internal 32 | export { default as ApiInterface } from "./core/internal/ApiInterface.js"; 33 | export { default as ContextDependent } from "./core/internal/ContextDependent.js"; 34 | 35 | // Core - Textures 36 | export { default as Texture } from "./core/textures/Texture.js"; 37 | export { default as Texture2d } from "./core/textures/Texture2d.js"; 38 | export { default as Texture2dArray } from "./core/textures/Texture2dArray.js"; 39 | export { default as Texture3d } from "./core/textures/Texture3d.js"; 40 | export { default as TextureCubemap } from "./core/textures/TextureCubemap.js"; 41 | 42 | // Core - Variables 43 | export { default as Attribute } from "./core/variables/attributes/Attribute.js"; 44 | export { default as Uniform } from "./core/variables/uniforms/Uniform.js"; 45 | export { default as Variable } from "./core/variables/Variable.js"; 46 | export { default as Varying } from "./core/variables/Varying.js"; 47 | 48 | // Core 49 | export { default as Context } from "./core/Context.js"; 50 | export { default as Framebuffer } from "./core/Framebuffer.js"; 51 | export { default as Program } from "./core/Program.js"; 52 | export { default as Renderbuffer } from "./core/Renderbuffer.js"; 53 | export { default as Shader } from "./core/Shader.js"; 54 | export { default as Sync } from "./core/Sync.js"; 55 | export { default as TransformFeedback } from "./core/TransformFeedback.js"; 56 | export { default as VertexArray } from "./core/VertexArray.js"; 57 | 58 | // Types 59 | export type { AttributeMap } from "./types/AttributeMap.js"; 60 | export type { default as AttributeValue } from "./types/AttributeValue.js"; 61 | export type { default as BlendEquationSet } from "./types/BlendEquationSet.js"; 62 | export type { default as BlendFunctionFullSet } from "./types/BlendFunctionFullSet.js"; 63 | export type { default as BlendFunctionSet } from "./types/BlendFunctionSet.js"; 64 | export type { default as Color } from "./types/Color.js"; 65 | export type { default as ColorMask } from "./types/ColorMask.js"; 66 | export type { default as DebugInfo } from "./types/DebugInfo.js"; 67 | export type { ExtensionObject } from "./types/ExtensionObject.js"; 68 | export type { default as Pair } from "./types/Pair.js"; 69 | export type { default as Prism } from "./types/Prism.js"; 70 | export type { default as Rectangle } from "./types/Rectangle.js"; 71 | export type { default as Stencil } from "./types/Stencil.js"; 72 | export type { UniformMap } from "./types/UniformMap.js"; 73 | export type { UniformValue } from "./types/UniformValue.js"; 74 | export type { VaryingMap } from "./types/VaryingMap.js"; 75 | export type { default as VaryingValue } from "./types/VaryingValue.js"; 76 | 77 | // Utility 78 | export { default as DuplicateContextError } from "./utility/DuplicateContextError.js"; 79 | export { default as BadValueError } from "./utility/BadValueError.js"; 80 | export { default as debug } from "./utility/debug.js"; 81 | export { default as ImmutableError } from "./utility/ImmutableError.js"; 82 | export { default as makeFullscreenCanvas } from "./utility/makeFullscreenCanvas.js"; 83 | export { default as ProgramLinkError } from "./utility/ProgramLinkError.js"; 84 | export { default as ShaderCompileError } from "./utility/ShaderCompileError.js"; 85 | export { default as TextureFormatError } from "./utility/TextureFormatError.js"; 86 | export { default as UnsupportedOperationError } from "./utility/UnsupportedOperationError.js"; 87 | export { default as WebglError } from "./utility/WebglError.js"; 88 | -------------------------------------------------------------------------------- /src/core/variables/uniforms/createUniform.ts: -------------------------------------------------------------------------------- 1 | import FloatMatrix2x2Uniform from "./FloatMatrix2x2Uniform.js"; 2 | import FloatMatrix2x3Uniform from "./FloatMatrix2x3Uniform.js"; 3 | import FloatMatrix2x4Uniform from "./FloatMatrix2x4Uniform.js"; 4 | import FloatMatrix3x2Uniform from "./FloatMatrix3x2Uniform.js"; 5 | import FloatMatrix3x3Uniform from "./FloatMatrix3x3Uniform.js"; 6 | import FloatMatrix3x4Uniform from "./FloatMatrix3x4Uniform.js"; 7 | import FloatMatrix4x2Uniform from "./FloatMatrix4x2Uniform.js"; 8 | import FloatMatrix4x3Uniform from "./FloatMatrix4x3Uniform.js"; 9 | import FloatMatrix4x4Uniform from "./FloatMatrix4x4Uniform.js"; 10 | import FloatUniform from "./FloatUniform.js"; 11 | import FloatVector2Uniform from "./FloatVector2Uniform.js"; 12 | import FloatVector3Uniform from "./FloatVector3Uniform.js"; 13 | import FloatVector4Uniform from "./FloatVector4Uniform.js"; 14 | import IntegerUniform from "./IntegerUniform.js"; 15 | import IntegerVector2Uniform from "./IntegerVector2Uniform.js"; 16 | import IntegerVector3Uniform from "./IntegerVector3Uniform.js"; 17 | import IntegerVector4Uniform from "./IntegerVector4Uniform.js"; 18 | import type Program from "../../Program.js"; 19 | import SamplerUniform from "./SamplerUniform.js"; 20 | import type Uniform from "./Uniform.js"; 21 | import UnsignedIntegerUniform from "./UnsignedIntegerUniform.js"; 22 | import UnsignedIntegerVector2Uniform from "./UnsignedIntegerVector2Uniform.js"; 23 | import UnsignedIntegerVector3Uniform from "./UnsignedIntegerVector3Uniform.js"; 24 | import UnsignedIntegerVector4Uniform from "./UnsignedIntegerVector4Uniform.js"; 25 | import UnsupportedOperationError from "../../../utility/UnsupportedOperationError.js"; 26 | import VariableType from "../../../constants/VariableType.js"; 27 | 28 | /** 29 | * Create a wrapper object for a uniform. 30 | * @param program - The shader program that the uniform belongs to. 31 | * @param index - The index of the uniform. 32 | * @returns The uniform. 33 | * @throws {@link UnsupportedOperationError} if the active information or location of the uniform cannot be retrieved. 34 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getActiveUniform | getActiveUniform} 35 | * @internal 36 | */ 37 | export default function createUniform( 38 | program: Program, 39 | index: number 40 | ): Uniform { 41 | const activeInfo = program.gl.getActiveUniform(program.internal, index); 42 | if (!activeInfo) { 43 | throw new UnsupportedOperationError( 44 | "The environment does not support active information." 45 | ); 46 | } 47 | 48 | switch (activeInfo.type as VariableType) { 49 | case VariableType.FLOAT: 50 | return new FloatUniform(program, activeInfo); 51 | case VariableType.FLOAT_VEC2: 52 | return new FloatVector2Uniform(program, activeInfo); 53 | case VariableType.FLOAT_VEC3: 54 | return new FloatVector3Uniform(program, activeInfo); 55 | case VariableType.FLOAT_VEC4: 56 | return new FloatVector4Uniform(program, activeInfo); 57 | case VariableType.SAMPLER_2D: 58 | case VariableType.SAMPLER_3D: 59 | case VariableType.SAMPLER_CUBE: 60 | case VariableType.SAMPLER_2D_SHADOW: 61 | case VariableType.SAMPLER_2D_ARRAY: 62 | case VariableType.SAMPLER_2D_ARRAY_SHADOW: 63 | case VariableType.SAMPLER_CUBE_SHADOW: 64 | case VariableType.INT_SAMPLER_2D: 65 | case VariableType.INT_SAMPLER_3D: 66 | case VariableType.INT_SAMPLER_CUBE: 67 | case VariableType.INT_SAMPLER_2D_ARRAY: 68 | return new SamplerUniform(program, activeInfo); 69 | case VariableType.BOOL: 70 | case VariableType.INT: 71 | return new IntegerUniform(program, activeInfo); 72 | case VariableType.BOOL_VEC2: 73 | case VariableType.INT_VEC2: 74 | return new IntegerVector2Uniform(program, activeInfo); 75 | case VariableType.BOOL_VEC3: 76 | case VariableType.INT_VEC3: 77 | return new IntegerVector3Uniform(program, activeInfo); 78 | case VariableType.BOOL_VEC4: 79 | case VariableType.INT_VEC4: 80 | return new IntegerVector4Uniform(program, activeInfo); 81 | case VariableType.UNSIGNED_INT: 82 | return new UnsignedIntegerUniform(program, activeInfo); 83 | case VariableType.UNSIGNED_INT_VEC2: 84 | return new UnsignedIntegerVector2Uniform(program, activeInfo); 85 | case VariableType.UNSIGNED_INT_VEC3: 86 | return new UnsignedIntegerVector3Uniform(program, activeInfo); 87 | case VariableType.UNSIGNED_INT_VEC4: 88 | return new UnsignedIntegerVector4Uniform(program, activeInfo); 89 | case VariableType.FLOAT_MAT2: 90 | return new FloatMatrix2x2Uniform(program, activeInfo); 91 | case VariableType.FLOAT_MAT3: 92 | return new FloatMatrix3x3Uniform(program, activeInfo); 93 | case VariableType.FLOAT_MAT4: 94 | return new FloatMatrix4x4Uniform(program, activeInfo); 95 | case VariableType.FLOAT_MAT2x3: 96 | return new FloatMatrix2x3Uniform(program, activeInfo); 97 | case VariableType.FLOAT_MAT2x4: 98 | return new FloatMatrix2x4Uniform(program, activeInfo); 99 | case VariableType.FLOAT_MAT3x2: 100 | return new FloatMatrix3x2Uniform(program, activeInfo); 101 | case VariableType.FLOAT_MAT3x4: 102 | return new FloatMatrix3x4Uniform(program, activeInfo); 103 | case VariableType.FLOAT_MAT4x2: 104 | return new FloatMatrix4x2Uniform(program, activeInfo); 105 | case VariableType.FLOAT_MAT4x3: 106 | default: // Not possible as long as this function is only called internally. 107 | return new FloatMatrix4x3Uniform(program, activeInfo); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/04-varyings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Varyings 6 | 7 | 8 | 9 | 10 | 11 | 12 | 165 | 166 | 167 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /src/core/buffers/Buffer.ts: -------------------------------------------------------------------------------- 1 | import { BUFFER_SIZE, BUFFER_USAGE } from "../../constants/constants.js"; 2 | import type BufferTarget from "../../constants/BufferTarget.js"; 3 | import type BufferUsage from "../../constants/BufferUsage.js"; 4 | import type Context from "../Context.js"; 5 | import ContextDependent from "../internal/ContextDependent.js"; 6 | import DataType from "../../constants/DataType.js"; 7 | 8 | /** 9 | * An array of binary data. 10 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer | WebGLBuffer} 11 | * @public 12 | */ 13 | export default abstract class Buffer< 14 | T extends ArrayBufferView = ArrayBufferView 15 | > extends ContextDependent { 16 | /** 17 | * Create a buffer. 18 | * @param context - The rendering context. 19 | * @param usage - The intended usage of the buffer. 20 | * @param offset - The index of the element to start reading the initial data at. 21 | * @param length - The length of the initial data to read into the buffer. 22 | * @param target - The target binding point of the buffer. 23 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/createBuffer | createBuffer} 24 | * @internal 25 | */ 26 | protected constructor(context: Context) { 27 | super(context); 28 | 29 | this.internal = this.gl.createBuffer(); 30 | this.isCacheValid = false; 31 | } 32 | 33 | /** 34 | * The API interface of this buffer. 35 | * @internal 36 | */ 37 | public readonly internal: WebGLBuffer; 38 | 39 | /** 40 | * The binding point of this buffer. 41 | * @internal 42 | */ 43 | public abstract get target(): BufferTarget; 44 | 45 | /** 46 | * The intended usage of this buffer. 47 | * @internal 48 | */ 49 | protected usageCache?: BufferUsage; 50 | 51 | /** The intended usage of this buffer. */ 52 | public get usage(): BufferUsage { 53 | if (this.usageCache) { 54 | return this.usageCache; 55 | } 56 | 57 | this.bind(); 58 | return (this.usageCache ??= this.gl.getBufferParameter( 59 | this.target, 60 | BUFFER_USAGE 61 | )); 62 | } 63 | 64 | /** 65 | * The data contained in this buffer. 66 | * @internal 67 | */ 68 | protected dataCache?: T; 69 | 70 | /** 71 | * Whether or not the data in the buffer cache hasn't been modified by μGL since it was last cached. 72 | * @internal 73 | */ 74 | protected isCacheValid: boolean; 75 | 76 | /** 77 | * The data contained in this buffer. 78 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/getBufferSubData | getBufferSubData} 79 | */ 80 | public abstract get data(): T; 81 | 82 | public abstract set data(value: T); 83 | 84 | /** 85 | * Clear this buffer's data cache. 86 | * @internal 87 | */ 88 | public clearDataCache(): void { 89 | this.isCacheValid = false; 90 | } 91 | 92 | /** 93 | * The type of the data in this buffer. 94 | * @internal 95 | */ 96 | protected typeCache?: DataType; 97 | 98 | /** The type of the data in this buffer. */ 99 | public get type(): DataType { 100 | return (this.typeCache ??= DataType.UNSIGNED_BYTE); 101 | } 102 | 103 | /** 104 | * The size of this buffer's data store in bytes. 105 | * @internal 106 | */ 107 | protected sizeCache?: number; 108 | 109 | /** The size of this buffer's data store in bytes. */ 110 | public get size(): number { 111 | if (typeof this.sizeCache === "number") { 112 | return this.sizeCache; 113 | } 114 | 115 | this.bind(); 116 | return (this.sizeCache ??= this.gl.getBufferParameter( 117 | this.target, 118 | BUFFER_SIZE 119 | )); 120 | } 121 | 122 | /** 123 | * Set the size of this buffer, clearing its data. 124 | * @param data - The size to set this buffer's data store to in bytes. 125 | * @param usage - The intended use case of the buffer. 126 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData | bufferData} 127 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferSubData | bufferSubData} 128 | */ 129 | public abstract setData(data: number, usage?: BufferUsage): void; 130 | 131 | /** 132 | * Replace all of or update a subset of the data in this buffer. 133 | * @param data - The data to store in this buffer. 134 | * @param usage - The intended use case of the buffer. 135 | * @param srcOffset - The index of the element to start reading the supplied data at. 136 | * @param length - The length of the supplied data to read. 137 | * @param dstOffset - The offset in bytes to start replacing data at. If this value is set, a subset of the data in the buffer is updated rather than replacing all of the data in the buffer and the usage pattern of the buffer is not updated. 138 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData | bufferData} 139 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferSubData | bufferSubData} 140 | */ 141 | public abstract setData( 142 | data: T, 143 | usage?: BufferUsage, 144 | srcOffset?: number, 145 | length?: number, 146 | dstOffset?: number 147 | ): void; 148 | 149 | /** 150 | * Delete this buffer. 151 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/deleteBuffer | deleteBuffer} 152 | */ 153 | public delete(): void { 154 | this.gl.deleteBuffer(this.internal); 155 | } 156 | 157 | /** 158 | * Bind this buffer to its binding point. 159 | * @internal 160 | */ 161 | public abstract bind(): void; 162 | 163 | /** 164 | * Unbind this buffer from its binding point. 165 | * @internal 166 | */ 167 | public abstract unbind(): void; 168 | } 169 | -------------------------------------------------------------------------------- /src/core/Shader.ts: -------------------------------------------------------------------------------- 1 | import { COMPILE_STATUS, SHADER_TYPE } from "../constants/constants.js"; 2 | import type Context from "./Context.js"; 3 | import ContextDependent from "./internal/ContextDependent.js"; 4 | import ShaderCompileError from "../utility/ShaderCompileError.js"; 5 | import type ShaderType from "../constants/ShaderType.js"; 6 | import UnsupportedOperationError from "../utility/UnsupportedOperationError.js"; 7 | 8 | /** 9 | * A WebGL2 shader. 10 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLShader | WebGLShader} 11 | * @public 12 | */ 13 | export default class Shader extends ContextDependent { 14 | /** 15 | * A map of WebGL shaders to existing `Shaders`. Used by `Program.prototype.getAttachedShaders`. 16 | * @internal 17 | */ 18 | public static existingShaders = new Map(); 19 | 20 | /** 21 | * Create a `Shader` or get an existing `Shader` if one already exists for the given `WebGLShader`. 22 | * @param context - The rendering context of the new shader if one must be created. 23 | * @param shader - The raw WebGL API shader. 24 | * @returns The corresponding `Shader`. 25 | * @internal 26 | */ 27 | public static get(context: Context, shader: WebGLShader): Shader { 28 | return Shader.existingShaders.get(shader) ?? new Shader(context, shader); 29 | } 30 | 31 | /** 32 | * Create a shader. 33 | * @param context - The rendering context. 34 | * @param shader - The raw WebGL API shader object. 35 | * @throws {@link UnsupportedOperationError} if a shader cannot be created. 36 | * @throws {@link ShaderCompileError} if the shader fails to compile. 37 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/createShader | createShader} 38 | * @internal 39 | */ 40 | public constructor(context: Context, shader: WebGLShader); 41 | 42 | /** 43 | * Create a shader. 44 | * @param context - The rendering context. 45 | * @param type - The type. 46 | * @param source - The source code of the shader. If supplied, the shader will automatically be compiled. 47 | * @throws {@link UnsupportedOperationError} if a shader cannot be created. 48 | * @throws {@link ShaderCompileError} if the shader fails to compile. 49 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/createShader | createShader} 50 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/shaderSource | shaderSource} 51 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/compileShader | compileShader} 52 | */ 53 | public constructor(context: Context, type: ShaderType, source?: string); 54 | 55 | public constructor( 56 | context: Context, 57 | type: ShaderType | WebGLShader, 58 | source?: string 59 | ) { 60 | super(context); 61 | 62 | if (type instanceof WebGLShader) { 63 | this.internal = type; 64 | } else { 65 | const shader = this.gl.createShader(type); 66 | if (!shader) { 67 | throw new UnsupportedOperationError( 68 | "The environment does not support shaders." 69 | ); 70 | } 71 | 72 | this.internal = shader; 73 | this.typeCache = type; 74 | 75 | // Compile the shader only if source code was given. 76 | if (!source) { 77 | return; 78 | } 79 | 80 | this.source = source; 81 | this.compile(); 82 | } 83 | 84 | Shader.existingShaders.set(this.internal, this); 85 | } 86 | 87 | /** 88 | * The API interface of this shader. 89 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLShader | WebGLShader} 90 | * @internal 91 | */ 92 | public readonly internal: WebGLShader; 93 | 94 | /** 95 | * The type of this shader. 96 | * @internal 97 | */ 98 | private typeCache?: ShaderType; 99 | 100 | public get type(): ShaderType { 101 | return (this.typeCache ??= this.gl.getShaderParameter( 102 | this.internal, 103 | SHADER_TYPE 104 | )); 105 | } 106 | 107 | /** 108 | * The source code of this shader. 109 | * @internal 110 | */ 111 | private sourceCache?: string | null; 112 | 113 | /** 114 | * The source code of this shader. 115 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/shaderSource | shaderSource} 116 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getShaderSource | getShaderSource} 117 | */ 118 | public get source(): string { 119 | return (this.sourceCache ??= this.gl.getShaderSource(this.internal) ?? ""); 120 | } 121 | 122 | public set source(value: string) { 123 | this.gl.shaderSource(this.internal, value); 124 | this.sourceCache = value; 125 | } 126 | 127 | /** 128 | * Compile this shader. 129 | * @throws {@link ShaderCompileError} if the shader fails to compile. 130 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/compileShader | compileShader} 131 | */ 132 | public compile(): void { 133 | this.gl.compileShader(this.internal); 134 | if (!this.compileStatus) { 135 | throw new ShaderCompileError(this.infoLog ?? void 0); 136 | } 137 | } 138 | 139 | /** The compilation status of this shader. */ 140 | public get compileStatus(): boolean { 141 | return this.gl.getShaderParameter(this.internal, COMPILE_STATUS) as boolean; 142 | } 143 | 144 | /** 145 | * The information log of this shader. 146 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getShaderInfoLog | getShaderInfoLog} 147 | */ 148 | public get infoLog(): string | null { 149 | return this.gl.getShaderInfoLog(this.internal); 150 | } 151 | 152 | /** 153 | * Delete this shader. 154 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/deleteShader | deleteShader} 155 | */ 156 | public delete(): void { 157 | this.gl.deleteShader(this.internal); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /test/05-matrices.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Matrices 6 | 7 | 8 | 9 | 10 | 11 | 12 | 181 | 182 | 183 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | --------------------------------------------------------------------------------