@footgun/cobalt 0.6.14 → 0.7.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.
- package/CHANGELOG.md +19 -0
- package/bundle.js +1318 -1304
- package/examples/01-primitives/index.html +1 -1
- package/examples/02-sprites/entity-sprite.js +10 -15
- package/examples/02-sprites/hdr.html +321 -0
- package/examples/02-sprites/index.html +21 -120
- package/examples/02-sprites/system-renderer.js +2 -2
- package/examples/03-tiles/index.html +87 -32
- package/examples/03-tiles/system-renderer.js +2 -2
- package/examples/04-overlay/index.html +178 -21
- package/examples/05-bloom/index.html +23 -23
- package/examples/05-bloom/system-renderer.js +2 -2
- package/examples/06-displacement/index.html +20 -112
- package/examples/06-displacement/system-renderer.js +2 -2
- package/examples/08-light/index.html +51 -123
- package/package.json +1 -1
- package/src/cobalt.js +8 -8
- package/src/sprite/public-api.js +57 -177
- package/src/sprite/sprite.js +301 -177
- package/src/sprite/sprite.wgsl +68 -87
- package/src/sprite-hdr/public-api.js +95 -0
- package/src/sprite-hdr/sprite.js +414 -0
- package/src/sprite-hdr/sprite.wgsl +101 -0
- package/src/{sprite → spritesheet}/create-sprite-quads.js +11 -11
- package/src/{sprite → spritesheet}/read-spritesheet.js +62 -28
- package/src/spritesheet/spritesheet.js +75 -0
- package/src/{tile → tile-hdr}/atlas.js +5 -3
- package/src/{tile → tile-hdr}/tile.js +15 -6
- package/examples/04-overlay/deps.js +0 -1
- package/src/overlay/constants.js +0 -1
- package/src/overlay/overlay.js +0 -343
- package/src/overlay/overlay.wgsl +0 -88
- package/src/sprite/constants.js +0 -1
- package/src/sprite/sorted-binary-insert.js +0 -45
- package/src/sprite/spritesheet.js +0 -215
- /package/examples/02-sprites/{Game.js → Global.js} +0 -0
- /package/examples/03-tiles/{Game.js → Global.js} +0 -0
- /package/examples/05-bloom/{Game.js → Global.js} +0 -0
- /package/examples/06-displacement/{Game.js → Global.js} +0 -0
- /package/examples/08-light/{Game.js → Global.js} +0 -0
- /package/src/{tile → tile-hdr}/tile.wgsl +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<title class="titleText">
|
|
5
|
+
<title class="titleText">WebGPU - Cobalt pure hardware tile rendering</title>
|
|
6
6
|
<meta name="description" content="Web GPU 2d cobalt" />
|
|
7
7
|
<meta name="author" content="Michael Reinstein" />
|
|
8
8
|
<meta name="viewport" content="width=device-width" />
|
|
@@ -51,6 +51,14 @@
|
|
|
51
51
|
display: none;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
button {
|
|
55
|
+
position: fixed;
|
|
56
|
+
left: 20px;
|
|
57
|
+
top: 20px;
|
|
58
|
+
user-select: none;
|
|
59
|
+
cursor: pointer;
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
</style>
|
|
55
63
|
</head>
|
|
56
64
|
<body>
|
|
@@ -59,8 +67,12 @@
|
|
|
59
67
|
<canvas id="viewport" width="480" height="270"></canvas>
|
|
60
68
|
</div>
|
|
61
69
|
|
|
70
|
+
<button type="button">disable fg sprite texture</button>
|
|
71
|
+
<button type="button" style="left: 180px">disable bg sprite texture</button>
|
|
72
|
+
|
|
73
|
+
|
|
62
74
|
<script type="module">
|
|
63
|
-
import
|
|
75
|
+
import Global from './Global.js'
|
|
64
76
|
import * as Cobalt from '../../bundle.js'
|
|
65
77
|
import constants from './constants.js'
|
|
66
78
|
import dat from 'https://cdn.skypack.dev/pin/dat.gui@v0.7.9-2wtQAdFH5SRwnJLDWGNz/mode=imports,min/optimized/dat.gui.js'
|
|
@@ -77,21 +89,22 @@ async function main () {
|
|
|
77
89
|
|
|
78
90
|
const viewportWidth = constants.GAME_WIDTH
|
|
79
91
|
const viewportHeight = constants.GAME_HEIGHT
|
|
80
|
-
|
|
92
|
+
Global.renderer = await Cobalt.init(canvas, viewportWidth, viewportHeight)
|
|
81
93
|
|
|
82
94
|
// instantiate all resource nodes
|
|
83
|
-
const tileAtlasNode = await Cobalt.initNode(
|
|
95
|
+
const tileAtlasNode = await Cobalt.initNode(Global.renderer, {
|
|
84
96
|
type: 'cobalt:tileAtlas',
|
|
85
97
|
refs: { },
|
|
86
98
|
options: {
|
|
87
99
|
label: 'tile atlas',
|
|
88
100
|
tileSize: 16,
|
|
89
101
|
tileScale: 1.0,
|
|
90
|
-
textureUrl: 'assets/spelunky-tiles.png'
|
|
102
|
+
textureUrl: 'assets/spelunky-tiles.png',
|
|
91
103
|
}
|
|
92
104
|
})
|
|
93
105
|
|
|
94
|
-
|
|
106
|
+
/*
|
|
107
|
+
const hdrTex = await Cobalt.initNode(Global.renderer, {
|
|
95
108
|
type: 'cobalt:fbTexture',
|
|
96
109
|
refs: { },
|
|
97
110
|
options: {
|
|
@@ -103,7 +116,7 @@ async function main () {
|
|
|
103
116
|
}
|
|
104
117
|
})
|
|
105
118
|
|
|
106
|
-
const emissiveTex = await Cobalt.initNode(
|
|
119
|
+
const emissiveTex = await Cobalt.initNode(Global.renderer, {
|
|
107
120
|
type: 'cobalt:fbTexture',
|
|
108
121
|
refs: { },
|
|
109
122
|
options: {
|
|
@@ -115,7 +128,7 @@ async function main () {
|
|
|
115
128
|
}
|
|
116
129
|
})
|
|
117
130
|
|
|
118
|
-
const bloomTex = await Cobalt.initNode(
|
|
131
|
+
const bloomTex = await Cobalt.initNode(Global.renderer, {
|
|
119
132
|
type: 'cobalt:fbTexture',
|
|
120
133
|
refs: { },
|
|
121
134
|
options: {
|
|
@@ -127,7 +140,7 @@ async function main () {
|
|
|
127
140
|
}
|
|
128
141
|
})
|
|
129
142
|
|
|
130
|
-
const bloomNode = await Cobalt.initNode(
|
|
143
|
+
const bloomNode = await Cobalt.initNode(Global.renderer, {
|
|
131
144
|
type: 'cobalt:bloom',
|
|
132
145
|
refs: {
|
|
133
146
|
// key is the var name defined in this node
|
|
@@ -155,7 +168,7 @@ async function main () {
|
|
|
155
168
|
}
|
|
156
169
|
})
|
|
157
170
|
|
|
158
|
-
const tmpTex = await Cobalt.initNode(
|
|
171
|
+
const tmpTex = await Cobalt.initNode(Global.renderer, {
|
|
159
172
|
type: 'cobalt:fbTexture',
|
|
160
173
|
refs: { },
|
|
161
174
|
options: {
|
|
@@ -166,40 +179,49 @@ async function main () {
|
|
|
166
179
|
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
|
|
167
180
|
}
|
|
168
181
|
})
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
const tileNodeBG = await Cobalt.initNode(Global.renderer, {
|
|
185
|
+
type: 'cobalt:tileHDR',
|
|
186
|
+
refs: {
|
|
187
|
+
tileAtlas: tileAtlasNode,
|
|
188
|
+
hdr: 'FRAME_TEXTURE_VIEW',
|
|
189
|
+
},
|
|
190
|
+
options: {
|
|
191
|
+
textureUrl: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR42mP4DwQACfsD/Wj6HMwAAAAASUVORK5CYII=',
|
|
192
|
+
scrollScale: 1.0,
|
|
193
|
+
loadOp: 'clear',
|
|
194
|
+
}
|
|
195
|
+
})
|
|
169
196
|
|
|
170
197
|
// instantiate all runnable nodes
|
|
171
|
-
const
|
|
172
|
-
type: 'cobalt:
|
|
198
|
+
const tileNodeBg = await Cobalt.initNode(Global.renderer, {
|
|
199
|
+
type: 'cobalt:tileHDR',
|
|
173
200
|
refs: {
|
|
174
|
-
// key is the var name defined in this node
|
|
175
|
-
// value is the var name in the cobalt resources dictionary
|
|
176
201
|
tileAtlas: tileAtlasNode,
|
|
177
|
-
hdr:
|
|
202
|
+
hdr: 'FRAME_TEXTURE_VIEW',
|
|
178
203
|
},
|
|
179
204
|
options: {
|
|
180
205
|
textureUrl: 'assets/spelunky1.png',
|
|
181
206
|
scrollScale: 0.6,
|
|
182
|
-
//zIndex: 0,
|
|
183
207
|
}
|
|
184
208
|
})
|
|
185
209
|
|
|
186
|
-
const
|
|
187
|
-
type: 'cobalt:
|
|
210
|
+
const tileNodeFg = await Cobalt.initNode(Global.renderer, {
|
|
211
|
+
type: 'cobalt:tileHDR',
|
|
188
212
|
refs: {
|
|
189
|
-
// key is the var name defined in this node
|
|
190
|
-
// value is the var name in the cobalt resources dictionary
|
|
191
213
|
tileAtlas: tileAtlasNode,
|
|
192
|
-
hdr:
|
|
214
|
+
hdr: 'FRAME_TEXTURE_VIEW',
|
|
193
215
|
},
|
|
194
216
|
options: {
|
|
195
217
|
textureUrl: 'assets/spelunky0.png',
|
|
196
218
|
scrollScale: 1.0,
|
|
197
|
-
//zIndex: 5,
|
|
198
219
|
}
|
|
199
220
|
})
|
|
200
221
|
|
|
201
222
|
|
|
202
|
-
|
|
223
|
+
/*
|
|
224
|
+
const compositeNode = await Cobalt.initNode(Global.renderer, {
|
|
203
225
|
type: 'cobalt:composite',
|
|
204
226
|
refs: {
|
|
205
227
|
hdr: hdrTex,
|
|
@@ -210,7 +232,7 @@ async function main () {
|
|
|
210
232
|
})
|
|
211
233
|
|
|
212
234
|
|
|
213
|
-
const b = await Cobalt.initNode(
|
|
235
|
+
const b = await Cobalt.initNode(Global.renderer, {
|
|
214
236
|
type: 'cobalt:fbBlit',
|
|
215
237
|
refs: {
|
|
216
238
|
in: tmpTex,
|
|
@@ -218,24 +240,57 @@ async function main () {
|
|
|
218
240
|
},
|
|
219
241
|
options: { }
|
|
220
242
|
})
|
|
243
|
+
*/
|
|
221
244
|
|
|
222
245
|
|
|
223
246
|
// use resizeViewport to init values on load:
|
|
224
|
-
resizeViewport(
|
|
247
|
+
resizeViewport(Global.renderer, window.innerWidth, window.innerHeight)
|
|
225
248
|
|
|
226
249
|
// window resize is *expensive* - best to debounce:
|
|
227
250
|
const debouncedResize = debounce(function () {
|
|
228
|
-
resizeViewport(
|
|
251
|
+
resizeViewport(Global.renderer, window.innerWidth, window.innerHeight)
|
|
229
252
|
}, 50)
|
|
230
253
|
|
|
231
254
|
window.addEventListener('resize', debouncedResize, { passive: true })
|
|
232
255
|
|
|
256
|
+
const [ button, button2 ] = document.querySelectorAll('button')
|
|
257
|
+
button.addEventListener('click', function (ev) {
|
|
258
|
+
let textureUrl = ''
|
|
259
|
+
if (ev.target.textContent === 'disable fg sprite texture') {
|
|
260
|
+
|
|
261
|
+
tileNodeFg.enabled = false
|
|
262
|
+
|
|
263
|
+
// 1x1 pixel with rg channels set to 255 to indicate discard
|
|
264
|
+
// this effectively clears the tilemap.
|
|
265
|
+
//tileNodeFg.setTexture('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR42mP4DwQACfsD/')
|
|
266
|
+
ev.target.textContent = 'enable fg sprite texture'
|
|
267
|
+
} else {
|
|
268
|
+
tileNodeFg.enabled = true
|
|
269
|
+
//tileNodeFg.setTexture('assets/spelunky0.png')
|
|
270
|
+
ev.target.textContent = 'disable fg sprite texture'
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
button2.addEventListener('click', function (ev) {
|
|
275
|
+
let textureUrl = ''
|
|
276
|
+
if (ev.target.textContent === 'disable bg sprite texture') {
|
|
277
|
+
tileNodeBg.enabled = false
|
|
278
|
+
// 1x1 pixel with rg channels set to 255 to indicate discard
|
|
279
|
+
// this effectively clears the tilemap.
|
|
280
|
+
//tileNodeBg.setTexture('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVR42mP4DwQACfsD/')
|
|
281
|
+
ev.target.textContent = 'enable bg sprite texture'
|
|
282
|
+
} else {
|
|
283
|
+
tileNodeBg.enabled = true
|
|
284
|
+
//tileNode.setTexture('assets/spelunky1.png')
|
|
285
|
+
ev.target.textContent = 'disable bg sprite texture'
|
|
286
|
+
}
|
|
287
|
+
})
|
|
233
288
|
|
|
234
289
|
|
|
235
290
|
const world = ECS.createWorld()
|
|
236
|
-
ECS.addSystem(world, rendererSystem(
|
|
291
|
+
ECS.addSystem(world, rendererSystem(Global.renderer))
|
|
237
292
|
|
|
238
|
-
Cobalt.setViewportPosition(
|
|
293
|
+
Cobalt.setViewportPosition(Global.renderer, [ 240, 135 ])
|
|
239
294
|
|
|
240
295
|
ECS.addSystem(world, function cameraLoopSystem(world) {
|
|
241
296
|
const onUpdate = function (dt) {
|
|
@@ -243,19 +298,19 @@ async function main () {
|
|
|
243
298
|
const x = (Math.sin(elapsed / 2000) * 0.5 + 0.5) * 128
|
|
244
299
|
const y = (Math.sin(elapsed / 5000) * 0.5 + 0.5) * 170
|
|
245
300
|
|
|
246
|
-
//const { tileScale } =
|
|
301
|
+
//const { tileScale } = Global.renderer.tile
|
|
247
302
|
|
|
248
|
-
Cobalt.setViewportPosition(
|
|
303
|
+
Cobalt.setViewportPosition(Global.renderer, [ x, y ])
|
|
249
304
|
}
|
|
250
305
|
|
|
251
306
|
return { onUpdate }
|
|
252
307
|
})
|
|
253
308
|
|
|
254
|
-
|
|
309
|
+
Global.world = world
|
|
255
310
|
|
|
256
311
|
|
|
257
312
|
const gameLoop = function () {
|
|
258
|
-
tick(
|
|
313
|
+
tick(Global)
|
|
259
314
|
requestAnimationFrame(gameLoop)
|
|
260
315
|
}
|
|
261
316
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Cobalt from '../../bundle.js'
|
|
2
|
-
import
|
|
2
|
+
import Global from './Global.js'
|
|
3
3
|
import { ECS } from './deps.js'
|
|
4
4
|
|
|
5
5
|
|
|
@@ -30,7 +30,7 @@ export default function createRendererSystem (renderer) {
|
|
|
30
30
|
oldSprite.spriteNode.removeSprite(oldSprite.sprite.cobaltSpriteId)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
Cobalt.draw(
|
|
33
|
+
Cobalt.draw(Global.renderer)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return { onUpdate }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<title class="titleText">
|
|
5
|
+
<title class="titleText">WebGPU - Cobalt screen space sprite overlays</title>
|
|
6
6
|
<meta name="description" content="Web GPU 2d cobalt" />
|
|
7
7
|
<meta name="author" content="Michael Reinstein" />
|
|
8
8
|
<meta name="viewport" content="width=device-width" />
|
|
@@ -66,7 +66,8 @@
|
|
|
66
66
|
<script type="module">
|
|
67
67
|
import * as Cobalt from '../../bundle.js'
|
|
68
68
|
import constants from './constants.js'
|
|
69
|
-
import
|
|
69
|
+
import debounce from 'https://cdn.skypack.dev/pin/lodash.debounce@v4.0.8-4GXU9B066R3Th6HmjZmO/lodash.debounce.js'
|
|
70
|
+
import { vec2, vec3, vec4 } from 'https://wgpu-matrix.org/dist/3.x/wgpu-matrix.module.js'
|
|
70
71
|
|
|
71
72
|
|
|
72
73
|
async function main () {
|
|
@@ -88,39 +89,195 @@ async function main () {
|
|
|
88
89
|
}
|
|
89
90
|
})
|
|
90
91
|
|
|
91
|
-
const
|
|
92
|
-
type: 'cobalt:
|
|
92
|
+
const hdrTex = await Cobalt.initNode(renderer, {
|
|
93
|
+
type: 'cobalt:fbTexture',
|
|
94
|
+
refs: { },
|
|
95
|
+
options: {
|
|
96
|
+
label: 'hdr color texture',
|
|
97
|
+
format: 'rgba16float',
|
|
98
|
+
mip_count: 1,
|
|
99
|
+
viewportScale: 1.0,
|
|
100
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
const emissiveTex = await Cobalt.initNode(renderer, {
|
|
105
|
+
type: 'cobalt:fbTexture',
|
|
106
|
+
refs: { },
|
|
107
|
+
options: {
|
|
108
|
+
label: 'hdr emissive texture',
|
|
109
|
+
format: 'rgba16float',
|
|
110
|
+
mip_count: 1,
|
|
111
|
+
viewportScale: 1.0,
|
|
112
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const bloomTex = await Cobalt.initNode(renderer, {
|
|
117
|
+
type: 'cobalt:fbTexture',
|
|
118
|
+
refs: { },
|
|
119
|
+
options: {
|
|
120
|
+
label: 'hdr bloom texture',
|
|
121
|
+
format: 'rgba16float',
|
|
122
|
+
mip_count: 7,
|
|
123
|
+
viewportScale: 0.5,
|
|
124
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.STORAGE_BINDING | GPUTextureUsage.TEXTURE_BINDING,
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
const bloomNode = await Cobalt.initNode(renderer, {
|
|
129
|
+
type: 'cobalt:bloom',
|
|
93
130
|
refs: {
|
|
94
131
|
// key is the var name defined in this node
|
|
95
132
|
// value is the var name in the cobalt resources dictionary
|
|
133
|
+
emissive: emissiveTex,
|
|
134
|
+
hdr: hdrTex,
|
|
135
|
+
bloom: bloomTex
|
|
136
|
+
},
|
|
137
|
+
options: {
|
|
138
|
+
// any extra options you want to pass to this node
|
|
139
|
+
bloom_intensity: 0.0,
|
|
140
|
+
bloom_knee: 0.0,
|
|
141
|
+
bloom_threshold: 0.1, // 1.0
|
|
142
|
+
/*
|
|
143
|
+
// sprite instance 1
|
|
144
|
+
sprite_instances: [
|
|
145
|
+
{
|
|
146
|
+
emissive_intensity: 1.0,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
emissive_intensity: 0.5,
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
*/
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
const tmpTex = await Cobalt.initNode(renderer, {
|
|
157
|
+
type: 'cobalt:fbTexture',
|
|
158
|
+
refs: { },
|
|
159
|
+
options: {
|
|
160
|
+
label: 'bloom + hdr compositing',
|
|
161
|
+
format: 'PREFERRED_TEXTURE_FORMAT',
|
|
162
|
+
mip_count: 1,
|
|
163
|
+
viewportScale: 1.0,
|
|
164
|
+
usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST | GPUTextureUsage.TEXTURE_BINDING,
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
const overlayNode = await Cobalt.initNode(renderer, {
|
|
169
|
+
type: 'cobalt:spriteHDR',
|
|
170
|
+
refs: {
|
|
96
171
|
spritesheet: spritesheet,
|
|
97
|
-
|
|
172
|
+
emissive: emissiveTex,
|
|
173
|
+
color: hdrTex,
|
|
174
|
+
},
|
|
175
|
+
options: {
|
|
176
|
+
loadOp: 'clear',
|
|
177
|
+
isScreenSpace: true
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
const compositeNode = await Cobalt.initNode(renderer, {
|
|
182
|
+
type: 'cobalt:composite',
|
|
183
|
+
refs: {
|
|
184
|
+
hdr: hdrTex,
|
|
185
|
+
bloom: bloomTex,
|
|
186
|
+
combined: tmpTex,
|
|
187
|
+
},
|
|
188
|
+
options: {
|
|
189
|
+
bloom_combine_constant: 0.0,
|
|
190
|
+
},
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
const b = await Cobalt.initNode(renderer, {
|
|
195
|
+
type: 'cobalt:fbBlit',
|
|
196
|
+
refs: {
|
|
197
|
+
in: tmpTex,
|
|
198
|
+
out: 'FRAME_TEXTURE_VIEW',
|
|
98
199
|
},
|
|
99
200
|
options: { }
|
|
100
201
|
})
|
|
101
202
|
|
|
102
203
|
|
|
103
204
|
// test sprites
|
|
104
|
-
overlayNode.addSprite('health-0.png',
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
vec4.
|
|
108
|
-
1.0,
|
|
109
|
-
|
|
110
|
-
//zIndex
|
|
205
|
+
overlayNode.addSprite('health-0.png', // name
|
|
206
|
+
vec2.fromValues(20, 20), // position
|
|
207
|
+
vec2.fromValues(1, 1), // scale
|
|
208
|
+
vec4.fromValues(0, 0, 0, 0), // tint
|
|
209
|
+
1.0, // opacity
|
|
210
|
+
Math.PI, // rotation
|
|
111
211
|
)
|
|
112
212
|
|
|
113
|
-
overlayNode.addSprite('health-0.png',
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
vec4.
|
|
117
|
-
|
|
118
|
-
0,
|
|
119
|
-
//zIndex
|
|
213
|
+
overlayNode.addSprite('health-0.png', // name
|
|
214
|
+
vec2.fromValues(150, 220), // position
|
|
215
|
+
vec2.fromValues(-2, 2), // scale
|
|
216
|
+
vec4.fromValues(0, 0, 0, 0), // tint
|
|
217
|
+
0.4, // opacity
|
|
218
|
+
0.0, // rotation
|
|
120
219
|
)
|
|
121
220
|
|
|
122
|
-
|
|
123
|
-
|
|
221
|
+
overlayNode.addSprite('health-0.png', // name
|
|
222
|
+
vec2.fromValues(300, 220), // position
|
|
223
|
+
vec2.fromValues(1, 1), // scale
|
|
224
|
+
vec4.fromValues(0, 0, 0, 0), // tint
|
|
225
|
+
0.3, // opacity
|
|
226
|
+
0.0, // rotation
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
function resizeViewport (renderer, width, height) {
|
|
230
|
+
|
|
231
|
+
const { canvas, device } = renderer
|
|
232
|
+
|
|
233
|
+
// determine which screen dimension is most constrained
|
|
234
|
+
// we floor the render scale to an integer because we get weird texture artifacts when trying to render at
|
|
235
|
+
// certain float values (e.g., 3.0145833333333334)
|
|
236
|
+
const renderScale = Math.floor(Math.min(width/constants.GAME_WIDTH, height/constants.GAME_HEIGHT))
|
|
237
|
+
|
|
238
|
+
canvas.width = Math.ceil(constants.GAME_WIDTH)
|
|
239
|
+
canvas.height = Math.ceil(constants.GAME_HEIGHT)
|
|
240
|
+
|
|
241
|
+
Cobalt.setViewportDimensions(renderer, constants.GAME_WIDTH, constants.GAME_HEIGHT)
|
|
242
|
+
|
|
243
|
+
// https://www.khronos.org/webgl/wiki/HandlingHighDPI
|
|
244
|
+
// webgl display resolution size within canvas
|
|
245
|
+
const resolution = window.devicePixelRatio || 1
|
|
246
|
+
|
|
247
|
+
// center the canvas if native window doesn't match aspect ratio
|
|
248
|
+
canvas.style.width = canvas.width * renderScale + 'px'
|
|
249
|
+
canvas.style.height = canvas.height * renderScale + 'px'
|
|
250
|
+
|
|
251
|
+
canvas.style.left = Math.round((width - canvas.width * renderScale) / 2) + 'px'
|
|
252
|
+
canvas.style.top = Math.round((height - canvas.height * renderScale) / 2) + 'px'
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
// use resizeViewport to init values on load:
|
|
257
|
+
resizeViewport(renderer, window.innerWidth, window.innerHeight)
|
|
258
|
+
|
|
259
|
+
// window resize is *expensive* - best to debounce:
|
|
260
|
+
const debouncedResize = debounce(function () {
|
|
261
|
+
resizeViewport(renderer, window.innerWidth, window.innerHeight)
|
|
262
|
+
}, 50)
|
|
263
|
+
|
|
264
|
+
window.addEventListener('resize', debouncedResize, { passive: true })
|
|
265
|
+
|
|
266
|
+
const gameLoop = function () {
|
|
267
|
+
|
|
268
|
+
const elapsed = performance.now()
|
|
269
|
+
//const x = (Math.sin(elapsed / 2000) * 0.5 + 0.5) * 128
|
|
270
|
+
//const y = (Math.sin(elapsed / 5000) * 0.5 + 0.5) * 170
|
|
271
|
+
|
|
272
|
+
//Cobalt.setViewportPosition(renderer, [ x, y ])
|
|
273
|
+
|
|
274
|
+
Cobalt.setViewportPosition(renderer, [ 240, 135 ])
|
|
275
|
+
|
|
276
|
+
Cobalt.draw(renderer)
|
|
277
|
+
requestAnimationFrame(gameLoop)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
requestAnimationFrame(gameLoop)
|
|
124
281
|
}
|
|
125
282
|
|
|
126
283
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
<title class="titleText">
|
|
5
|
+
<title class="titleText">WebGPU - Cobalt bloom postprocessing</title>
|
|
6
6
|
<meta name="description" content="Web GPU 2d cobalt" />
|
|
7
7
|
<meta name="author" content="Michael Reinstein" />
|
|
8
8
|
<meta name="viewport" content="width=device-width" />
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
</div>
|
|
64
64
|
|
|
65
65
|
<script type="module">
|
|
66
|
-
import
|
|
66
|
+
import Global from './Global.js'
|
|
67
67
|
import * as Cobalt from '../../bundle.js'
|
|
68
68
|
import constants from './constants.js'
|
|
69
69
|
import dat from 'https://cdn.skypack.dev/pin/dat.gui@v0.7.9-2wtQAdFH5SRwnJLDWGNz/mode=imports,min/optimized/dat.gui.js'
|
|
@@ -80,10 +80,10 @@ async function main () {
|
|
|
80
80
|
|
|
81
81
|
const viewportWidth = constants.GAME_WIDTH
|
|
82
82
|
const viewportHeight = constants.GAME_HEIGHT
|
|
83
|
-
|
|
83
|
+
Global.renderer = await Cobalt.init(canvas, viewportWidth, viewportHeight)
|
|
84
84
|
|
|
85
85
|
// instantiate all resource nodes
|
|
86
|
-
const hdrTex = await Cobalt.initNode(
|
|
86
|
+
const hdrTex = await Cobalt.initNode(Global.renderer, {
|
|
87
87
|
type: 'cobalt:fbTexture',
|
|
88
88
|
refs: { },
|
|
89
89
|
options: {
|
|
@@ -95,7 +95,7 @@ async function main () {
|
|
|
95
95
|
}
|
|
96
96
|
})
|
|
97
97
|
|
|
98
|
-
const spritesheet = await Cobalt.initNode(
|
|
98
|
+
const spritesheet = await Cobalt.initNode(Global.renderer, {
|
|
99
99
|
type: 'cobalt:spritesheet',
|
|
100
100
|
refs: { },
|
|
101
101
|
options: {
|
|
@@ -105,7 +105,7 @@ async function main () {
|
|
|
105
105
|
}
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
-
const emissiveTex = await Cobalt.initNode(
|
|
108
|
+
const emissiveTex = await Cobalt.initNode(Global.renderer, {
|
|
109
109
|
type: 'cobalt:fbTexture',
|
|
110
110
|
refs: { },
|
|
111
111
|
options: {
|
|
@@ -117,7 +117,7 @@ async function main () {
|
|
|
117
117
|
}
|
|
118
118
|
})
|
|
119
119
|
|
|
120
|
-
const bloomTex = await Cobalt.initNode(
|
|
120
|
+
const bloomTex = await Cobalt.initNode(Global.renderer, {
|
|
121
121
|
type: 'cobalt:fbTexture',
|
|
122
122
|
refs: { },
|
|
123
123
|
options: {
|
|
@@ -130,14 +130,14 @@ async function main () {
|
|
|
130
130
|
})
|
|
131
131
|
|
|
132
132
|
|
|
133
|
-
const spriteNode = await Cobalt.initNode(
|
|
134
|
-
type: 'cobalt:
|
|
133
|
+
const spriteNode = await Cobalt.initNode(Global.renderer, {
|
|
134
|
+
type: 'cobalt:spriteHDR',
|
|
135
135
|
refs: {
|
|
136
136
|
// key is the var name defined in this node
|
|
137
137
|
// value is the var name in the cobalt resources dictionary
|
|
138
138
|
spritesheet: spritesheet,
|
|
139
139
|
emissive: emissiveTex,
|
|
140
|
-
|
|
140
|
+
color: hdrTex,
|
|
141
141
|
},
|
|
142
142
|
options: {
|
|
143
143
|
loadOp: 'clear',
|
|
@@ -145,7 +145,7 @@ async function main () {
|
|
|
145
145
|
})
|
|
146
146
|
|
|
147
147
|
|
|
148
|
-
const bloomNode = await Cobalt.initNode(
|
|
148
|
+
const bloomNode = await Cobalt.initNode(Global.renderer, {
|
|
149
149
|
type: 'cobalt:bloom',
|
|
150
150
|
refs: {
|
|
151
151
|
// key is the var name defined in this node
|
|
@@ -173,7 +173,7 @@ async function main () {
|
|
|
173
173
|
}
|
|
174
174
|
})
|
|
175
175
|
|
|
176
|
-
const tmpTex = await Cobalt.initNode(
|
|
176
|
+
const tmpTex = await Cobalt.initNode(Global.renderer, {
|
|
177
177
|
type: 'cobalt:fbTexture',
|
|
178
178
|
refs: { },
|
|
179
179
|
options: {
|
|
@@ -185,7 +185,7 @@ async function main () {
|
|
|
185
185
|
}
|
|
186
186
|
})
|
|
187
187
|
|
|
188
|
-
const compositeNode = await Cobalt.initNode(
|
|
188
|
+
const compositeNode = await Cobalt.initNode(Global.renderer, {
|
|
189
189
|
type: 'cobalt:composite',
|
|
190
190
|
refs: {
|
|
191
191
|
hdr: hdrTex,
|
|
@@ -196,7 +196,7 @@ async function main () {
|
|
|
196
196
|
})
|
|
197
197
|
|
|
198
198
|
|
|
199
|
-
const b = await Cobalt.initNode(
|
|
199
|
+
const b = await Cobalt.initNode(Global.renderer, {
|
|
200
200
|
type: 'cobalt:fbBlit',
|
|
201
201
|
refs: {
|
|
202
202
|
in: tmpTex,
|
|
@@ -208,11 +208,11 @@ async function main () {
|
|
|
208
208
|
|
|
209
209
|
|
|
210
210
|
// use resizeViewport to init values on load:
|
|
211
|
-
resizeViewport(
|
|
211
|
+
resizeViewport(Global.renderer, window.innerWidth, window.innerHeight)
|
|
212
212
|
|
|
213
213
|
// window resize is *expensive* - best to debounce:
|
|
214
214
|
const debouncedResize = debounce(function () {
|
|
215
|
-
resizeViewport(
|
|
215
|
+
resizeViewport(Global.renderer, window.innerWidth, window.innerHeight)
|
|
216
216
|
}, 50)
|
|
217
217
|
|
|
218
218
|
window.addEventListener('resize', debouncedResize, { passive: true })
|
|
@@ -238,7 +238,7 @@ async function main () {
|
|
|
238
238
|
})
|
|
239
239
|
|
|
240
240
|
const updateFinalParams = function (bloom_intensity=40.0, bloom_combine_constant=0.68, bloom_knee=0.2, bloom_threshold=0.1) {
|
|
241
|
-
const { device } =
|
|
241
|
+
const { device } = Global.renderer
|
|
242
242
|
|
|
243
243
|
device.queue.writeBuffer(
|
|
244
244
|
compositeNode.data.params_buf,
|
|
@@ -263,9 +263,9 @@ async function main () {
|
|
|
263
263
|
|
|
264
264
|
|
|
265
265
|
const world = ECS.createWorld()
|
|
266
|
-
ECS.addSystem(world, rendererSystem(
|
|
266
|
+
ECS.addSystem(world, rendererSystem(Global.renderer))
|
|
267
267
|
|
|
268
|
-
Cobalt.setViewportPosition(
|
|
268
|
+
Cobalt.setViewportPosition(Global.renderer, [ 240, 135 ])
|
|
269
269
|
|
|
270
270
|
ECS.addSystem(world, function cameraLoopSystem(world) {
|
|
271
271
|
const onUpdate = function (dt) {
|
|
@@ -273,16 +273,16 @@ async function main () {
|
|
|
273
273
|
const x = (Math.sin(elapsed / 2000) * 0.5 + 0.5) * 128
|
|
274
274
|
const y = (Math.sin(elapsed / 5000) * 0.5 + 0.5) * 170
|
|
275
275
|
|
|
276
|
-
//const { tileScale } =
|
|
276
|
+
//const { tileScale } = Global.renderer.tile
|
|
277
277
|
|
|
278
278
|
//console.log(x, y)
|
|
279
|
-
Cobalt.setViewportPosition(
|
|
279
|
+
Cobalt.setViewportPosition(Global.renderer, [ x, y ])
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
return { onUpdate }
|
|
283
283
|
})
|
|
284
284
|
|
|
285
|
-
|
|
285
|
+
Global.world = world
|
|
286
286
|
|
|
287
287
|
// test sprites
|
|
288
288
|
const s2 = spriteEntity(world, {
|
|
@@ -303,7 +303,7 @@ async function main () {
|
|
|
303
303
|
|
|
304
304
|
|
|
305
305
|
const gameLoop = function () {
|
|
306
|
-
tick(
|
|
306
|
+
tick(Global)
|
|
307
307
|
requestAnimationFrame(gameLoop)
|
|
308
308
|
}
|
|
309
309
|
|