@footgun/cobalt 0.1.0

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -0
  3. package/bundle.js +284 -0
  4. package/cobalt2.jpeg +0 -0
  5. package/esbuild.js +20 -0
  6. package/examples/01-primitives/Game.js +8 -0
  7. package/examples/01-primitives/component-animation.js +8 -0
  8. package/examples/01-primitives/component-transform.js +13 -0
  9. package/examples/01-primitives/constants.js +6 -0
  10. package/examples/01-primitives/deps.js +2 -0
  11. package/examples/01-primitives/entity-sprite.js +47 -0
  12. package/examples/01-primitives/index.html +191 -0
  13. package/examples/01-primitives/system-renderer.js +37 -0
  14. package/examples/02-sprites/Game.js +8 -0
  15. package/examples/02-sprites/assets/spritesheet.json +6276 -0
  16. package/examples/02-sprites/assets/spritesheet.png +0 -0
  17. package/examples/02-sprites/assets/spritesheet_emissive.png +0 -0
  18. package/examples/02-sprites/component-animation.js +8 -0
  19. package/examples/02-sprites/component-transform.js +13 -0
  20. package/examples/02-sprites/constants.js +6 -0
  21. package/examples/02-sprites/deps.js +2 -0
  22. package/examples/02-sprites/entity-sprite.js +47 -0
  23. package/examples/02-sprites/index.html +310 -0
  24. package/examples/02-sprites/system-renderer.js +38 -0
  25. package/examples/03-tiles/Game.js +8 -0
  26. package/examples/03-tiles/assets/spelunky-tiles.png +0 -0
  27. package/examples/03-tiles/assets/spelunky0.png +0 -0
  28. package/examples/03-tiles/assets/spelunky1.png +0 -0
  29. package/examples/03-tiles/component-animation.js +8 -0
  30. package/examples/03-tiles/component-transform.js +13 -0
  31. package/examples/03-tiles/constants.js +6 -0
  32. package/examples/03-tiles/deps.js +2 -0
  33. package/examples/03-tiles/entity-sprite.js +47 -0
  34. package/examples/03-tiles/index.html +309 -0
  35. package/examples/03-tiles/system-renderer.js +38 -0
  36. package/examples/04-overlay/assets/spritesheet.json +22 -0
  37. package/examples/04-overlay/assets/spritesheet.png +0 -0
  38. package/examples/04-overlay/assets/spritesheet_emissive.png +0 -0
  39. package/examples/04-overlay/constants.js +6 -0
  40. package/examples/04-overlay/deps.js +1 -0
  41. package/examples/04-overlay/index.html +133 -0
  42. package/examples/05-bloom/Game.js +8 -0
  43. package/examples/05-bloom/assets/spritesheet.json +6276 -0
  44. package/examples/05-bloom/assets/spritesheet.png +0 -0
  45. package/examples/05-bloom/assets/spritesheet_emissive.png +0 -0
  46. package/examples/05-bloom/component-animation.js +8 -0
  47. package/examples/05-bloom/component-transform.js +13 -0
  48. package/examples/05-bloom/constants.js +6 -0
  49. package/examples/05-bloom/deps.js +2 -0
  50. package/examples/05-bloom/entity-sprite.js +47 -0
  51. package/examples/05-bloom/index.html +357 -0
  52. package/examples/05-bloom/system-renderer.js +38 -0
  53. package/examples/06-displacement/Game.js +8 -0
  54. package/examples/06-displacement/assets/displacement_map_repeat.jpg +0 -0
  55. package/examples/06-displacement/assets/spelunky-tiles.png +0 -0
  56. package/examples/06-displacement/assets/spelunky0.png +0 -0
  57. package/examples/06-displacement/assets/spelunky1.png +0 -0
  58. package/examples/06-displacement/component-animation.js +8 -0
  59. package/examples/06-displacement/component-transform.js +13 -0
  60. package/examples/06-displacement/constants.js +6 -0
  61. package/examples/06-displacement/deps.js +2 -0
  62. package/examples/06-displacement/entity-sprite.js +47 -0
  63. package/examples/06-displacement/index.html +350 -0
  64. package/examples/06-displacement/system-renderer.js +38 -0
  65. package/examples/07-sdl/assets/spritesheet.json +22 -0
  66. package/examples/07-sdl/assets/spritesheet.png +0 -0
  67. package/examples/07-sdl/assets/spritesheet_emissive.png +0 -0
  68. package/examples/07-sdl/main.js +109 -0
  69. package/examples/07-sdl/package.json +19 -0
  70. package/examples/08-light/Game.js +8 -0
  71. package/examples/08-light/assets/spelunky-tiles.png +0 -0
  72. package/examples/08-light/assets/spelunky0.png +0 -0
  73. package/examples/08-light/assets/spelunky1.png +0 -0
  74. package/examples/08-light/constants.js +6 -0
  75. package/examples/08-light/deps.js +2 -0
  76. package/examples/08-light/index.html +477 -0
  77. package/package.json +34 -0
  78. package/src/bloom/bloom.js +467 -0
  79. package/src/bloom/bloom.wgsl +176 -0
  80. package/src/cobalt.js +231 -0
  81. package/src/create-texture-from-buffer.js +39 -0
  82. package/src/create-texture-from-url.js +35 -0
  83. package/src/create-texture.js +46 -0
  84. package/src/deps.js +3 -0
  85. package/src/displacement/composition.wgsl +58 -0
  86. package/src/displacement/displacement-composition.ts +161 -0
  87. package/src/displacement/displacement-parameters-buffer.ts +44 -0
  88. package/src/displacement/displacement-texture.ts +221 -0
  89. package/src/displacement/displacement.js +160 -0
  90. package/src/displacement/displacement.wgsl +31 -0
  91. package/src/displacement/triangles-buffer.ts +95 -0
  92. package/src/fb-blit/fb-blit.js +161 -0
  93. package/src/fb-blit/fb-blit.wgsl +40 -0
  94. package/src/fb-texture/fb-texture.js +56 -0
  95. package/src/light/README.md +61 -0
  96. package/src/light/light.js +148 -0
  97. package/src/light/lights-buffer.ts +98 -0
  98. package/src/light/lights-renderer.ts +278 -0
  99. package/src/light/public-api.js +20 -0
  100. package/src/light/readme/01_illumination.webp +0 -0
  101. package/src/light/readme/02_lights_texture.webp +0 -0
  102. package/src/light/readme/03_lights_texture_decomposed.webp +0 -0
  103. package/src/light/readme/04_lights_texture_mask.webp +0 -0
  104. package/src/light/readme/05_lights_obstacle_decomposition.webp +0 -0
  105. package/src/light/readme/06_lights_hard_cast_shadows.webp +0 -0
  106. package/src/light/texture/lights-texture-initializer.ts +191 -0
  107. package/src/light/texture/lights-texture-mask.ts +286 -0
  108. package/src/light/texture/lights-texture.ts +121 -0
  109. package/src/light/types.ts +23 -0
  110. package/src/light/viewport.ts +63 -0
  111. package/src/overlay/constants.js +1 -0
  112. package/src/overlay/overlay.js +341 -0
  113. package/src/overlay/overlay.wgsl +88 -0
  114. package/src/primitives/constants.js +1 -0
  115. package/src/primitives/primitives.js +252 -0
  116. package/src/primitives/primitives.wgsl +54 -0
  117. package/src/primitives/public-api.js +325 -0
  118. package/src/scene-composite/scene-composite.js +168 -0
  119. package/src/scene-composite/scene-composite.wgsl +94 -0
  120. package/src/sprite/constants.js +1 -0
  121. package/src/sprite/create-sprite-quads.js +60 -0
  122. package/src/sprite/public-api.js +215 -0
  123. package/src/sprite/read-spritesheet.js +103 -0
  124. package/src/sprite/sorted-binary-insert.js +45 -0
  125. package/src/sprite/sprite.js +268 -0
  126. package/src/sprite/sprite.wgsl +103 -0
  127. package/src/sprite/spritesheet.js +212 -0
  128. package/src/tile/atlas.js +193 -0
  129. package/src/tile/tile.js +171 -0
  130. package/src/tile/tile.wgsl +105 -0
  131. package/src/uuid.js +3 -0
@@ -0,0 +1,350 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title class="titleText">Web GPU prototyping</title>
6
+ <meta name="description" content="Web GPU 2d cobalt" />
7
+ <meta name="author" content="Michael Reinstein" />
8
+ <meta name="viewport" content="width=device-width" />
9
+ <meta name="viewport" content="initial-scale=1, maximum-scale=1" />
10
+
11
+ <meta name="apple-mobile-web-app-capable" content="yes" />
12
+ <meta name="mobile-web-app-capable" content="yes" />
13
+
14
+ <style>
15
+
16
+ body {
17
+ padding-inline: 40px;
18
+ margin: 0;
19
+ overscroll-behavior: none;
20
+ }
21
+
22
+ img {
23
+ image-rendering: -moz-crisp-edges;
24
+ image-rendering: -webkit-crisp-edges;
25
+ image-rendering: pixelated;
26
+ image-rendering: crisp-edges;
27
+ }
28
+
29
+ .viewport-container {
30
+ position: fixed;
31
+ top: 0;
32
+ left: 0;
33
+ bottom: 0;
34
+ right: 0;
35
+
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ }
40
+
41
+ canvas {
42
+ background-color: green;
43
+ border: none;
44
+ image-rendering: -moz-crisp-edges;
45
+ image-rendering: -webkit-crisp-edges;
46
+ image-rendering: pixelated;
47
+ image-rendering: crisp-edges;
48
+ }
49
+
50
+ canvas::-webkit-scrollbar {
51
+ display: none;
52
+ }
53
+
54
+ </style>
55
+ </head>
56
+ <body>
57
+ <h1>Displacement Node</h1>
58
+ <p>
59
+ Useful for special effects like heat waves, etc.
60
+ </p>
61
+ <div class="viewport-container">
62
+ <canvas id="viewport" width="480" height="270"></canvas>
63
+ </div>
64
+
65
+ <script type="module">
66
+ import Game from './Game.js'
67
+ import * as Cobalt from '../../bundle.js'
68
+ import constants from './constants.js'
69
+ import dat from 'https://cdn.skypack.dev/pin/dat.gui@v0.7.9-2wtQAdFH5SRwnJLDWGNz/mode=imports,min/optimized/dat.gui.js'
70
+ import debounce from 'https://cdn.skypack.dev/pin/lodash.debounce@v4.0.8-4GXU9B066R3Th6HmjZmO/lodash.debounce.js'
71
+ import rendererSystem from './system-renderer.js'
72
+ import spriteEntity from './entity-sprite.js'
73
+ import { ECS, vec2 } from './deps.js'
74
+
75
+
76
+ async function main () {
77
+
78
+ const canvas = document.querySelector('canvas')
79
+
80
+ const viewportWidth = constants.GAME_WIDTH
81
+ const viewportHeight = constants.GAME_HEIGHT
82
+ Game.renderer = await Cobalt.init(canvas, viewportWidth, viewportHeight)
83
+
84
+ // instantiate all resource nodes
85
+ const tileAtlasNode = await Cobalt.initNode(Game.renderer, {
86
+ type: 'cobalt:tileAtlas',
87
+ refs: { },
88
+ options: {
89
+ label: 'tile atlas',
90
+ tileSize: 16,
91
+ tileScale: 1.0,
92
+ textureUrl: 'assets/spelunky-tiles.png'
93
+ }
94
+ })
95
+
96
+ const hdrTex = await Cobalt.initNode(Game.renderer, {
97
+ type: 'cobalt:fbTexture',
98
+ refs: { },
99
+ options: {
100
+ label: 'hdr color texture',
101
+ format: 'rgba16float',
102
+ mip_count: 1,
103
+ viewportScale: 1.0,
104
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
105
+ }
106
+ })
107
+
108
+ const emissiveTex = await Cobalt.initNode(Game.renderer, {
109
+ type: 'cobalt:fbTexture',
110
+ refs: { },
111
+ options: {
112
+ label: 'hdr emissive texture',
113
+ format: 'rgba16float',
114
+ mip_count: 1,
115
+ viewportScale: 1.0,
116
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
117
+ }
118
+ })
119
+
120
+ const bloomTex = await Cobalt.initNode(Game.renderer, {
121
+ type: 'cobalt:fbTexture',
122
+ refs: { },
123
+ options: {
124
+ label: 'hdr bloom texture',
125
+ format: 'rgba16float',
126
+ mip_count: 7,
127
+ viewportScale: 0.5,
128
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
129
+ }
130
+ })
131
+
132
+ const bloomNode = await Cobalt.initNode(Game.renderer, {
133
+ type: 'cobalt:bloom',
134
+ refs: {
135
+ // key is the var name defined in this node
136
+ // value is the var name in the cobalt resources dictionary
137
+ emissive: emissiveTex,
138
+ hdr: hdrTex,
139
+ bloom: bloomTex
140
+ },
141
+ options: {
142
+ // any extra options you want to pass to this node
143
+ bloom_intensity: 0.0,
144
+ bloom_combine_constant: 0.0,
145
+ bloom_knee: 0.2,
146
+ bloom_threshold: 0.1, // 1.0
147
+
148
+ // sprite instance 1
149
+ sprite_instances: [
150
+ {
151
+ emissive_intensity: 1.0,
152
+ },
153
+ {
154
+ emissive_intensity: 0.5,
155
+ },
156
+ ],
157
+ }
158
+ })
159
+
160
+ const tmpTex = await Cobalt.initNode(Game.renderer, {
161
+ type: 'cobalt:fbTexture',
162
+ refs: { },
163
+ options: {
164
+ label: 'bloom + hdr compositing',
165
+ format: 'bgra8unorm',
166
+ mip_count: 1,
167
+ viewportScale: 1.0,
168
+ usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
169
+ }
170
+ })
171
+
172
+ const perlinTex = await Cobalt.createTextureFromUrl(Game.renderer, 'displacement map', './assets/displacement_map_repeat.jpg')
173
+
174
+ // instantiate all runnable nodes
175
+ const tileNode = await Cobalt.initNode(Game.renderer, {
176
+ type: 'cobalt:tile',
177
+ refs: {
178
+ // key is the var name defined in this node
179
+ // value is the var name in the cobalt resources dictionary
180
+ tileAtlas: tileAtlasNode,
181
+ hdr: hdrTex,
182
+ },
183
+ options: {
184
+ textureUrl: 'assets/spelunky1.png',
185
+ scrollScale: 0.6,
186
+ //zIndex: 0,
187
+ }
188
+ })
189
+
190
+ const tileNode2 = await Cobalt.initNode(Game.renderer, {
191
+ type: 'cobalt:tile',
192
+ refs: {
193
+ // key is the var name defined in this node
194
+ // value is the var name in the cobalt resources dictionary
195
+ tileAtlas: tileAtlasNode,
196
+ hdr: hdrTex,
197
+ },
198
+ options: {
199
+ textureUrl: 'assets/spelunky0.png',
200
+ scrollScale: 1.0,
201
+ //zIndex: 5,
202
+ }
203
+ })
204
+
205
+
206
+ const compositeNode = await Cobalt.initNode(Game.renderer, {
207
+ type: 'cobalt:composite',
208
+ refs: {
209
+ hdr: hdrTex,
210
+ bloom: bloomTex,
211
+ combined: tmpTex,
212
+ },
213
+ options: {
214
+ bloom_combine_constant: 0.0,
215
+ }
216
+ })
217
+
218
+ const b = await Cobalt.initNode(Game.renderer, {
219
+ type: 'cobalt:fbBlit',
220
+ refs: {
221
+ in: tmpTex,
222
+ out: 'FRAME_TEXTURE_VIEW',
223
+ },
224
+ options: { }
225
+ })
226
+
227
+ const displacement = await Cobalt.initNode(Game.renderer, {
228
+ type: 'cobalt:displacement',
229
+ refs: {
230
+ color: tmpTex,
231
+ map: perlinTex,
232
+ out: 'FRAME_TEXTURE_VIEW',
233
+ },
234
+ options: {
235
+ scale: 32,
236
+ offsetX: 0,
237
+ offsetY: 0,
238
+ }
239
+ })
240
+
241
+ displacement.addTriangle([
242
+ [ 250, 85 ],
243
+ [ 210, 140 ],
244
+ [ 310, 140 ],
245
+ ])
246
+
247
+
248
+
249
+ // use resizeViewport to init values on load:
250
+ resizeViewport(Game.renderer, window.innerWidth, window.innerHeight)
251
+
252
+ // window resize is *expensive* - best to debounce:
253
+ const debouncedResize = debounce(function () {
254
+ resizeViewport(Game.renderer, window.innerWidth, window.innerHeight)
255
+ }, 50)
256
+
257
+ window.addEventListener('resize', debouncedResize, { passive: true })
258
+
259
+ const gui = new dat.GUI()
260
+
261
+ const disp = gui.addFolder('displacement')
262
+ disp.open()
263
+
264
+ disp.add(displacement.options, 'scale', 0, 100).onChange((v) => {
265
+ displacement.data.displacementParameters.setParameters(displacement.options);
266
+ })
267
+
268
+ disp.add(displacement.options, 'offsetX', 0, 512).onChange((v) => {
269
+ displacement.data.displacementParameters.setParameters(displacement.options);
270
+ })
271
+
272
+ disp.add(displacement.options, 'offsetY', 0, 512).onChange((v) => {
273
+ displacement.data.displacementParameters.setParameters(displacement.options);
274
+ })
275
+
276
+
277
+
278
+ const world = ECS.createWorld()
279
+ ECS.addSystem(world, rendererSystem(Game.renderer))
280
+
281
+ Cobalt.setViewportPosition(Game.renderer, [ 240, 135 ])
282
+
283
+ ECS.addSystem(world, function displacementSystem (world) {
284
+ const onUpdate = function (dt) {
285
+ // loop the displacement offset
286
+ //displacement.options.offsetX = (displacement.options.offsetX + 1) % perlinTex.texture.width
287
+ displacement.options.offsetY = (displacement.options.offsetY + 1) % perlinTex.texture.height
288
+
289
+ displacement.data.displacementParameters.setParameters(displacement.options);
290
+ }
291
+
292
+ return { onUpdate }
293
+ })
294
+
295
+ Game.world = world
296
+
297
+
298
+ const gameLoop = function () {
299
+ tick(Game)
300
+ requestAnimationFrame(gameLoop)
301
+ }
302
+
303
+
304
+ requestAnimationFrame(gameLoop)
305
+ }
306
+
307
+
308
+ function tick (context) {
309
+ const newTime = performance.now()
310
+ const frameTime = newTime - context.lastFrameTime
311
+ context.lastFrameTime = newTime
312
+ ECS.update(context.world, frameTime)
313
+ ECS.cleanup(context.world)
314
+ }
315
+
316
+
317
+ function resizeViewport (renderer, width, height) {
318
+
319
+ const { canvas, device } = renderer
320
+
321
+ // determine which screen dimension is most constrained
322
+ // we floor the render scale to an integer because we get weird texture artifacts when trying to render at
323
+ // certain float values (e.g., 3.0145833333333334)
324
+ const renderScale = Math.floor(Math.min(width/constants.GAME_WIDTH, height/constants.GAME_HEIGHT))
325
+
326
+ canvas.width = Math.ceil(constants.GAME_WIDTH)
327
+ canvas.height = Math.ceil(constants.GAME_HEIGHT)
328
+
329
+ Cobalt.setViewportDimensions(renderer, constants.GAME_WIDTH, constants.GAME_HEIGHT)
330
+
331
+ // https://www.khronos.org/webgl/wiki/HandlingHighDPI
332
+ // webgl display resolution size within canvas
333
+ const resolution = window.devicePixelRatio || 1
334
+
335
+ // center the canvas if native window doesn't match aspect ratio
336
+ canvas.style.width = canvas.width * renderScale + 'px'
337
+ canvas.style.height = canvas.height * renderScale + 'px'
338
+
339
+ canvas.style.left = Math.round((width - canvas.width * renderScale) / 2) + 'px'
340
+ canvas.style.top = Math.round((height - canvas.height * renderScale) / 2) + 'px'
341
+ }
342
+
343
+
344
+ main()
345
+
346
+ </script>
347
+
348
+
349
+ </body>
350
+ </html>
@@ -0,0 +1,38 @@
1
+ import * as Cobalt from '../../bundle.js'
2
+ import Game from './Game.js'
3
+ import { ECS } from './deps.js'
4
+
5
+
6
+ const SPRITE_QUERY = [ 'sprite' ]
7
+
8
+
9
+ // @param Object renderer Cobalt render state
10
+ export default function createRendererSystem (renderer) {
11
+
12
+ // temporary variables, allocated once to avoid garbage collection
13
+ const buf = new Float32Array(136) // tile instance data stored in a UBO
14
+ const removedEntities = {
15
+ count: 0,
16
+ entries: new Array(100)
17
+ }
18
+
19
+ return function rendererSystem (world) {
20
+
21
+ const onUpdate = function (/*dt*/) {
22
+
23
+ const device = renderer.device
24
+ const context = renderer.context
25
+
26
+ ECS.getEntities(world, SPRITE_QUERY, 'removed', removedEntities)
27
+
28
+ for (let i=0; i < removedEntities.count; i++) {
29
+ const oldSprite = removedEntities.entries[i]
30
+ oldSprite.spriteNode.removeSprite(oldSprite.sprite.cobaltSpriteId)
31
+ }
32
+
33
+ Cobalt.draw(Game.renderer)
34
+ }
35
+
36
+ return { onUpdate }
37
+ }
38
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "frames": {
3
+ "health-0.png":
4
+ {
5
+ "frame": {"x":924,"y":369,"w":14,"h":15},
6
+ "rotated": false,
7
+ "trimmed": false,
8
+ "spriteSourceSize": {"x":0,"y":0,"w":14,"h":15},
9
+ "sourceSize": {"w":14,"h":15}
10
+ }
11
+
12
+ },
13
+ "meta": {
14
+ "app": "https://www.codeandweb.com/texturepacker",
15
+ "version": "1.0",
16
+ "image": "spritesheet.png",
17
+ "format": "RGBA8888",
18
+ "size": {"w":1024,"h":1024},
19
+ "scale": "1",
20
+ "smartupdate": "$TexturePacker:SmartUpdate:b764ee9c12c5dc939f41397531cf84b9:41d72789a4b56c697e70e42eff410840:729adc6043343cfda41c447ce8f464d6$"
21
+ }
22
+ }
@@ -0,0 +1,109 @@
1
+ import * as Cobalt from '../../bundle.js'
2
+ import sdl from '@kmamal/sdl'
3
+ import gpu from '@kmamal/gpu'
4
+ import { PNG } from 'pngjs'
5
+ import fs from 'node:fs'
6
+ import path from 'node:path'
7
+ import { fileURLToPath } from 'node:url'
8
+ import { vec3, vec4 } from 'wgpu-matrix'
9
+
10
+
11
+ const __dirname = fileURLToPath(new URL('.', import.meta.url))
12
+
13
+
14
+ async function main () {
15
+ const window = sdl.video.createWindow({ webgpu: true, width: 480, height: 270 })
16
+
17
+ window.setTitle('examples/07-sdl')
18
+
19
+ //const { pixelWidth: width, pixelHeight: height } = window
20
+ const width = 480
21
+ const height = 270
22
+
23
+ const c = await Cobalt.init({ sdlWindow: window, gpu }, width, height)
24
+
25
+ // instantiate all resource nodes
26
+ const spriteSheetJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'assets/spritesheet.json'), 'utf8'))
27
+
28
+ const pngData = await fs.promises.readFile(path.join(__dirname, 'assets/spritesheet.png'))
29
+ const colorTexture = PNG.sync.read(pngData)
30
+
31
+ const pngData2 = await fs.promises.readFile(path.join(__dirname, 'assets/spritesheet_emissive.png'))
32
+ const emissiveTexture = PNG.sync.read(pngData2)
33
+
34
+
35
+
36
+ const pNode = await Cobalt.initNode(c, {
37
+ type: 'cobalt:primitives',
38
+ refs: {
39
+ // key is the var name defined in this node
40
+ // value is the var name in the cobalt resources dictionary
41
+ color: 'FRAME_TEXTURE_VIEW',
42
+ },
43
+ options: {
44
+ //zIndex: 5,
45
+ }
46
+ })
47
+
48
+ // start end color width
49
+ pNode.line([ 0, 0 ], [ 479, 269 ], [ 1, 0, 0, 1 ], 5)
50
+ pNode.line([ 100, 10 ], [ 100, 100 ], [ 1, 1, 0, 1 ], 1)
51
+ pNode.line([ 450, 10 ], [ 100, 100 ], [ 0, 1, 1, 1 ], 1)
52
+
53
+ pNode.filledEllipse([ 180, 80 ], 20, 40, 20, [ 1, 0, 1, 0.6 ])
54
+
55
+ pNode.filledEllipse([ 192, 140 ], 8, 8, 20, [ 1, 1, 1, 0.9 ])
56
+
57
+ pNode.filledBox([ 50, 170 ], 42, 23, [ 0, 1, 0, 1 ])
58
+
59
+ pNode.box([ 120, 130 ], 42, 23, [ 1, 0, 1, 1 ], 1)
60
+
61
+
62
+
63
+ const spritesheet = await Cobalt.initNode(c, {
64
+ type: 'cobalt:spritesheet',
65
+ refs: { },
66
+ options: {
67
+ spriteSheetJson,
68
+ colorTexture,
69
+ emissiveTexture,
70
+ }
71
+ })
72
+
73
+
74
+ const overlayNode = await Cobalt.initNode(c, {
75
+ type: 'cobalt:overlay',
76
+ refs: {
77
+ // key is the var name defined in this node
78
+ // value is the var name in the cobalt resources dictionary
79
+ spritesheet: spritesheet,
80
+ color: 'FRAME_TEXTURE_VIEW',
81
+ },
82
+ options: { }
83
+ })
84
+
85
+ // test sprites
86
+ overlayNode.addSprite('health-0.png', // name
87
+ [ 20, 20 ], // position
88
+ vec3.create(1, 1, 1),
89
+ vec4.create(0, 0, 0, 0), // tint
90
+ 1.0, // opacity
91
+ 0, // rotation
92
+ //zIndex
93
+ )
94
+
95
+ overlayNode.addSprite('health-0.png', // name
96
+ [ 420, 220 ], // position
97
+ vec3.create(1, 1, 1),
98
+ vec4.create(0, 0, 0, 0), // tint
99
+ 1.0, // opacity
100
+ 0, // rotation
101
+ //zIndex
102
+ )
103
+
104
+ Cobalt.setViewportDimensions(c, width, height)
105
+ Cobalt.draw(c)
106
+ }
107
+
108
+
109
+ main()
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "07-sdl",
3
+ "private": true,
4
+ "type": "module",
5
+ "version": "1.0.0",
6
+ "description": "test module using sdl + gpu + cobalt",
7
+ "main": "main.js",
8
+ "scripts": {
9
+ "test": "echo \"Error: no test specified\" && exit 1"
10
+ },
11
+ "author": "",
12
+ "license": "ISC",
13
+ "dependencies": {
14
+ "@kmamal/gpu": "^0.1.3",
15
+ "@kmamal/sdl": "^0.10.2",
16
+ "pngjs": "^7.0.0",
17
+ "wgpu-matrix": "^3.0.2"
18
+ }
19
+ }
@@ -0,0 +1,8 @@
1
+ // all of the example's globals are consolidated here
2
+ export default {
3
+ renderer: undefined, // cobalt instance
4
+ world: undefined, // ECS instance
5
+
6
+ // timekeeping (in milliseconds)
7
+ lastFrameTime: 0, // local time the last frame ran
8
+ }
@@ -0,0 +1,6 @@
1
+
2
+ export default {
3
+ // virtual game screen dimensions in 16:9
4
+ GAME_WIDTH: 480,
5
+ GAME_HEIGHT: 270,
6
+ }
@@ -0,0 +1,2 @@
1
+ export { default as ECS } from 'https://cdn.skypack.dev/pin/ecs@v0.21.0-P934LlnmSF5QgmGODbyN/mode=imports/optimized/ecs.js'
2
+ export { mat4, vec2, vec3, vec4 } from 'https://wgpu-matrix.org/dist/3.x/wgpu-matrix.module.js'