@bigmistqke/view.gl 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +4 -1
- package/.prettierignore +1 -0
- package/README.md +429 -213
- package/dev/src/examples/bezier.ts +3 -9
- package/dev/src/examples/{game_of_life.ts → game-of-life.ts} +2 -9
- package/dev/src/examples/glsl-composition.ts +131 -0
- package/dev/src/examples/grid.ts +4 -3
- package/dev/src/examples/overview.ts +7 -6
- package/dev/src/examples/{pix_sim.ts → pix-sim.ts} +3 -14
- package/dev/src/examples/symbol.ts +4 -3
- package/dev/src/index.ts +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/tag.d.mts +39 -21
- package/dist/tag.mjs +395 -47
- package/dist/tag.mjs.map +1 -1
- package/dist/{types-DoFAJoh-.d.mts → types-DIIqZ8e6.d.mts} +34 -11
- package/package.json +3 -2
- package/src/index.ts +4 -4
- package/src/tag.ts +251 -110
- package/src/types.ts +65 -5
- package/src/utils/index.ts +9 -9
- package/test/tag.test.ts +800 -82
package/README.md
CHANGED
|
@@ -10,56 +10,48 @@
|
|
|
10
10
|
- [📦 Install](#-install)
|
|
11
11
|
- [👁️ view.gl](#️-viewgl)
|
|
12
12
|
- [🚀 Basic Usage](#-basic-usage)
|
|
13
|
-
- [
|
|
13
|
+
- [👁️ view](#️-view)
|
|
14
|
+
- [👀 Resource Views](#-resource-views)
|
|
14
15
|
- [🎯 uniformView](#-uniformview)
|
|
15
16
|
- [📝 attributeView](#-attributeview)
|
|
16
17
|
- [🔗 interleavedAttributeView](#-interleavedattributeview)
|
|
17
18
|
- [🗂️ bufferView](#-bufferview)
|
|
18
|
-
- [🎨 Drawing Examples](#-drawing-examples)
|
|
19
|
-
- [🖼️ Regular Drawing](#-regular-drawing)
|
|
20
|
-
- [📱 Instanced Drawing](#-instanced-drawing)
|
|
21
19
|
- [🏷️ view.gl/tag](#️-viewgltag)
|
|
22
20
|
- [🚀 Basic Usage](#-basic-usage-1)
|
|
23
|
-
- [📝
|
|
24
|
-
|
|
21
|
+
- [📝 glsl](#-glsl)
|
|
22
|
+
- [🧩 GLSL Fragment](#-glsl-fragment)
|
|
23
|
+
- [🔒 Symbol Variables](#-symbol-variables)
|
|
24
|
+
- [WebGL Version Support](#webgl-version-support)
|
|
25
|
+
- [⚙️ Resource Tags](#️-resource-tags)
|
|
25
26
|
- [🎯 uniform[kind](name, options?)](#-uniformkindname-options)
|
|
26
27
|
- [📝 attribute[kind](name, options?)](#-attributekindname-options)
|
|
27
28
|
- [🔗 interleave(name, layout, options?)](#-interleavename-layout-options)
|
|
28
|
-
|
|
29
|
-
- [⚙️ compile(gl, vertex, fragment)](#️-compilegl-vertex-fragment)
|
|
30
|
-
- [🔣 Symbol Support](#-symbol-support)
|
|
29
|
+
- [⚙️ compile(gl, vertex, fragment)](#️-compilegl-vertex-fragment)
|
|
31
30
|
- [🛠️ Utils](#️-utils)
|
|
32
31
|
- [🏗️ createProgram](#️-createprogram)
|
|
33
32
|
- [🖼️ createTexture](#️-createtexture)
|
|
34
33
|
- [🖥️ createFramebuffer](#️-createframebuffer)
|
|
34
|
+
- [🔍 WebGL Type Compatibility](#-webgl-type-compatibility)
|
|
35
|
+
- [🎯 Uniform Types](#-uniform-types)
|
|
36
|
+
- [📝 Attribute Types](#-attribute-types)
|
|
35
37
|
|
|
36
38
|
## 📦 Install
|
|
37
39
|
|
|
38
40
|
```shell
|
|
39
41
|
npm install @bigmistqke/view.gl
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```shell
|
|
42
|
+
# or
|
|
43
43
|
pnpm add @bigmistqke/view.gl
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
```shell
|
|
44
|
+
# or
|
|
47
45
|
yarn add @bigmistqke/view.gl
|
|
48
46
|
```
|
|
49
47
|
|
|
50
|
-
```shell
|
|
51
|
-
bun add @bigmistqke/view.gl
|
|
52
|
-
```
|
|
53
|
-
|
|
54
48
|
## 👁️ view.gl
|
|
55
49
|
|
|
56
|
-
The view system provides type-safe WebGL resource management for uniforms, attributes, and buffers
|
|
50
|
+
The view system provides type-safe WebGL resource management for uniforms, attributes, and buffers
|
|
57
51
|
|
|
58
52
|
### 🚀 Basic Usage
|
|
59
53
|
|
|
60
54
|
```typescript
|
|
61
|
-
import { view } from '@bigmistqke/view.gl'
|
|
62
|
-
|
|
63
55
|
const { uniforms, attributes } = view(gl, program, {
|
|
64
56
|
uniforms: {
|
|
65
57
|
time: { kind: 'float' },
|
|
@@ -83,26 +75,74 @@ attributes.position.set(positionData)
|
|
|
83
75
|
attributes.position.bind()
|
|
84
76
|
```
|
|
85
77
|
|
|
86
|
-
###
|
|
78
|
+
### 👁️ view
|
|
87
79
|
|
|
88
|
-
|
|
80
|
+
The `view()` function creates type-safe WebGL resource managers from a schema.
|
|
89
81
|
|
|
90
82
|
```typescript
|
|
91
|
-
|
|
92
|
-
uniformView,
|
|
93
|
-
attributeView,
|
|
94
|
-
interleavedAttributeView,
|
|
95
|
-
bufferView,
|
|
96
|
-
} from '@bigmistqke/view.gl'
|
|
83
|
+
const { uniforms, attributes, buffers } = view(gl, program, schema)
|
|
97
84
|
```
|
|
98
85
|
|
|
86
|
+
**Parameters:**
|
|
87
|
+
|
|
88
|
+
- `gl`: WebGL rendering context
|
|
89
|
+
- `program`: Compiled WebGL program
|
|
90
|
+
- `schema`: Resource definitions object
|
|
91
|
+
|
|
92
|
+
**Returns:**
|
|
93
|
+
|
|
94
|
+
- `uniforms`: Type-safe uniform setters
|
|
95
|
+
- `attributes`: Attribute managers with buffer handling
|
|
96
|
+
- `buffers`: Generic buffer managers
|
|
97
|
+
|
|
98
|
+
**ViewSchema:**
|
|
99
|
+
The complete schema object that defines all WebGL resources. Contains optional mappings for uniforms, attributes, interleaved attributes, and buffers.
|
|
100
|
+
|
|
101
|
+
<details>
|
|
102
|
+
<summary>TypeScript Types</summary>
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
interface ViewSchema {
|
|
106
|
+
uniforms?: Record<string | symbol, UniformOptions>
|
|
107
|
+
attributes?: Record<string | symbol, AttributeOptions>
|
|
108
|
+
interleavedAttributes?: Record<string | symbol, InterleavedAttributeOptions>
|
|
109
|
+
buffers?: Record<string | symbol, BufferOptions>
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface UniformOptions {
|
|
113
|
+
kind: UniformKind
|
|
114
|
+
size?: number // For array uniforms
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface AttributeOptions {
|
|
118
|
+
kind: AttributeKind
|
|
119
|
+
instanced?: boolean
|
|
120
|
+
buffer?: WebGLBuffer
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
interface InterleavedAttributeOptions {
|
|
124
|
+
layout: Array<{ key: string | symbol; kind: AttributeKind }>
|
|
125
|
+
instanced?: boolean
|
|
126
|
+
buffer?: WebGLBuffer
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface BufferOptions {
|
|
130
|
+
target: 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER'
|
|
131
|
+
usage?: 'STATIC_DRAW' | 'DYNAMIC_DRAW' | 'STREAM_DRAW'
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
</details>
|
|
136
|
+
|
|
137
|
+
### 👀 Resource Views
|
|
138
|
+
|
|
139
|
+
Each view type can be imported individually.
|
|
140
|
+
|
|
99
141
|
#### 🎯 uniformView
|
|
100
142
|
|
|
101
143
|
Manages shader uniform variables.
|
|
102
144
|
|
|
103
145
|
```typescript
|
|
104
|
-
import { uniformView } from '@bigmistqke/view.gl'
|
|
105
|
-
|
|
106
146
|
const uniforms = uniformView(gl, program, {
|
|
107
147
|
time: { kind: 'float' },
|
|
108
148
|
lights: { kind: 'vec3', size: 8 }, // Array uniform: vec3[8]
|
|
@@ -111,52 +151,103 @@ const uniforms = uniformView(gl, program, {
|
|
|
111
151
|
|
|
112
152
|
uniforms.time.set(performance.now())
|
|
113
153
|
uniforms.lights.set(lightData) // Takes Float32Array for array uniforms
|
|
114
|
-
uniforms.transform.set(transformMatrix)
|
|
115
154
|
```
|
|
116
155
|
|
|
117
|
-
**
|
|
156
|
+
**UniformSchema:**
|
|
157
|
+
A mapping of uniform names to their configuration. Each uniform has a GLSL type and optional array size.
|
|
118
158
|
|
|
119
|
-
- `kind`: GLSL type (
|
|
120
|
-
- `size`: Array size (optional) - converts uniform to array type
|
|
159
|
+
- `kind`: GLSL type (see [Uniform Types](#-uniform-types) for full list and WebGL compatibility)
|
|
160
|
+
- `size`: Array size (optional) - converts uniform to array type
|
|
161
|
+
|
|
162
|
+
<details>
|
|
163
|
+
<summary>TypeScript Types</summary>
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
type UniformKind =
|
|
167
|
+
| 'float'
|
|
168
|
+
| 'int'
|
|
169
|
+
| 'bool'
|
|
170
|
+
| 'vec2'
|
|
171
|
+
| 'vec3'
|
|
172
|
+
| 'vec4'
|
|
173
|
+
| 'ivec2'
|
|
174
|
+
| 'ivec3'
|
|
175
|
+
| 'ivec4'
|
|
176
|
+
| 'bvec2'
|
|
177
|
+
| 'bvec3'
|
|
178
|
+
| 'bvec4'
|
|
179
|
+
| 'mat2'
|
|
180
|
+
| 'mat3'
|
|
181
|
+
| 'mat4'
|
|
182
|
+
| 'sampler2D'
|
|
183
|
+
| 'samplerCube'
|
|
184
|
+
|
|
185
|
+
interface UniformOptions {
|
|
186
|
+
kind: UniformKind
|
|
187
|
+
size?: number // Creates array uniform with Float32Array setter
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
type UniformSchema = Record<string | symbol, UniformOptions>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
</details>
|
|
121
194
|
|
|
122
195
|
#### 📝 attributeView
|
|
123
196
|
|
|
124
|
-
Manages vertex attributes with buffer creation
|
|
197
|
+
Manages vertex attributes with automatic buffer creation and binding.
|
|
125
198
|
|
|
126
199
|
```typescript
|
|
127
|
-
import { attributeView } from '@bigmistqke/view.gl'
|
|
128
|
-
|
|
129
200
|
const attributes = attributeView(gl, program, {
|
|
130
201
|
position: { kind: 'vec3' },
|
|
131
202
|
instanceOffset: { kind: 'vec2', instanced: true },
|
|
132
203
|
})
|
|
133
204
|
|
|
134
|
-
// Regular attribute for vertices
|
|
135
205
|
attributes.position.set(positionData).bind()
|
|
136
|
-
|
|
137
|
-
// Instanced attribute for per-instance data
|
|
138
206
|
attributes.instanceOffset.set(instanceData).bind()
|
|
139
207
|
|
|
140
|
-
// Draw regular geometry
|
|
141
|
-
gl.drawArrays(gl.TRIANGLES, 0, 3)
|
|
142
|
-
|
|
143
|
-
// Draw instanced geometry
|
|
144
208
|
gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, 100)
|
|
145
209
|
```
|
|
146
210
|
|
|
147
|
-
**
|
|
211
|
+
**AttributeSchema:**
|
|
212
|
+
A mapping of attribute names to their configuration. Each attribute has a GLSL type, optional instancing, and optional custom buffer.
|
|
213
|
+
|
|
214
|
+
- `kind`: GLSL type (see [Attribute Types](#-attribute-types) for full list and WebGL compatibility)
|
|
215
|
+
- `instanced`: Boolean - enables instanced rendering
|
|
216
|
+
- `buffer`: Custom WebGLBuffer (optional)
|
|
148
217
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
218
|
+
<details>
|
|
219
|
+
<summary>TypeScript Types</summary>
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
type AttributeKind =
|
|
223
|
+
| 'float'
|
|
224
|
+
| 'vec2'
|
|
225
|
+
| 'vec3'
|
|
226
|
+
| 'vec4'
|
|
227
|
+
| 'mat2'
|
|
228
|
+
| 'mat3'
|
|
229
|
+
| 'mat4'
|
|
230
|
+
| 'int'
|
|
231
|
+
| 'ivec2'
|
|
232
|
+
| 'ivec3'
|
|
233
|
+
| 'ivec4'
|
|
234
|
+
|
|
235
|
+
interface AttributeOptions {
|
|
236
|
+
kind: AttributeKind
|
|
237
|
+
instanced?: boolean // Enables vertexAttribDivisor
|
|
238
|
+
buffer?: WebGLBuffer // Custom buffer, auto-created if not provided
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
type AttributeSchema = Record<string | symbol, AttributeOptions>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
</details>
|
|
152
245
|
|
|
153
246
|
#### 🔗 interleavedAttributeView
|
|
154
247
|
|
|
155
|
-
Manages interleaved vertex data with automatic stride/offset calculation
|
|
248
|
+
Manages interleaved vertex data with automatic stride/offset calculation.
|
|
156
249
|
|
|
157
250
|
```typescript
|
|
158
|
-
import { interleavedAttributeView } from '@bigmistqke/view.gl'
|
|
159
|
-
|
|
160
251
|
const interleavedAttributes = interleavedAttributeView(gl, program, {
|
|
161
252
|
vertexData: {
|
|
162
253
|
layout: [
|
|
@@ -165,109 +256,90 @@ const interleavedAttributes = interleavedAttributeView(gl, program, {
|
|
|
165
256
|
{ key: 'uv', kind: 'vec2' },
|
|
166
257
|
],
|
|
167
258
|
},
|
|
168
|
-
instanceData: {
|
|
169
|
-
layout: [
|
|
170
|
-
{ key: 'instancePos', kind: 'vec2' },
|
|
171
|
-
{ key: 'instanceColor', kind: 'vec3' },
|
|
172
|
-
],
|
|
173
|
-
instanced: true,
|
|
174
|
-
},
|
|
175
259
|
})
|
|
176
260
|
|
|
177
|
-
|
|
178
|
-
interleavedAttributes.vertexData.set(interleavedVertexData)
|
|
179
|
-
interleavedAttributes.instanceData.set(interleavedInstanceData)
|
|
180
|
-
|
|
181
|
-
// Bind all attributes in layout
|
|
182
|
-
interleavedAttributes.vertexData.bind()
|
|
183
|
-
interleavedAttributes.instanceData.bind()
|
|
261
|
+
interleavedAttributes.vertexData.set(interleavedVertexData).bind()
|
|
184
262
|
```
|
|
185
263
|
|
|
186
|
-
**
|
|
264
|
+
**InterleavedAttributeSchema:**
|
|
265
|
+
A mapping of interleaved buffer names to their layout configuration. Each layout defines multiple attributes packed into a single buffer.
|
|
266
|
+
|
|
267
|
+
- `layout`: Array of attribute definitions with `key` and `kind` (see [Attribute Types](#-attribute-types))
|
|
268
|
+
- `instanced`: Boolean - applies to all attributes in layout
|
|
187
269
|
|
|
188
|
-
|
|
189
|
-
|
|
270
|
+
<details>
|
|
271
|
+
<summary>TypeScript Types</summary>
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
interface InterleavedAttributeOptions {
|
|
275
|
+
layout: Array<{
|
|
276
|
+
key: string | symbol
|
|
277
|
+
kind: AttributeKind
|
|
278
|
+
}>
|
|
279
|
+
instanced?: boolean // Applies vertexAttribDivisor to all attributes
|
|
280
|
+
buffer?: WebGLBuffer // Custom buffer for interleaved data
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
type InterleavedAttributeSchema = Record<string | symbol, InterleavedAttributeOptions>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
</details>
|
|
190
287
|
|
|
191
288
|
#### 🗂️ bufferView
|
|
192
289
|
|
|
193
|
-
Manages generic WebGL buffers
|
|
290
|
+
Manages generic WebGL buffers.
|
|
194
291
|
|
|
195
292
|
```typescript
|
|
196
|
-
import { bufferView } from '@bigmistqke/view.gl'
|
|
197
|
-
|
|
198
293
|
const buffers = bufferView(gl, {
|
|
199
294
|
indices: { target: 'ELEMENT_ARRAY_BUFFER' },
|
|
200
295
|
data: { target: 'ARRAY_BUFFER', usage: 'DYNAMIC_DRAW' },
|
|
201
296
|
})
|
|
202
297
|
|
|
203
|
-
buffers.indices.set(indexData)
|
|
204
|
-
buffers.
|
|
205
|
-
|
|
206
|
-
buffers.data.set(dynamicData)
|
|
207
|
-
buffers.data.bind()
|
|
298
|
+
buffers.indices.set(indexData).bind()
|
|
299
|
+
buffers.data.set(dynamicData).bind()
|
|
208
300
|
```
|
|
209
301
|
|
|
210
|
-
**
|
|
302
|
+
**BufferSchema:**
|
|
303
|
+
A mapping of buffer names to their configuration. Each buffer has a target type and optional usage pattern.
|
|
211
304
|
|
|
212
305
|
- `target`: Buffer target (`'ARRAY_BUFFER'`, `'ELEMENT_ARRAY_BUFFER'`)
|
|
213
306
|
- `usage`: Usage pattern (`'STATIC_DRAW'`, `'DYNAMIC_DRAW'`, `'STREAM_DRAW'`)
|
|
214
307
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
#### 🖼️ Regular Drawing
|
|
308
|
+
<details>
|
|
309
|
+
<summary>TypeScript Types</summary>
|
|
218
310
|
|
|
219
311
|
```typescript
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
},
|
|
225
|
-
})
|
|
312
|
+
interface BufferOptions {
|
|
313
|
+
target: 'ARRAY_BUFFER' | 'ELEMENT_ARRAY_BUFFER'
|
|
314
|
+
usage?: 'STATIC_DRAW' | 'DYNAMIC_DRAW' | 'STREAM_DRAW' // Defaults to 'STATIC_DRAW'
|
|
315
|
+
}
|
|
226
316
|
|
|
227
|
-
|
|
228
|
-
attributes.uv.set(uvData).bind()
|
|
229
|
-
|
|
230
|
-
gl.drawArrays(gl.TRIANGLES, 0, vertexCount)
|
|
317
|
+
type BufferSchema = Record<string | symbol, BufferOptions>
|
|
231
318
|
```
|
|
232
319
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
```typescript
|
|
236
|
-
const { attributes } = view(gl, program, {
|
|
237
|
-
attributes: {
|
|
238
|
-
position: { kind: 'vec3' },
|
|
239
|
-
instanceOffset: { kind: 'vec2', instanced: true },
|
|
240
|
-
instanceColor: { kind: 'vec3', instanced: true },
|
|
241
|
-
},
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
attributes.position.set(triangleVertices).bind()
|
|
245
|
-
attributes.instanceOffset.set(instanceOffsets).bind()
|
|
246
|
-
attributes.instanceColor.set(instanceColors).bind()
|
|
247
|
-
|
|
248
|
-
gl.drawArraysInstanced(gl.TRIANGLES, 0, 3, instanceCount)
|
|
249
|
-
```
|
|
320
|
+
</details>
|
|
250
321
|
|
|
251
322
|
## 🏷️ view.gl/tag
|
|
252
323
|
|
|
253
|
-
|
|
324
|
+
Type-safe GLSL template literals with automatic schema extraction.
|
|
325
|
+
|
|
326
|
+
- **Embedded Resources**: Define uniforms, attributes, and interleaved layouts directly in GLSL
|
|
327
|
+
- **Type Inference**: Automatically infers schema types and creates type-safe view
|
|
328
|
+
- **Unique Variables**: Prevent naming collisions using symbols for unique shader variables
|
|
329
|
+
- **GLSL Composition**: Compose reusable GLSL fragments with automatic dependency resolution
|
|
254
330
|
|
|
255
331
|
### 🚀 Basic Usage
|
|
256
332
|
|
|
257
333
|
```typescript
|
|
258
|
-
import { glsl, uniform, attribute, compile } from '@bigmistqke/view.gl/tag'
|
|
259
|
-
|
|
260
334
|
const vertexShader = glsl`
|
|
261
335
|
${attribute.vec3('position')}
|
|
262
|
-
${attribute.vec2('uv')}
|
|
263
|
-
${uniform.mat4('projection')}
|
|
264
336
|
${uniform.mat4('model')}
|
|
265
337
|
|
|
266
338
|
varying vec2 vUv;
|
|
267
339
|
|
|
268
340
|
void main() {
|
|
269
341
|
vUv = uv;
|
|
270
|
-
gl_Position =
|
|
342
|
+
gl_Position = model * vec4(position, 1.0);
|
|
271
343
|
}
|
|
272
344
|
`
|
|
273
345
|
|
|
@@ -284,170 +356,247 @@ const fragmentShader = glsl`
|
|
|
284
356
|
const { program, schema } = compile(gl, vertexShader, fragmentShader)
|
|
285
357
|
```
|
|
286
358
|
|
|
287
|
-
### 📝
|
|
359
|
+
### 📝 glsl
|
|
288
360
|
|
|
289
|
-
|
|
290
|
-
- **Type Safety**: Automatic schema generation from template literals
|
|
291
|
-
- **WebGL Version Support**: Automatic syntax conversion for WebGL1/2
|
|
292
|
-
- **Interleaved Attributes**: Multi-attribute layout support
|
|
293
|
-
- **Symbol Support**: Use JavaScript symbols as keys (see [Symbol Support](#-symbol-support))
|
|
361
|
+
Template literal processor that handles GLSL code and embedded resources. Supports interpolation of:
|
|
294
362
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
363
|
+
- **[Resource tags](#️-resource-tags)**: `uniform.*()`, `attribute.*()`, `interleave()`
|
|
364
|
+
- **[GLSL fragments](#-glsl-fragment)**: Reusable shader code snippets
|
|
365
|
+
- **[Symbol Variables](#-symbol-variables)**: Unique variable names to prevent collisions
|
|
366
|
+
- **Strings**: Interpolated as-is into the shader code
|
|
367
|
+
- **Arrays**: Arrays of any supported interpolation types
|
|
300
368
|
|
|
301
369
|
```typescript
|
|
302
|
-
|
|
370
|
+
const precision = 'precision mediump float;'
|
|
371
|
+
const functionName = Symbol('function')
|
|
303
372
|
|
|
304
373
|
const shader = glsl`
|
|
305
|
-
${
|
|
374
|
+
${precision} // String interpolated as-is
|
|
306
375
|
${uniform.vec2('resolution')}
|
|
307
|
-
${
|
|
308
|
-
|
|
309
|
-
${
|
|
376
|
+
${[attribute.vec3('position'), attribute.vec2('uv')]} // Array interpolation
|
|
377
|
+
|
|
378
|
+
vec3 ${functionName}(vec2 uv) { // Symbol interpolated to unique identifier
|
|
379
|
+
return vec3(uv, 0.5);
|
|
380
|
+
}
|
|
310
381
|
|
|
311
382
|
void main() {
|
|
312
|
-
|
|
383
|
+
gl_Position = vec4(position, 1.0);
|
|
313
384
|
}
|
|
314
385
|
`
|
|
315
386
|
```
|
|
316
387
|
|
|
317
|
-
|
|
388
|
+
#### 🧩 GLSL Fragment
|
|
318
389
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
- `size`: Array size (creates array uniform with Float32Array setter)
|
|
322
|
-
|
|
323
|
-
#### 📝 attribute[kind](name, options?)
|
|
324
|
-
|
|
325
|
-
Define vertex attributes in GLSL templates.
|
|
390
|
+
Compose reusable GLSL code fragments to build complex shaders:
|
|
326
391
|
|
|
327
392
|
```typescript
|
|
328
|
-
|
|
393
|
+
const lighting = glsl`
|
|
394
|
+
vec3 calculateLighting(vec3 normal, vec3 lightDir) {
|
|
395
|
+
float diff = max(dot(normal, lightDir), 0.0);
|
|
396
|
+
return vec3(diff);
|
|
397
|
+
}
|
|
398
|
+
`
|
|
329
399
|
|
|
330
400
|
const vertexShader = glsl`
|
|
331
|
-
${attribute.vec3('
|
|
332
|
-
${attribute.vec2('uv')}
|
|
401
|
+
${attribute.vec3('direction')}
|
|
333
402
|
${attribute.vec3('normal')}
|
|
334
|
-
${
|
|
403
|
+
${lighting} // Include the lighting fragment
|
|
404
|
+
|
|
405
|
+
varying vec3 vLighting;
|
|
335
406
|
|
|
336
407
|
void main() {
|
|
337
|
-
|
|
408
|
+
vLighting = calculateLighting(normal, direction);
|
|
338
409
|
}
|
|
339
410
|
`
|
|
340
411
|
```
|
|
341
412
|
|
|
342
|
-
|
|
413
|
+
#### 🔒 Symbol Variables
|
|
343
414
|
|
|
344
|
-
|
|
415
|
+
Use JavaScript symbols to prevent naming collisions:
|
|
345
416
|
|
|
346
|
-
|
|
347
|
-
|
|
417
|
+
```typescript
|
|
418
|
+
const sum = Symbol('sum')
|
|
348
419
|
|
|
349
|
-
|
|
420
|
+
const sumFragment = glsl`
|
|
421
|
+
float ${sum}(float a, float b){
|
|
422
|
+
return a + b;
|
|
423
|
+
}`
|
|
350
424
|
|
|
351
|
-
|
|
425
|
+
const shader = glsl`
|
|
426
|
+
${sumFragment}
|
|
352
427
|
|
|
353
|
-
|
|
354
|
-
|
|
428
|
+
void main(){
|
|
429
|
+
float result = ${sum}(1.0, 2.0);
|
|
430
|
+
}
|
|
431
|
+
`
|
|
432
|
+
```
|
|
355
433
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
{ key: 'instanceColor', kind: 'vec3' },
|
|
368
|
-
],
|
|
369
|
-
{ instanced: true },
|
|
370
|
-
)}
|
|
371
|
-
|
|
372
|
-
void main() {
|
|
373
|
-
gl_Position = vec4(position + vec3(instancePos, 0.0), 1.0);
|
|
374
|
-
}
|
|
434
|
+
Symbols are converted to unique identifiers during the compilation of the shader.
|
|
435
|
+
|
|
436
|
+
#### WebGL Version Support
|
|
437
|
+
|
|
438
|
+
The glsl-function supports both WebGL1 and WebGL2 syntax, automatically using the correct keywords for resource tags:
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
// WebGL1 (default)
|
|
442
|
+
const shader = glsl`
|
|
443
|
+
${attribute.vec3('position')} // → attribute vec3 position;
|
|
444
|
+
varying vec2 vUv;
|
|
375
445
|
`
|
|
376
446
|
```
|
|
377
447
|
|
|
378
|
-
|
|
448
|
+
If the shader starts with `#version 300 es`, resource tags generate WebGL2 syntax:
|
|
379
449
|
|
|
380
|
-
|
|
381
|
-
|
|
450
|
+
```typescript
|
|
451
|
+
// WebGL2
|
|
452
|
+
const shader = glsl`#version 300 es
|
|
453
|
+
${attribute.vec3('position')} // → in vec3 position;
|
|
454
|
+
out vec2 vUv;
|
|
455
|
+
`
|
|
456
|
+
```
|
|
382
457
|
|
|
383
|
-
|
|
458
|
+
### ⚙️ Resource Tags
|
|
384
459
|
|
|
385
|
-
|
|
460
|
+
Functions for defining WebGL resources directly in GLSL templates. These tags generate GLSL declarations and automatically extract type-safe schemas for use with the view system.
|
|
386
461
|
|
|
387
|
-
####
|
|
462
|
+
#### 🎯 uniform[kind](name, options?)
|
|
388
463
|
|
|
389
|
-
|
|
464
|
+
Define uniform variables in GLSL templates (see [Uniform Types](#-uniform-types)).
|
|
390
465
|
|
|
391
466
|
```typescript
|
|
392
|
-
|
|
467
|
+
const uniqueTime = Symbol('time')
|
|
393
468
|
|
|
394
469
|
const shader = glsl`
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
${uniform.
|
|
470
|
+
${uniform.float('time')} // String key
|
|
471
|
+
${uniform.float(uniqueTime)} // Symbol key
|
|
472
|
+
${uniform.vec3('lights', { size: 8 })} // Array uniform: vec3[8]
|
|
398
473
|
|
|
399
474
|
void main() {
|
|
400
|
-
|
|
401
|
-
|
|
475
|
+
float wave = sin(time * 2.0 + ${uniqueTime});
|
|
476
|
+
vec3 totalLight = vec3(0.0);
|
|
477
|
+
for(int i = 0; i < 8; i++) {
|
|
478
|
+
totalLight += lights[i] * wave;
|
|
479
|
+
}
|
|
480
|
+
gl_FragColor = vec4(totalLight, 1.0);
|
|
402
481
|
}
|
|
403
482
|
`
|
|
404
483
|
```
|
|
405
484
|
|
|
406
|
-
|
|
485
|
+
**Parameters**:
|
|
407
486
|
|
|
408
|
-
|
|
487
|
+
- `name`: Uniform name (string or symbol for unique variables)
|
|
488
|
+
- `options`: Optional configuration object
|
|
489
|
+
- `size`: Array size (creates array uniform with Float32Array setter)
|
|
409
490
|
|
|
410
|
-
|
|
411
|
-
import { compile } from '@bigmistqke/view.gl/tag'
|
|
491
|
+
#### 📝 attribute[kind](name, options?)
|
|
412
492
|
|
|
413
|
-
|
|
493
|
+
Define vertex attributes in GLSL templates (see [Attribute Types](#-attribute-types)).
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
const uniquePosition = Symbol('position')
|
|
414
497
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
498
|
+
const vertexShader = glsl`
|
|
499
|
+
${attribute.vec3('position')} // String key
|
|
500
|
+
${attribute.vec3(uniquePosition)} // Symbol key
|
|
501
|
+
${attribute.vec2('offset', { instanced: true })}
|
|
502
|
+
|
|
503
|
+
void main() {
|
|
504
|
+
gl_Position = vec4(position + vec3(offset, 0.0), 1.0);
|
|
505
|
+
}
|
|
506
|
+
`
|
|
418
507
|
```
|
|
419
508
|
|
|
420
|
-
**
|
|
509
|
+
**Parameters**:
|
|
421
510
|
|
|
422
|
-
- `
|
|
423
|
-
- `
|
|
511
|
+
- `name`: Attribute name (string or symbol for unique variables)
|
|
512
|
+
- `options`: Optional configuration object
|
|
513
|
+
- `instanced`: Boolean - enables instanced rendering with `vertexAttribDivisor`
|
|
514
|
+
- `buffer`: Custom WebGLBuffer (optional)
|
|
424
515
|
|
|
425
|
-
|
|
516
|
+
#### 🔗 interleave(name, layout, options?)
|
|
426
517
|
|
|
427
|
-
|
|
518
|
+
Define interleaved attribute layouts for efficient vertex data.
|
|
428
519
|
|
|
429
520
|
```typescript
|
|
430
|
-
const
|
|
431
|
-
const
|
|
521
|
+
const uniqueVertexData = Symbol('vertexData')
|
|
522
|
+
const uniquePosition = Symbol('position')
|
|
432
523
|
|
|
433
|
-
const
|
|
434
|
-
${
|
|
435
|
-
|
|
524
|
+
const vertexShader = glsl`
|
|
525
|
+
${interleave('vertexData', [
|
|
526
|
+
// String key
|
|
527
|
+
{ key: 'position', kind: 'vec3' },
|
|
528
|
+
{ key: 'uv', kind: 'vec2' },
|
|
529
|
+
])}
|
|
530
|
+
${interleave(uniqueVertexData, [
|
|
531
|
+
// Symbol key
|
|
532
|
+
{ key: uniquePosition, kind: 'vec3' }, // Symbol keys in layout
|
|
533
|
+
{ key: 'uv', kind: 'vec2' },
|
|
534
|
+
])}
|
|
436
535
|
|
|
437
536
|
void main() {
|
|
438
|
-
gl_Position = vec4(
|
|
537
|
+
gl_Position = vec4(position + vec3(uv, 0.0), 1.0);
|
|
439
538
|
}
|
|
440
539
|
`
|
|
441
540
|
```
|
|
442
541
|
|
|
542
|
+
**Parameters**:
|
|
543
|
+
|
|
544
|
+
- `name`: Buffer name (string or symbol for unique variables)
|
|
545
|
+
- `layout`: Array of attribute definitions
|
|
546
|
+
- `key`: Attribute name (string or symbol for unique variables)
|
|
547
|
+
- `kind`: GLSL type (see [Attribute Types](#-attribute-types))
|
|
548
|
+
- `options`: Optional configuration object
|
|
549
|
+
- `instanced`: Boolean - applies `vertexAttribDivisor` to all attributes
|
|
550
|
+
|
|
551
|
+
### ⚙️ compile(gl, vertex, fragment, overrideSchema?)
|
|
552
|
+
|
|
553
|
+
Compiles shaders and extracts schema from embedded resources. Returns both the compiled program and a ready-to-use view.
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
const { program, schema, view } = compile(gl, vertexShader, fragmentShader)
|
|
557
|
+
|
|
558
|
+
// Use the view directly
|
|
559
|
+
view.uniforms.time.set(performance.now())
|
|
560
|
+
view.attributes.position.set(vertexData).bind()
|
|
561
|
+
|
|
562
|
+
// Or access the extracted schema
|
|
563
|
+
console.log(schema.uniforms) // { time: { kind: 'float' }, ... }
|
|
564
|
+
console.log(schema.attributes) // { position: { kind: 'vec3' }, ... }
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
**Override Schema:**
|
|
568
|
+
|
|
569
|
+
You can provide an optional override schema to enhance or override the automatically extracted schema:
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
const { program, schema, view } = compile(gl, vertexShader, fragmentShader, {
|
|
573
|
+
uniforms: {
|
|
574
|
+
// Add additional uniforms not automatically inferred
|
|
575
|
+
customTime: { kind: 'float' },
|
|
576
|
+
},
|
|
577
|
+
buffers: {
|
|
578
|
+
// Add buffer definitions
|
|
579
|
+
indices: { target: 'ELEMENT_ARRAY_BUFFER' },
|
|
580
|
+
},
|
|
581
|
+
})
|
|
582
|
+
|
|
583
|
+
// The override schema is merged with the extracted schema
|
|
584
|
+
view.uniforms.customTime.set(123.45)
|
|
585
|
+
view.buffers.indices.set(indexData).bind()
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
**Returns**:
|
|
589
|
+
|
|
590
|
+
- `program`: Compiled WebGL program
|
|
591
|
+
- `schema`: Merged schema (extracted + override)
|
|
592
|
+
- `view`: Ready-to-use view with type-safe resource access
|
|
593
|
+
|
|
443
594
|
<details>
|
|
444
595
|
<summary>Usage with vanilla view.gl</summary>
|
|
445
596
|
|
|
446
|
-
When manually constructing GLSL strings, use `toID()` to convert symbols to valid identifiers:
|
|
597
|
+
When manually constructing GLSL strings, use `toID()` to convert symbols to valid, unique identifiers:
|
|
447
598
|
|
|
448
599
|
```typescript
|
|
449
|
-
import { createProgram, view, toID } from 'view.gl'
|
|
450
|
-
|
|
451
600
|
const u_time = Symbol('time')
|
|
452
601
|
const a_position = Symbol('position')
|
|
453
602
|
|
|
@@ -489,8 +638,6 @@ uniforms[u_time].set(performance.now())
|
|
|
489
638
|
Creates and links a WebGL program from vertex and fragment shader sources.
|
|
490
639
|
|
|
491
640
|
```typescript
|
|
492
|
-
import { createProgram } from '@bigmistqke/view.gl/utils'
|
|
493
|
-
|
|
494
641
|
const program = createProgram(gl, vertexShaderSource, fragmentShaderSource)
|
|
495
642
|
```
|
|
496
643
|
|
|
@@ -499,8 +646,6 @@ const program = createProgram(gl, vertexShaderSource, fragmentShaderSource)
|
|
|
499
646
|
Creates a WebGL texture with specified parameters.
|
|
500
647
|
|
|
501
648
|
```typescript
|
|
502
|
-
import { createTexture } from '@bigmistqke/view.gl/utils'
|
|
503
|
-
|
|
504
649
|
const texture = createTexture(
|
|
505
650
|
gl,
|
|
506
651
|
{
|
|
@@ -525,8 +670,6 @@ Automatically validates WebGL2-only formats and provides fallbacks for WebGL1.
|
|
|
525
670
|
Creates a framebuffer with attached texture for render-to-texture operations.
|
|
526
671
|
|
|
527
672
|
```typescript
|
|
528
|
-
import { createFramebuffer } from '@bigmistqke/view.gl/utils'
|
|
529
|
-
|
|
530
673
|
const { framebuffer, texture } = createFramebuffer(gl, {
|
|
531
674
|
width: 512,
|
|
532
675
|
height: 512,
|
|
@@ -538,3 +681,76 @@ const { framebuffer, texture } = createFramebuffer(gl, {
|
|
|
538
681
|
```
|
|
539
682
|
|
|
540
683
|
Supports color, depth, stencil, and combined depth-stencil attachments with completeness validation.
|
|
684
|
+
|
|
685
|
+
## 🔍 WebGL Type Compatibility
|
|
686
|
+
|
|
687
|
+
### 🎯 Uniform Types
|
|
688
|
+
|
|
689
|
+
| Type | WebGL 1 | WebGL 2 |
|
|
690
|
+
| ---------------------- | ------- | ------- |
|
|
691
|
+
| `float` | ✅ | ✅ |
|
|
692
|
+
| `int` | ✅ | ✅ |
|
|
693
|
+
| `bool` | ✅ | ✅ |
|
|
694
|
+
| `vec2` | ✅ | ✅ |
|
|
695
|
+
| `vec3` | ✅ | ✅ |
|
|
696
|
+
| `vec4` | ✅ | ✅ |
|
|
697
|
+
| `ivec2` | ✅ | ✅ |
|
|
698
|
+
| `ivec3` | ✅ | ✅ |
|
|
699
|
+
| `ivec4` | ✅ | ✅ |
|
|
700
|
+
| `bvec2` | ✅ | ✅ |
|
|
701
|
+
| `bvec3` | ✅ | ✅ |
|
|
702
|
+
| `bvec4` | ✅ | ✅ |
|
|
703
|
+
| `mat2` | ✅ | ✅ |
|
|
704
|
+
| `mat3` | ✅ | ✅ |
|
|
705
|
+
| `mat4` | ✅ | ✅ |
|
|
706
|
+
| `sampler2D` | ✅ | ✅ |
|
|
707
|
+
| `samplerCube` | ✅ | ✅ |
|
|
708
|
+
| `uint` | ❌ | ✅ |
|
|
709
|
+
| `uvec2` | ❌ | ✅ |
|
|
710
|
+
| `uvec3` | ❌ | ✅ |
|
|
711
|
+
| `uvec4` | ❌ | ✅ |
|
|
712
|
+
| `mat2x3` | ❌ | ✅ |
|
|
713
|
+
| `mat2x4` | ❌ | ✅ |
|
|
714
|
+
| `mat3x2` | ❌ | ✅ |
|
|
715
|
+
| `mat3x4` | ❌ | ✅ |
|
|
716
|
+
| `mat4x2` | ❌ | ✅ |
|
|
717
|
+
| `mat4x3` | ❌ | ✅ |
|
|
718
|
+
| `sampler3D` | ❌ | ✅ |
|
|
719
|
+
| `sampler2DArray` | ❌ | ✅ |
|
|
720
|
+
| `sampler2DShadow` | ❌ | ✅ |
|
|
721
|
+
| `samplerCubeShadow` | ❌ | ✅ |
|
|
722
|
+
| `sampler2DArrayShadow` | ❌ | ✅ |
|
|
723
|
+
| `isampler2D` | ❌ | ✅ |
|
|
724
|
+
| `isampler3D` | ❌ | ✅ |
|
|
725
|
+
| `isamplerCube` | ❌ | ✅ |
|
|
726
|
+
| `isampler2DArray` | ❌ | ✅ |
|
|
727
|
+
| `usampler2D` | ❌ | ✅ |
|
|
728
|
+
| `usampler3D` | ❌ | ✅ |
|
|
729
|
+
| `usamplerCube` | ❌ | ✅ |
|
|
730
|
+
| `usampler2DArray` | ❌ | ✅ |
|
|
731
|
+
|
|
732
|
+
### 📝 Attribute Types
|
|
733
|
+
|
|
734
|
+
| Type | WebGL 1 | WebGL 2 |
|
|
735
|
+
| -------- | ------- | ------- |
|
|
736
|
+
| `float` | ✅ | ✅ |
|
|
737
|
+
| `vec2` | ✅ | ✅ |
|
|
738
|
+
| `vec3` | ✅ | ✅ |
|
|
739
|
+
| `vec4` | ✅ | ✅ |
|
|
740
|
+
| `mat2` | ✅ | ✅ |
|
|
741
|
+
| `mat3` | ✅ | ✅ |
|
|
742
|
+
| `mat4` | ✅ | ✅ |
|
|
743
|
+
| `int` | ❌ | ✅ |
|
|
744
|
+
| `ivec2` | ❌ | ✅ |
|
|
745
|
+
| `ivec3` | ❌ | ✅ |
|
|
746
|
+
| `ivec4` | ❌ | ✅ |
|
|
747
|
+
| `uint` | ❌ | ✅ |
|
|
748
|
+
| `uvec2` | ❌ | ✅ |
|
|
749
|
+
| `uvec3` | ❌ | ✅ |
|
|
750
|
+
| `uvec4` | ❌ | ✅ |
|
|
751
|
+
| `mat2x3` | ❌ | ✅ |
|
|
752
|
+
| `mat2x4` | ❌ | ✅ |
|
|
753
|
+
| `mat3x2` | ❌ | ✅ |
|
|
754
|
+
| `mat3x4` | ❌ | ✅ |
|
|
755
|
+
| `mat4x2` | ❌ | ✅ |
|
|
756
|
+
| `mat4x3` | ❌ | ✅ |
|