@bigmistqke/view.gl 0.1.8 → 0.1.10

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.
Files changed (44) hide show
  1. package/.claude/settings.local.json +4 -8
  2. package/README.md +30 -0
  3. package/dev/src/examples/bezier.ts +3 -2
  4. package/dev/src/examples/game-of-life.ts +13 -30
  5. package/dev/src/examples/glsl-composition.ts +3 -3
  6. package/dev/src/examples/grid.ts +20 -14
  7. package/dev/src/examples/pix-sim.ts +29 -22
  8. package/dev/src/examples/ray-casting.ts +455 -0
  9. package/dev/src/examples/sdf.ts +98 -0
  10. package/dev/src/examples/symbol.ts +2 -2
  11. package/dev/src/index.ts +12 -11
  12. package/dev/src/utils.ts +18 -4
  13. package/dist/gl.d.mts +6 -0
  14. package/dist/gl.mjs +39 -0
  15. package/dist/gl.mjs.map +1 -0
  16. package/dist/index.d.mts +2 -2
  17. package/dist/index.mjs +27 -38
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/tag.d.mts +21 -4
  20. package/dist/tag.mjs +140 -110
  21. package/dist/tag.mjs.map +1 -1
  22. package/dist/{types-Bp9VAVe3.d.mts → types-DaV9McmR.d.mts} +18 -14
  23. package/package.json +10 -4
  24. package/src/gl.ts +45 -0
  25. package/src/index.ts +1 -1
  26. package/src/tag.ts +112 -44
  27. package/src/types.ts +36 -22
  28. package/src/utils/index.ts +0 -46
  29. package/test/tag.test.ts +462 -0
  30. package/tsup.config.ts +1 -1
  31. package/dev/dist/404.html +0 -19
  32. package/dev/dist/assets/bezier-DuLTb2d1.js +0 -294
  33. package/dev/dist/assets/game_of_life-D7qHdFcv.js +0 -202
  34. package/dev/dist/assets/grid-Ie22U_9K.js +0 -173
  35. package/dev/dist/assets/index-0qrXMlfv.js +0 -109
  36. package/dev/dist/assets/index-C2N3u8wj.css +0 -12
  37. package/dev/dist/assets/main-BZ1N6pp6.js +0 -32
  38. package/dev/dist/assets/overview-DAxtMIw5.js +0 -78
  39. package/dev/dist/assets/pix_sim-DIhzM_vu.js +0 -501
  40. package/dev/dist/assets/symbol-BouRL-Ni.js +0 -65
  41. package/dev/dist/assets/tag-C_bg62fD.js +0 -516
  42. package/dev/dist/assets/tetris-IMnkSi9p.js +0 -344
  43. package/dev/dist/assets/utils-CvCgsM08.js +0 -50
  44. package/dev/dist/index.html +0 -51
@@ -1,12 +1,8 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Bash(pnpm build:*)",
5
- "Bash(grep:*)",
6
- "Bash(npm test:*)",
7
- "Bash(npm run build:*)",
8
- "Bash(rg:*)"
9
- ],
10
- "deny": []
4
+ "Bash(git add:*)",
5
+ "Bash(git commit:*)"
6
+ ]
11
7
  }
12
- }
8
+ }
package/README.md CHANGED
@@ -32,6 +32,7 @@
32
32
  - 📝 [attribute[kind](name, options?)](#-attributekindname-options)
33
33
  - 🔗 [interleave(name, layout, options?)](#-interleavename-layout-options)
34
34
  - ⚙️ [compile(gl, vertex, fragment)](#️-compilegl-vertex-fragment)
35
+ - 🔄 [compile.toQuad(gl, fragment)](#-compiletoquadgl-fragment-options)
35
36
  - 🔍 [compile.toString(shader)](#-compiletostringshader)
36
37
  - 📋 [compile.toSchema(shader)](#-compiletoschemaschader)
37
38
  - 🛠️ [Utils](#️-utils)
@@ -550,6 +551,35 @@ const vertexShader = glsl`
550
551
 
551
552
  Compiles shaders to a `WebGLProgram` and extracts typesafe schema and view.
552
553
 
554
+ ### 🔄 compile.toQuad(gl, fragment, options?)
555
+
556
+ Convenient helper for fullscreen quad rendering with fragment shaders. Automatically creates a vertex shader with a quad geometry and handles vertex buffer setup.
557
+
558
+ ```typescript
559
+ const { program, schema, view } = compile.toQuad(gl, fragmentShader)
560
+
561
+ // Ready to render - no vertex setup required
562
+ view.uniforms.time.set(performance.now())
563
+ gl.drawArrays(gl.TRIANGLES, 0, 6)
564
+ ```
565
+
566
+ **Perfect for:**
567
+ - Fragment shader effects (ray-marching, post-processing, etc.)
568
+ - Fullscreen compute-style shaders
569
+ - Quick prototyping and experimentation
570
+
571
+ **Generated vertex shader:**
572
+ - Creates `a_quad` attribute automatically
573
+ - Outputs `uv` varying (same as vertex position: `[-1,1]` range)
574
+ - Sets up clip-space quad covering the entire screen
575
+
576
+ **Parameters:**
577
+ - `gl`: WebGL rendering context
578
+ - `fragment`: Fragment shader with embedded resources
579
+ - `options`: Optional compilation options (same as `compile()`)
580
+
581
+ **Returns:** Same as `compile()` with pre-configured quad rendering
582
+
553
583
  ```typescript
554
584
  const { program, schema, view, vertex, fragment } = compile(gl, vertexShader, fragmentShader)
555
585
 
@@ -1,8 +1,8 @@
1
1
  import { attribute, compile, glsl, interleave, uniform } from 'view.gl/tag'
2
- import { createElement, cursor } from '../utils'
2
+ import { cursor, dom } from '../utils'
3
3
 
4
4
  // Create canvas and WebGL context
5
- const canvas = createElement('canvas')
5
+ const canvas = dom('canvas', { parentElement: document.body })
6
6
  canvas.width = window.innerWidth
7
7
  canvas.height = window.innerHeight
8
8
  const gl = canvas.getContext('webgl2', { antialias: true })!
@@ -357,6 +357,7 @@ updateLineData()
357
357
  /**********************************************************************************/
358
358
 
359
359
  function render() {
360
+ console.log('render!')
360
361
  // Update canvas size if window was resized
361
362
  if (canvas.width !== window.innerWidth || canvas.height !== window.innerHeight) {
362
363
  canvas.width = window.innerWidth
@@ -1,10 +1,11 @@
1
1
  import { FramebufferDefinition } from 'src/types'
2
2
  import { createFramebuffer } from 'src/utils'
3
- import { attribute, compile, glsl, uniform } from 'view.gl/tag'
3
+ import { compile, glsl, uniform } from 'view.gl/tag'
4
+ import { dom } from '../utils'
4
5
 
5
6
  let playing = false
6
7
 
7
- const canvas = document.createElement('canvas')
8
+ const canvas = dom('canvas')
8
9
  const gl = canvas.getContext('webgl', { antialias: false })!
9
10
  if (!gl) {
10
11
  throw new Error('WebGL not supported')
@@ -85,18 +86,6 @@ canvas.height = 256 * 2
85
86
  const WIDTH = canvas.width
86
87
  const HEIGHT = canvas.height
87
88
 
88
- // --- Shaders ---
89
-
90
- // Vertex shader (simple fullscreen quad)
91
- const vertex = glsl`
92
- ${attribute.vec2('a_vertex')}
93
- varying vec2 v_uv;
94
- void main() {
95
- v_uv = a_vertex * 0.5 + 0.5;
96
- gl_Position = vec4(a_vertex, 0, 1);
97
- }
98
- `
99
-
100
89
  // Fragment shader for Game of Life step
101
90
  // We read from u_texture the current state
102
91
  // Alive cells are red > 0.5, dead < 0.5
@@ -115,15 +104,17 @@ const stepFragment = glsl`
115
104
  }
116
105
 
117
106
  void main() {
107
+ vec2 uv = v_uv * 0.5 + 0.5;
108
+
118
109
  int sum = 0;
119
110
  // Iterate neighbors -1,0,1
120
111
  for (int y = -1; y <= 1; y++) {
121
112
  for (int x = -1; x <= 1; x++) {
122
113
  if (x == 0 && y == 0) continue;
123
- sum += getCell(v_uv + vec2(float(x), float(y)) * u_texelSize);
114
+ sum += getCell(uv + vec2(float(x), float(y)) * u_texelSize);
124
115
  }
125
116
  }
126
- int current = getCell(v_uv);
117
+ int current = getCell(uv);
127
118
 
128
119
  int nextState = 0;
129
120
  if (current == 1) {
@@ -144,22 +135,14 @@ const renderFragment = glsl`
144
135
  ${uniform.sampler2D('u_texture')}
145
136
 
146
137
  void main() {
147
- float cell = texture2D(u_texture, v_uv).r;
138
+ vec2 uv = v_uv * 0.5 + 0.5;
139
+ float cell = texture2D(u_texture, uv).r;
148
140
  gl_FragColor = vec4(vec3(cell), 1.0);
149
141
  }`
150
142
 
151
143
  // --- Create programs ---
152
- const { program: stepProgram, view: stepView } = compile(gl, vertex, stepFragment)
153
- const { program: renderProgram, view: renderView } = compile(gl, vertex, renderFragment, {
154
- attributes: {
155
- a_vertex: {
156
- buffer: stepView.attributes.a_vertex.buffer,
157
- },
158
- },
159
- })
160
-
161
- // Setup quad
162
- stepView.attributes.a_vertex.set(new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]))
144
+ const { program: stepProgram, view: stepView } = compile.toQuad(gl, stepFragment)
145
+ const { program: renderProgram, view: renderView } = compile.toQuad(gl, renderFragment)
163
146
 
164
147
  // Initialize two framebuffers (with their respective texture) for ping-pong
165
148
  const framebufferOptions = {
@@ -210,7 +193,7 @@ function step() {
210
193
  stepView.uniforms.u_texture.set(0)
211
194
  stepView.uniforms.u_texelSize.set(1 / WIDTH, 1 / HEIGHT)
212
195
 
213
- stepView.attributes.a_vertex.bind()
196
+ stepView.attributes.a_quad.bind()
214
197
 
215
198
  gl.drawArrays(gl.TRIANGLES, 0, 6)
216
199
  }
@@ -225,7 +208,7 @@ function render() {
225
208
  gl.bindTexture(gl.TEXTURE_2D, write.texture)
226
209
  renderView.uniforms.u_texture.set(0)
227
210
 
228
- renderView.attributes.a_vertex.bind()
211
+ renderView.attributes.a_quad.bind()
229
212
 
230
213
  gl.drawArrays(gl.TRIANGLES, 0, 6)
231
214
  }
@@ -8,13 +8,13 @@
8
8
  */
9
9
 
10
10
  import { attribute, compile, glsl, uniform } from 'view.gl/tag'
11
- import { createElement } from '../utils'
11
+ import { dom } from '../utils'
12
12
 
13
- const canvas = createElement('canvas', {
13
+ const canvas = dom('canvas', {
14
14
  width: window.innerWidth,
15
15
  height: window.innerHeight,
16
16
  parentElement: document.body,
17
- style: 'width: 100%; height: 100%',
17
+ style: { width: '100%' },
18
18
  })
19
19
 
20
20
  const gl = canvas.getContext('webgl2')!
@@ -1,7 +1,11 @@
1
1
  import { attribute, compile, glsl, uniform } from 'view.gl/tag'
2
- import { createElement, cursor } from '../utils'
2
+ import { cursor, dom } from '../utils'
3
3
 
4
- const canvas = createElement('canvas', { width: window.innerWidth, height: window.innerHeight })
4
+ const canvas = dom('canvas', {
5
+ width: window.innerWidth,
6
+ height: window.innerHeight,
7
+ parentElement: document.body,
8
+ })
5
9
  const gl = canvas.getContext('webgl2', { antialias: false })!
6
10
 
7
11
  if (!gl) {
@@ -14,7 +18,7 @@ const state = {
14
18
  elements: [] as Array<ReturnType<typeof createGridElement>>,
15
19
  }
16
20
 
17
- const container = createElement('div')
21
+ const container = dom('div', { parentElement: document.body })
18
22
  state.elements.push(createGridElement({ x: 100, y: 100 }))
19
23
 
20
24
  /**********************************************************************************/
@@ -29,28 +33,30 @@ function createGridElement(position = { x: 0, y: 0 }) {
29
33
  y: (position.y - state.position.y) / state.scale,
30
34
  }
31
35
 
32
- const element = createElement('div', {
36
+ const div = dom('div', {
33
37
  innerText: 'HALLO WORLD',
34
- style: `position: fixed;
35
- z-index: 10;
36
- left: 0px;
37
- top: 0px;
38
- transform-origin: top left;
39
- background: white;
40
- padding: 2px;
41
- border-radius: 2px;`,
38
+ style: {
39
+ position: 'fixed',
40
+ zIndex: '10',
41
+ left: '0px',
42
+ top: '0px',
43
+ transformOrigin: 'top left',
44
+ background: 'white',
45
+ padding: '2px',
46
+ borderRadius: '2px',
47
+ },
42
48
  parentElement: container,
43
49
  })
44
50
 
45
51
  function update() {
46
- element.style.transform = `translate3d(${state.position.x + position.x * state.scale}px,${
52
+ div.style.transform = `translate3d(${state.position.x + position.x * state.scale}px,${
47
53
  state.position.y + position.y * state.scale
48
54
  }px,0) scale(${state.scale})`
49
55
  }
50
56
  update()
51
57
 
52
58
  return {
53
- element,
59
+ element: div,
54
60
  position,
55
61
  update,
56
62
  }
@@ -1,7 +1,7 @@
1
1
  import { FramebufferDefinition } from 'src/types'
2
2
  import { createFramebuffer } from 'src/utils'
3
3
  import { attribute, compile, glsl, uniform } from 'view.gl/tag'
4
- import { createElement } from '../utils'
4
+ import { dom } from '../utils'
5
5
 
6
6
  export const MATERIALS = {
7
7
  SAND: {
@@ -24,36 +24,41 @@ let playing = false
24
24
  let currentMaterial: (typeof MATERIALS)[keyof typeof MATERIALS]['id'] = MATERIALS.SAND.id
25
25
 
26
26
  // Create UI container
27
- const container = createElement('div', {
28
- style: 'display: flex; flex-direction: column; align-items: center; gap: 10px;',
27
+ const container = dom('div', {
28
+ style: {
29
+ display: 'flex',
30
+ flexDirection: 'column',
31
+ alignItems: 'center',
32
+ gap: '10px',
33
+ },
29
34
  parentElement: document.body,
30
35
  })
31
36
 
32
37
  // Create material buttons
33
- const buttonContainer = createElement('div', {
38
+ const buttonContainer = dom('div', {
34
39
  style: 'display: flex; gap: 10px; margin-bottom: 10px;',
35
40
  parentElement: container,
36
41
  })
37
42
 
38
43
  Object.entries(MATERIALS).forEach(([name, material]) => {
39
- createElement('button', {
40
- textContent: name.toLowerCase(),
44
+ dom('button', {
41
45
  'data-name': name,
42
46
  'data-id': material.id.toString(),
43
- style: `padding: 5px 10px;
44
- font-size: 14px;
45
- font-family: arial;
46
- cursor: pointer;
47
- color: black;
48
- background: ${
49
- currentMaterial === material.id
50
- ? `rgb(${material.color.map(c => Math.floor(c * 255)).join(',')})`
51
- : `rgba(${material.color.map(c => Math.floor(c * 255)).join(',')}, 0.75)`
52
- };
53
- border-color: ${name === 'SAND' ? 'black' : 'white'};
54
- border: 2px solid rgb(${material.color.map(c => Math.floor(c * 255)).join(',')});
55
- border-radius: 2px;
56
- `,
47
+ textContent: name.toLowerCase(),
48
+ style: {
49
+ padding: '5px 10px',
50
+ fontSize: '14px',
51
+ fontFamily: 'arial',
52
+ cursor: 'pointer',
53
+ color: 'black',
54
+ background:
55
+ currentMaterial === material.id
56
+ ? `rgb(${material.color.map(c => Math.floor(c * 255)).join(',')})`
57
+ : `rgba(${material.color.map(c => Math.floor(c * 255)).join(',')}, 0.75)`,
58
+ borderColor: name === 'SAND' ? 'black' : 'white',
59
+ border: `2px solid rgb(${material.color.map(c => Math.floor(c * 255)).join(',')})`,
60
+ borderRadius: '2px',
61
+ },
57
62
  onclick() {
58
63
  currentMaterial = material.id
59
64
  // Update all button borders
@@ -79,7 +84,7 @@ function spray() {
79
84
  return Math.floor(Math.random() * 8) * (Math.random() < 0.5 ? 1 : -1)
80
85
  }
81
86
 
82
- const canvas = createElement('canvas', {
87
+ const canvas = dom('canvas', {
83
88
  parentElement: container,
84
89
  onmousedown() {
85
90
  const rect = canvas.getBoundingClientRect()
@@ -462,7 +467,9 @@ void main() {
462
467
  // --- Create programs ---
463
468
  const { program: stepProgram, view: stepView } = compile(gl, vertex, stepFragment)
464
469
  const { program: renderProgram, view: renderView } = compile(gl, vertex, renderFragment, {
465
- attributes: { a_vertex: { buffer: stepView.attributes.a_vertex.buffer } },
470
+ schema: {
471
+ attributes: { a_vertex: { buffer: stepView.attributes.a_vertex.buffer } },
472
+ },
466
473
  })
467
474
 
468
475
  gl.useProgram(renderProgram)