Skip to content
bigmistqkePublic

About

πŸ‘€ utilities for managing WebGL resources

Resources

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

137 Commits

Folders and files

Repository files navigation

πŸ‘οΈ @bigmistqke/view.gl

πŸ”§ Utilities for managing WebGL resources: uniforms, (interleaved) attributes and buffers.

  • schema-based resource management view-gl
  • compose schema and shader simultaneously via a tag template literal view-gl/tag

Table of Contents

πŸ“¦ Install

npm install @bigmistqke/view.gl
pnpm add @bigmistqke/view.gl
yarn add @bigmistqke/view.gl
bun add @bigmistqke/view.gl

πŸ‘οΈ view.gl

The view system provides type-safe WebGL resource management for uniforms and attributes

πŸš€ Basic Usage

const { uniforms, attributes } = view(gl, program, {
  uniforms: {
    time: { kind: 'float' },
    resolution: { kind: 'vec2' },
  },
  attributes: {
    position: { kind: 'vec3' },
    uv: { kind: 'vec2' },
  },
})

// Type-safe uniform setting
uniforms.time.set(performance.now())
uniforms.resolution.set(canvas.width, canvas.height)

// Attribute management
attributes.position.set(positionData)
attributes.position.bind()

πŸ‘οΈ view

The view() function creates type-safe WebGL resource managers from a schema.

const { uniforms, attributes } = view(gl, program, schema)

Parameters:

  • gl: WebGL rendering context
  • program: Compiled WebGL program
  • schema: see ViewSchema

Returns:

  • uniforms: Type-safe uniform setters
  • attributes: Attribute managers with buffer handling
  • dispose: Deletes everything the view made β€” see Disposal

πŸ“‹ ViewSchema

The complete schema object that defines all WebGL resources. Contains mappings for:

A buffer is the one schema member with no name in the source, so it is not resolved against the program the way a uniform or an attribute is β€” a buffer key is a label for the reader. What putting it in the schema decides is its lifetime, and that is the question worth answering at the declaration:

the buffer declare it disposed by
lives and dies with the view buffers: in the schema the view
outlives the view, or is shared between views a standalone bufferView you
belongs to somebody else name it on an attribute nobody β€” it is borrowed

An index buffer whose lifetime is its program's belongs in the schema, beside the attributes it is drawn with, on the one signal. A quad cached per context, or a buffer handed from one program's view to another's, is its own thing.

TypeScript Types
interface ViewSchema {
  uniforms: UniformSchema
  attributes: AttributeSchema
  interleavedAttributes: InterleavedAttributeSchema
}

πŸ—‘οΈ Disposal

Everything that creates a WebGL resource takes an AbortSignal and offers a dispose(), and the two are the same teardown reached two ways:

const controller = new AbortController()

const { view, dispose } = compile(gl, vertex, fragment, { signal: controller.signal })
const buffers = bufferView(gl, { indices: {} }, { signal: controller.signal })
const target = createFramebuffer(gl, definition, { signal: controller.signal })

controller.abort() // deletes the program, the buffers, the vertex arrays, the framebuffer

Two rules make this safe to reach for.

Only what it made. A resource handed in from outside is borrowed, never deleted: a buffer named by an attribute schema, a texture passed to createFramebuffer. Those belong to whoever created them, and the same buffer often feeds several views. Delete one out from under its owner and WebGL does not fault where it happened β€” the object survives while it is bound, so the handle is invalidated and the other view fails later, on its next upload.

Once. Every dispose() is idempotent. Disposing by hand and then aborting, or aborting twice, deletes each resource exactly once.

creates disposed by
view() its own attribute, layout and schema buffers, and vertex arrays still held from vao()
compile() the program, and its view
attributeView / interleavedAttributeView the buffer, unless the schema named one
bufferView its buffers
vaoView the vertex array, never its participants
createProgram the program
createTexture the texture
createFramebuffer the framebuffer, and the texture unless one was passed in

uniformView takes no signal: a uniform location is not a resource, so there is nothing to delete.

πŸ‘€ Resource Views

Each view type can be imported individually.

🎯 uniformView

Manages shader uniform variables.

const uniforms = uniformView(gl, program, {
  time: { kind: 'float' },
  lights: { kind: 'vec3', size: 8 }, // Array uniform: vec3[8]
  transform: { kind: 'mat4' },
})

uniforms.time.set(performance.now())
uniforms.lights.set(lightData) // Takes Float32Array for array uniforms
πŸ“‹ UniformSchema

A mapping of uniform names to their configuration.

  • kind: GLSL type (see Uniform Types for full list and WebGL compatibility)
  • size: Array size (optional) - converts uniform to array type
TypeScript Types
type UniformKind =
  | 'float'
  | 'int'
  | 'bool'
  | 'vec2'
  | 'vec3'
  | 'vec4'
  | 'ivec2'
  | 'ivec3'
  | 'ivec4'
  | 'bvec2'
  | 'bvec3'
  | 'bvec4'
  | 'mat2'
  | 'mat3'
  | 'mat4'
  | 'sampler2D'
  | 'samplerCube'

interface UniformDefinition {
  kind: UniformKind
  size?: number                               // Creates array uniform with Float32Array setter
}

type UniformSchema = Record<string | symbol, UniformDefinition>

πŸ“ attributeView

Manages vertex attributes with automatic buffer creation and binding.

const attributes = attributeView(gl, program, {
  position: { kind: 'vec3' },
  instanceOffset: { kind: 'vec2', instanced: true },
})

attributes.position.set(positionData).bind()
attributes.instanceOffset.set(instanceData).bind()

gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, 100)

bind() returns a disposer that restores the state it changed β€” here the instancing divisor, which belongs to the attribute location rather than to the program, and so is inherited by whatever binds there next. Ignore it when the view owns its locations for the lifetime of the program; call it when they are shared:

const unbind = attributes.instanceOffset.set(instanceData).bind()
gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, 100)
unbind()

A large buffer can be sized first and filled in parts, counting in elements of the attribute's format:

attributes.position.allocate(totalElements)   // sizes the buffer, contents undefined
attributes.position.write(chunk, offset)      // overwrites a range with bufferSubData
πŸ“‹ AttributeSchema

A mapping of attribute names to their configuration.

  • kind: GLSL type (see Attribute Types for full list and WebGL compatibility)
  • instanced: Boolean (optional) - enables instanced rendering
  • buffer: Custom WebGLBuffer (optional) - by default it gets created automatically during compilation
TypeScript Types
type AttributeKind =
  | 'float'
  | 'vec2'
  | 'vec3'
  | 'vec4'
  | 'mat2'
  | 'mat3'
  | 'mat4'
  | 'int'
  | 'ivec2'
  | 'ivec3'
  | 'ivec4'

interface AttributeDefinition {
  kind: AttributeKind
  instanced?: boolean                         // Enables vertexAttribDivisor
  buffer?: WebGLBuffer                        // Custom buffer, auto-created if not provided
}

type AttributeSchema = Record<string | symbol, AttributeDefinition>

πŸ”— interleavedAttributeView

Manages interleaved vertex data with automatic stride/offset calculation.

const interleavedAttributes = interleavedAttributeView(gl, program, {
  vertexData: {
    layout: [
      { key: 'position', kind: 'vec3' },
      { key: 'normal', kind: 'vec3' },
      { key: 'uv', kind: 'vec2' },
    ],
  },
})

interleavedAttributes.vertexData.buffer.set(interleavedVertexData)

Where vertex array objects are available bind() binds one, and it stays selected for every later draw β€” which would then write its own attributes into it. The disposer returned by bind() selects the previous array again:

const unbind = interleavedAttributes.vertexData.buffer.bind()
gl.drawElements(gl.TRIANGLES, count, gl.UNSIGNED_SHORT, 0)
unbind()

Whether the buffer steps once per vertex or once per instance is chosen per draw, not in the schema: buffer steps per vertex, buffer.perInstance per instance. constant sets the same layout as constant attribute values, for a draw that needs one set of values without a buffer.

A large buffer can be sized first and filled in parts, so it never has to exist whole in JavaScript. Both count in floats:

const { buffer } = interleavedAttributes.vertexData
buffer.allocate(totalFloats)             // sizes the buffer, contents undefined
buffer.write(chunk, offsetFloats)        // overwrites a range with bufferSubData
πŸ“‹ InterleavedAttributeSchema

A mapping of interleaved buffer names to their layout configuration. Each layout defines multiple attributes packed into a single buffer.

  • layout: Array of attribute definitions with key and kind (see Attribute Types)
TypeScript Types
interface InterleavedAttributeDefinition {
  layout: Array<{
    key: string | symbol
    kind: AttributeKind
  }>
}

type InterleavedAttributeSchema = Record<string | symbol, InterleavedAttributeDefinition>

πŸ—‚οΈ bufferView

Manages generic WebGL buffers.

const buffers = bufferView(gl, {
  indices: { target: 'ELEMENT_ARRAY_BUFFER' },
  data: { target: 'ARRAY_BUFFER', usage: 'DYNAMIC_DRAW' },
})

buffers.indices.set(indexData)
buffers.data.set(dynamicData)

const unbind = buffers.indices.bind()

// bind() returns a disposer restoring the previous binding for that target.
// Worth calling for ELEMENT_ARRAY_BUFFER, whose binding is recorded in the
// bound vertex array object.

A large buffer can be sized first and filled in parts. A buffer has no element type of its own, so these count in bytes:

buffers.data.allocate(byteLength)        // sizes the buffer, contents undefined
buffers.data.write(chunk, byteOffset)    // overwrites a range with bufferSubData
πŸ“‹ BufferSchema

A mapping of buffer names to their configuration. Each buffer has a target type and optional usage pattern.

  • target: Buffer target ('ARRAY_BUFFER', 'ELEMENT_ARRAY_BUFFER')
  • usage: Usage pattern ('STATIC_DRAW', 'DYNAMIC_DRAW', 'STREAM_DRAW')
TypeScript Types
interface BufferDefinition {
  target: 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER'
  usage?: 'STATIC_DRAW' | 'DYNAMIC_DRAW' | 'STREAM_DRAW' // Defaults to 'STATIC_DRAW'
}

type BufferSchema = Record<string | symbol, BufferDefinition>

🏷️ view.gl/tag

Type-safe GLSL template literals with automatic schema extraction and view creation.

  • Embedded Resources: Define uniforms, attributes, and interleaved layouts directly in GLSL
  • Type Inference: Automatically infers schema types and creates type-safe view
  • Unique Variables: Prevent naming collisions using symbols for unique shader variables
  • GLSL Composition: Compose reusable GLSL fragments with automatic dependency resolution

πŸš€ Basic Usage

const vertexShader = glsl`
  ${attribute.vec3('position')}
  ${uniform.mat4('model')}
  
  varying vec2 vUv;
  
  void main() {
    vUv = uv;
    gl_Position = model * vec4(position, 1.0);
  }
`

const fragmentShader = glsl`
  ${uniform.sampler2D('texture')}
  
  varying vec2 vUv;
  
  void main() {
    gl_FragColor = texture2D(texture, vUv);
  }
`

const { program, schema } = compile(gl, vertexShader, fragmentShader)

πŸ“ glsl

Template literal processor that handles GLSL code and embedded resources. Supports interpolation of:

  • Resource tags: uniform.*(), attribute.*(), interleave()
  • GLSL fragments: Reusable shader code snippets
  • Symbol Variables: Unique variable names to prevent collisions
  • Strings: Interpolated as-is into the shader code
  • Arrays: Arrays of any supported interpolation types
const precision = 'precision mediump float;'
const functionName = Symbol('function')

const shader = glsl`
  ${precision}                                // String interpolated as-is
  ${uniform.vec2('resolution')}
  ${[attribute.vec3('position'), attribute.vec2('uv')]}  // Array interpolation
  
  vec3 ${functionName}(vec2 uv) {             // Symbol interpolated to unique identifier
    return vec3(uv, 0.5);
  }
  
  void main() {
    gl_Position = vec4(position, 1.0);
  }
`

🧩 GLSL Fragment

Compose reusable GLSL code fragments to build complex shaders:

const lighting = glsl`
  vec3 calculateLighting(vec3 normal, vec3 lightDir) {
    float diff = max(dot(normal, lightDir), 0.0);
    return vec3(diff);
  }
`

const vertexShader = glsl`
  ${attribute.vec3('direction')}
  ${attribute.vec3('normal')}
  ${lighting}                                 // Include the lighting fragment
  
  varying vec3 vLighting;
  
  void main() {
    vLighting = calculateLighting(normal, direction);
  }
`

πŸ”’ Symbol Variables

Use JavaScript symbols to prevent naming collisions:

const sum = Symbol('sum')

const sumFragment = glsl`
float ${sum}(float a, float b){
  return a + b;
}`

const shader = glsl`
${sumFragment}

void main(){
  float result = ${sum}(1.0, 2.0);
}
`

Symbols are converted to unique identifiers during the compilation of the shader.

WebGL Version Support

The glsl-function supports both WebGL1 and WebGL2 syntax, automatically using the correct keywords for resource tags:

// WebGL1 (default)
const shader = glsl`
  ${attribute.vec3('position')}               // β†’ attribute vec3 position;
  varying vec2 vUv;
`

If the shader starts with #version 300 es, resource tags generate WebGL2 syntax:

// WebGL2
const shader = glsl`#version 300 es
  ${attribute.vec3('position')}               // β†’ in vec3 position;
  out vec2 vUv;
`

🏷️ Resource Tokens

Utilities for defining WebGL resources directly in GLSL templates. These create metadata that the compile consumes to generate the typesafe schema and view.

🎯 uniform[kind](name, options?)

Define uniform variables in GLSL templates (see Uniform Types).

const uniqueTime = Symbol('time')

const shader = glsl`
  ${uniform.float('time')}                    // String key
  ${uniform.float(uniqueTime)}                // Symbol key
  ${uniform.vec3('lights', { size: 8 })}      // Array uniform: vec3[8]
  
  void main() {
    float wave = sin(time * 2.0 + ${uniqueTime});
    vec3 totalLight = vec3(0.0);
    for(int i = 0; i < 8; i++) {
      totalLight += lights[i] * wave;
    }
    gl_FragColor = vec4(totalLight, 1.0);
  }
`

Parameters:

  • name: Uniform name (string or symbol for unique variables)
  • options: Optional configuration object
    • size: Array size (creates array uniform with Float32Array setter)

πŸ“ attribute[kind](name, options?)

Define vertex attributes in GLSL templates (see Attribute Types).

const uniquePosition = Symbol('position')

const vertexShader = glsl`
  ${attribute.vec3('position')}               // String key
  ${attribute.vec3(uniquePosition)}           // Symbol key
  ${attribute.vec2('offset', { instanced: true })}
  
  void main() {
    gl_Position = vec4(position + vec3(offset, 0.0), 1.0);
  }
`

Parameters:

  • name: Attribute name (string or symbol for unique variables)
  • options: Optional configuration object
    • instanced: Boolean - enables instanced rendering with vertexAttribDivisor
    • buffer: Custom WebGLBuffer (optional)

πŸ”— interleave(name, layout, options?)

Define interleaved attribute layouts for efficient vertex data.

const uniqueVertexData = Symbol('vertexData')
const uniquePosition = Symbol('position')

const vertexShader = glsl`
  ${interleave('vertexData', [
    // String key
    { key: 'position', kind: 'vec3' },
    { key: 'uv', kind: 'vec2' },
  ])}
  ${interleave(uniqueVertexData, [
    // Symbol key
    { key: uniquePosition, kind: 'vec3' },    // Symbol keys in layout
    { key: 'uv', kind: 'vec2' },
  ])}
  
  void main() {
    gl_Position = vec4(position + vec3(uv, 0.0), 1.0);
  }
`

Parameters:

  • name: Buffer name (string or symbol for unique variables)
  • layout: Array of attribute definitions
    • key: Attribute name (string or symbol for unique variables)
    • kind: GLSL type (see Attribute Types)
  • options: Optional configuration object
    • instanced: Boolean - applies vertexAttribDivisor to all attributes

βš™οΈ compile(gl, vertex, fragment, overrideSchema?)

Compiles shaders to a WebGLProgram and extracts typesafe schema and view.

πŸ”„ compile.toQuad(gl, fragment, options?)

Convenient helper for fullscreen quad rendering with fragment shaders. Automatically creates a vertex shader with a quad geometry and handles vertex buffer setup.

const { program, schema, view } = compile.toQuad(gl, fragmentShader)

// Ready to render - no vertex setup required
view.uniforms.time.set(performance.now())
gl.drawArrays(gl.TRIANGLES, 0, 6)

Perfect for:

  • Fragment shader effects (ray-marching, post-processing, etc.)
  • Fullscreen compute-style shaders
  • Quick prototyping and experimentation

Generated vertex shader:

  • Creates a_quad attribute automatically
  • Outputs uv varying (same as vertex position: [-1,1] range)
  • Sets up clip-space quad covering the entire screen

Parameters:

  • gl: WebGL rendering context
  • fragment: Fragment shader with embedded resources
  • options: Optional compilation options (same as compile())

Returns: Same as compile() with pre-configured quad rendering

const { program, schema, view, vertex, fragment } = compile(gl, vertexShader, fragmentShader)

// Use the view directly
view.uniforms.time.set(performance.now())
view.attributes.position.set(vertexData).bind()

// Access the compiled shader strings
console.log(vertex)                           // Compiled vertex shader GLSL
console.log(fragment)                         // Compiled fragment shader GLSL

// Or access the extracted schema
console.log(schema.uniforms)                  // { time: { kind: 'float' }, ... }
console.log(schema.attributes)                // { position: { kind: 'vec3' }, ... }

Override Schema:

You can provide an optional override schema to enhance or override the automatically extracted schema:

const { program, schema, view } = compile(gl, vertexShader, fragmentShader, {
  schema: {
    uniforms: {
      // Add additional uniforms not automatically inferred
      customTime: { kind: 'float' },
    },
  },
})

// The override schema is merged with the extracted schema
view.uniforms.customTime.set(123.45)

// An index buffer that outlives this program β€” shared between views, or cached
// per context β€” is its own thing. One that dies with the view goes in the
// schema instead, and is disposed with it.
const buffers = bufferView(gl, { indices: { target: 'ELEMENT_ARRAY_BUFFER' } })
buffers.indices.set(indexData)
const vao = view.vao([view.attributes.position, buffers.indices])

Returns:

  • program: Compiled WebGL program
  • schema: Merged schema (extracted + override)
  • view: Ready-to-use view with type-safe resource access
  • vertex: Compiled vertex shader GLSL string
  • fragment: Compiled fragment shader GLSL string

πŸ” compile.toString(shader)

Converts a GLSL tagged template to a shader string without compilation of the WebGLProgram. Useful for debugging or when you need the raw shader code.

const vertexShader = glsl`
  ${attribute.vec3('position')}
  ${uniform.mat4('mvpMatrix')}
  
  void main() {
    gl_Position = mvpMatrix * vec4(position, 1.0);
  }
`

const shaderString = compile.toString(vertexShader)
console.log(shaderString)
// Output:
// attribute vec3 position;
// uniform mat4 mvpMatrix;
// 
// void main() {
//   gl_Position = mvpMatrix * vec4(position, 1.0);
// }

Features:

  • Converts resource tags to GLSL declarations
  • Handles WebGL1/WebGL2 syntax automatically
  • Resolves symbol variables to unique identifiers
  • Processes nested GLSL fragments and arrays

πŸ“‹ compile.toSchema(shader)

Extracts the ViewSchema from a GLSL tagged template without compilation of the WebGLProgram. Returns the type-safe schema that could be used by view().

const shader = glsl`
  ${uniform.float('time')}
  ${uniform.vec3('lightPos', { size: 4 })}
  ${attribute.vec3('position')}
  ${interleave('vertexData', [
    attribute.vec2('uv'),
    attribute.vec4('color')
  ])}
`

const schema = compile.toSchema(shader)
console.log(schema)
// Output:
// {
//   uniforms: {
//     time: { kind: 'float' },
//     lightPos: { kind: 'vec3', size: 4 }
//   },
//   attributes: {
//     position: { kind: 'vec3' }
//   },
//   interleavedAttributes: {
//     vertexData: {
//       layout: [
//         { key: 'uv', kind: 'vec2' },
//         { key: 'color', kind: 'vec4' }
//       ],
//       instanced: false
//     }
//   }
// }

Use Cases:

  • Analyze shader resources without GL context
  • Generate TypeScript types from shaders
  • Validate shader compatibility before compilation
  • Build tooling around shader resources
Usage with vanilla view.gl

When manually constructing GLSL strings, use toID() to convert symbols to valid, unique identifiers:

const u_time = Symbol('time')
const a_position = Symbol('position')

const vertex = `
  attribute vec3 ${toID(a_position)};
  uniform float ${toID(u_time)};

  void main() {
    gl_Position = vec4(${toID(a_position)}, ${toID(u_time)});
  }
`

const fragment = `
  precision mediump float;
  uniform float ${toID(u_time)};

  void main() {
    gl_FragColor = vec4(1.0, 1.0, 1.0, sin(${toID(u_time)}));
  }
`

const program = createProgram(gl, vertex, fragment)

const { attributes, uniforms } = view(gl, program, {
  uniforms: { [u_time]: { kind: 'float' } },
  attributes: { [a_position]: { kind: 'vec3' } },
})

attributes[a_position].set(vertexData)
uniforms[u_time].set(performance.now())

πŸ› οΈ Utils

πŸ—οΈ createProgram

Creates and links a WebGL program from vertex and fragment shader sources.

const program = createProgram(gl, vertexShaderSource, fragmentShaderSource, { signal })

πŸ–ΌοΈ createTexture

Creates a WebGL texture with specified parameters.

const texture = createTexture(
  gl,
  {
    width: 512,
    height: 512,
    internalFormat: 'RGBA',
    format: 'RGBA',
    type: 'UNSIGNED_BYTE',
    minFilter: 'LINEAR',
    magFilter: 'LINEAR',
    wrapS: 'CLAMP_TO_EDGE',
    wrapT: 'CLAMP_TO_EDGE',
  },
  data,
  { signal },
)

Automatically validates WebGL2-only formats and provides fallbacks for WebGL1.

πŸ–₯️ createFramebuffer

Creates a framebuffer with attached texture for render-to-texture operations.

const { framebuffer, texture, dispose } = createFramebuffer(
  gl,
  {
    width: 512,
    height: 512,
    attachment: 'color',
    internalFormat: 'RGBA',
    format: 'RGBA',
    type: 'UNSIGNED_BYTE',
  },
  { signal },
)

Supports color, depth, stencil, and combined depth-stencil attachments with completeness validation.

Pass a texture to attach one you already have β€” ping-ponging a pair of framebuffers over shared textures, say. dispose() then deletes the framebuffer and leaves that texture alone, because it is not the framebuffer's to delete.

🚨 Errors

Every error view.gl throws for a GL call that failed is a class exported from @bigmistqke/view.gl, carrying what the GL answered:

Error Thrown when Carries
ShaderCompileError a shader does not compile stage, infoLog (string | null, as the driver answered it), glError
ProgramLinkError a program does not link infoLog (string | null), glError
GLCreateError a create* call answers null resource: 'shader', 'program', 'buffer', 'vertexArray', 'texture' or 'framebuffer'
AttributeNotFoundError getAttribLocation answers -1 attribute

A lost WebGL context answers every call with a default: null from a create*, -1 for an attribute, false with an empty or null log for a compile or link. So an empty infoLog or a GLCreateError carries no cause, where a non-empty infoLog is the driver's own reason.

import { createProgram } from '@bigmistqke/view.gl/gl'
import { ShaderCompileError } from '@bigmistqke/view.gl'

try {
  createProgram(gl, vertex, fragment)
} catch (error) {
  if (error instanceof ShaderCompileError && error.infoLog?.trim()) {
    console.error(`${error.stage} shader rejected:`, error.infoLog)
  }
}

πŸ” WebGL Type Compatibility

🎯 Uniform Types

Type WebGL 1 WebGL 2
float βœ… βœ…
int βœ… βœ…
bool βœ… βœ…
vec2 βœ… βœ…
vec3 βœ… βœ…
vec4 βœ… βœ…
ivec2 βœ… βœ…
ivec3 βœ… βœ…
ivec4 βœ… βœ…
bvec2 βœ… βœ…
bvec3 βœ… βœ…
bvec4 βœ… βœ…
mat2 βœ… βœ…
mat3 βœ… βœ…
mat4 βœ… βœ…
sampler2D βœ… βœ…
samplerCube βœ… βœ…
uint ❌ βœ…
uvec2 ❌ βœ…
uvec3 ❌ βœ…
uvec4 ❌ βœ…
mat2x3 ❌ βœ…
mat2x4 ❌ βœ…
mat3x2 ❌ βœ…
mat3x4 ❌ βœ…
mat4x2 ❌ βœ…
mat4x3 ❌ βœ…
sampler3D ❌ βœ…
sampler2DArray ❌ βœ…
sampler2DShadow ❌ βœ…
samplerCubeShadow ❌ βœ…
sampler2DArrayShadow ❌ βœ…
isampler2D ❌ βœ…
isampler3D ❌ βœ…
isamplerCube ❌ βœ…
isampler2DArray ❌ βœ…
usampler2D ❌ βœ…
usampler3D ❌ βœ…
usamplerCube ❌ βœ…
usampler2DArray ❌ βœ…

πŸ“ Attribute Types

Type WebGL 1 WebGL 2
float βœ… βœ…
vec2 βœ… βœ…
vec3 βœ… βœ…
vec4 βœ… βœ…
mat2 βœ… βœ…
mat3 βœ… βœ…
mat4 βœ… βœ…
int ❌ βœ…
ivec2 ❌ βœ…
ivec3 ❌ βœ…
ivec4 ❌ βœ…
uint ❌ βœ…
uvec2 ❌ βœ…
uvec3 ❌ βœ…
uvec4 ❌ βœ…
mat2x3 ❌ βœ…
mat2x4 ❌ βœ…
mat3x2 ❌ βœ…
mat3x4 ❌ βœ…
mat4x2 ❌ βœ…
mat4x3 ❌ βœ…

About

πŸ‘€ utilities for managing WebGL resources

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages