@footgun/cobalt 0.10.0 → 0.11.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.
@@ -1,13 +1,20 @@
1
- import { LIGHTS_BUFFER_STRUCTS } from '../lights-buffer.js'
2
-
3
- // Creates the shadow/occlusion mask pass resources.
4
- // Returns a plain object with all mask state; mutate it via the free functions below.
5
- export function createLightsTextureMask(device, lightsBufferGpu, lightsTexture, uniformLightSize) {
6
- const obstaclesAreTwoWay = true
7
-
8
- const shaderModule = device.createShaderModule({
9
- label: 'LightsTextureMask shader module',
10
- code: `
1
+ import { LightsBuffer } from "../lights-buffer.js";
2
+
3
+ class LightsTextureMask {
4
+ device;
5
+ renderPipeline;
6
+ renderBundleEncoderDescriptor;
7
+ renderBundle;
8
+ lightsBuffer;
9
+ indirectDrawing;
10
+ obstacles = null;
11
+ constructor(device, lightsBuffer, lightsTexture, uniformLightSize) {
12
+ this.device = device;
13
+ this.lightsBuffer = lightsBuffer;
14
+ const obstaclesAreTwoWay = true;
15
+ const shaderModule = device.createShaderModule({
16
+ label: "LightsTextureMask shader module",
17
+ code: `
11
18
  struct VertexIn {
12
19
  @builtin(instance_index) lightIndex: u32,
13
20
  @location(0) position: vec3<f32>,
@@ -65,191 +72,164 @@ fn main_fragment(in: VertexOut) -> FragmentOut {
65
72
  out.color = in.color;
66
73
  return out;
67
74
  }
68
- `,
69
- })
70
-
71
- const maskPipeline = device.createRenderPipeline({
72
- label: 'LightsTextureMask renderpipeline',
73
- layout: 'auto',
74
- vertex: {
75
- module: shaderModule,
76
- entryPoint: 'main_vertex',
77
- buffers: [
78
- {
79
- attributes: [
80
- {
81
- shaderLocation: 0,
82
- offset: 0,
83
- format: 'float32x3',
84
- },
85
- ],
86
- arrayStride: 3 * Float32Array.BYTES_PER_ELEMENT,
87
- stepMode: 'vertex',
88
- },
89
- {
90
- attributes: [
91
- {
92
- shaderLocation: 1,
93
- offset: LIGHTS_BUFFER_STRUCTS.light.radius.offset,
94
- format: 'float32',
95
- },
96
- {
97
- shaderLocation: 2,
98
- offset: LIGHTS_BUFFER_STRUCTS.light.position.offset,
99
- format: 'float32x2',
100
- },
101
- ],
102
- arrayStride: LIGHTS_BUFFER_STRUCTS.lightsBuffer.lights.stride,
103
- stepMode: 'instance',
104
- },
105
- ],
106
- },
107
- fragment: {
108
- module: shaderModule,
109
- entryPoint: 'main_fragment',
110
- targets: [
111
- {
112
- format: lightsTexture.format,
113
- blend: {
114
- color: {
115
- operation: 'min',
116
- srcFactor: 'one',
117
- dstFactor: 'one',
118
- },
119
- alpha: {
120
- operation: 'min',
121
- srcFactor: 'one',
122
- dstFactor: 'one',
123
- },
75
+ `,
76
+ });
77
+ this.renderPipeline = device.createRenderPipeline({
78
+ label: "LightsTextureMask renderpipeline",
79
+ layout: "auto",
80
+ vertex: {
81
+ module: shaderModule,
82
+ entryPoint: "main_vertex",
83
+ buffers: [
84
+ {
85
+ attributes: [
86
+ {
87
+ shaderLocation: 0,
88
+ offset: 0,
89
+ format: "float32x3",
90
+ },
91
+ ],
92
+ arrayStride: 3 * Float32Array.BYTES_PER_ELEMENT,
93
+ stepMode: "vertex",
124
94
  },
125
- },
126
- ],
127
- },
128
- primitive: {
129
- cullMode: obstaclesAreTwoWay ? 'none' : 'back',
130
- topology: 'triangle-list',
131
- },
132
- multisample: {
133
- count: lightsTexture.sampleCount,
134
- },
135
- })
136
-
137
- const maskIndirectBufferCpu = new ArrayBuffer(20)
138
- const maskIndirectBufferGpu = device.createBuffer({
139
- label: 'LightsTextureMask indirect buffer',
140
- size: 20,
141
- usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_DST,
142
- })
143
-
144
- const maskRenderBundleDescriptor = {
145
- label: 'LightsTextureMask renderbundle encoder',
146
- colorFormats: [lightsTexture.format],
147
- sampleCount: lightsTexture.sampleCount,
95
+ {
96
+ attributes: [
97
+ {
98
+ shaderLocation: 1,
99
+ offset: LightsBuffer.structs.light.radius.offset,
100
+ format: "float32",
101
+ },
102
+ {
103
+ shaderLocation: 2,
104
+ offset: LightsBuffer.structs.light.position.offset,
105
+ format: "float32x2",
106
+ },
107
+ ],
108
+ arrayStride: LightsBuffer.structs.lightsBuffer.lights.stride,
109
+ stepMode: "instance",
110
+ },
111
+ ],
112
+ },
113
+ fragment: {
114
+ module: shaderModule,
115
+ entryPoint: "main_fragment",
116
+ targets: [{
117
+ format: lightsTexture.format,
118
+ blend: {
119
+ color: {
120
+ operation: "min",
121
+ srcFactor: "one",
122
+ dstFactor: "one",
123
+ },
124
+ alpha: {
125
+ operation: "min",
126
+ srcFactor: "one",
127
+ dstFactor: "one",
128
+ },
129
+ },
130
+ }],
131
+ },
132
+ primitive: {
133
+ cullMode: obstaclesAreTwoWay ? "none" : "back",
134
+ topology: "triangle-list",
135
+ },
136
+ multisample: {
137
+ count: lightsTexture.sampleCount,
138
+ },
139
+ });
140
+ this.indirectDrawing = {
141
+ bufferCpu: new ArrayBuffer(20),
142
+ bufferGpu: device.createBuffer({
143
+ label: "LightsTextureMask indirect buffer",
144
+ size: 20,
145
+ usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_DST,
146
+ }),
147
+ };
148
+ this.uploadIndirectDrawingBuffer();
149
+ this.renderBundleEncoderDescriptor = {
150
+ label: "LightsTextureMask renderbundle encoder",
151
+ colorFormats: [lightsTexture.format],
152
+ sampleCount: lightsTexture.sampleCount,
153
+ };
154
+ this.renderBundle = this.buildRenderBundle();
148
155
  }
149
-
150
- const mask = {
151
- maskPipeline,
152
- maskRenderBundleDescriptor,
153
- maskRenderBundle: null,
154
- maskIndirectBufferCpu,
155
- maskIndirectBufferGpu,
156
- maskObstacles: null,
157
- lightsBufferGpu,
156
+ getRenderBundle() {
157
+ return this.renderBundle;
158
158
  }
159
-
160
- uploadMaskIndirectBuffer(device, mask)
161
- mask.maskRenderBundle = buildMaskRenderBundle(device, mask)
162
-
163
- return mask
164
- }
165
-
166
- export function setMaskObstacles(device, data, segments) {
167
- const positions = []
168
- const indices = []
169
- for (const segment of segments) {
170
- const firstQuadIndex = positions.length / 3
171
- positions.push(...segment[0], 0, ...segment[1], 0, ...segment[0], 1, ...segment[1], 1)
172
- indices.push(
173
- firstQuadIndex + 0,
174
- firstQuadIndex + 1,
175
- firstQuadIndex + 3,
176
- firstQuadIndex + 0,
177
- firstQuadIndex + 3,
178
- firstQuadIndex + 2,
179
- )
159
+ setObstacles(segments) {
160
+ const positions = [];
161
+ const indices = [];
162
+ for (const segment of segments) {
163
+ const firstQuadIndex = positions.length / 3;
164
+ positions.push(...segment[0], 0, ...segment[1], 0, ...segment[0], 1, ...segment[1], 1);
165
+ indices.push(firstQuadIndex + 0, firstQuadIndex + 1, firstQuadIndex + 3, firstQuadIndex + 0, firstQuadIndex + 3, firstQuadIndex + 2);
166
+ }
167
+ let gpuBuffersChanged = false;
168
+ const positionsArray = new Float32Array(positions);
169
+ let positionsBufferGpu = this.obstacles?.positionsBufferGpu;
170
+ if (!positionsBufferGpu || positionsBufferGpu.size < positionsArray.byteLength) {
171
+ positionsBufferGpu?.destroy();
172
+ positionsBufferGpu = this.device.createBuffer({
173
+ label: "LightsTextureMask positions buffer",
174
+ size: positionsArray.byteLength,
175
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
176
+ });
177
+ gpuBuffersChanged = true;
178
+ }
179
+ this.device.queue.writeBuffer(positionsBufferGpu, 0, positionsArray);
180
+ const indicesArray = new Uint16Array(indices);
181
+ let indexBufferGpu = this.obstacles?.indexBufferGpu;
182
+ if (!indexBufferGpu || indexBufferGpu.size < indicesArray.byteLength) {
183
+ indexBufferGpu?.destroy();
184
+ indexBufferGpu = this.device.createBuffer({
185
+ label: "LightsTextureMask index buffer",
186
+ size: indicesArray.byteLength,
187
+ usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
188
+ });
189
+ gpuBuffersChanged = true;
190
+ }
191
+ this.device.queue.writeBuffer(indexBufferGpu, 0, indicesArray);
192
+ this.obstacles = { positionsBufferGpu, indexBufferGpu };
193
+ this.setIndirectIndexCount(indices.length);
194
+ if (gpuBuffersChanged) {
195
+ this.renderBundle = this.buildRenderBundle();
196
+ }
180
197
  }
181
-
182
- let gpuBuffersChanged = false
183
-
184
- const positionsArray = new Float32Array(positions)
185
- let positionsBufferGpu = data.maskObstacles?.positionsBufferGpu
186
- if (!positionsBufferGpu || positionsBufferGpu.size < positionsArray.byteLength) {
187
- positionsBufferGpu?.destroy()
188
- positionsBufferGpu = device.createBuffer({
189
- label: 'LightsTextureMask positions buffer',
190
- size: positionsArray.byteLength,
191
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
192
- })
193
- gpuBuffersChanged = true
198
+ setLightsCount(count) {
199
+ this.setIndirectInstanceCount(count);
194
200
  }
195
- device.queue.writeBuffer(positionsBufferGpu, 0, positionsArray)
196
-
197
- const indicesArray = new Uint16Array(indices)
198
- let indexBufferGpu = data.maskObstacles?.indexBufferGpu
199
- if (!indexBufferGpu || indexBufferGpu.size < indicesArray.byteLength) {
200
- indexBufferGpu?.destroy()
201
- indexBufferGpu = device.createBuffer({
202
- label: 'LightsTextureMask index buffer',
203
- size: indicesArray.byteLength,
204
- usage: GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST,
205
- })
206
- gpuBuffersChanged = true
201
+ destroy() {
202
+ this.indirectDrawing.bufferGpu.destroy();
203
+ this.obstacles?.positionsBufferGpu.destroy();
204
+ this.obstacles?.indexBufferGpu.destroy();
207
205
  }
208
- device.queue.writeBuffer(indexBufferGpu, 0, indicesArray)
209
-
210
- data.maskObstacles = { positionsBufferGpu, indexBufferGpu }
211
-
212
- const params = new Uint32Array(data.maskIndirectBufferCpu)
213
- if (params[0] !== indices.length) {
214
- params[0] = indices.length
215
- uploadMaskIndirectBuffer(device, data)
206
+ setIndirectIndexCount(indexCount) {
207
+ const drawIndexedIndirectParameters = new Uint32Array(this.indirectDrawing.bufferCpu);
208
+ if (drawIndexedIndirectParameters[0] !== indexCount) {
209
+ drawIndexedIndirectParameters[0] = indexCount;
210
+ this.uploadIndirectDrawingBuffer();
211
+ }
216
212
  }
217
-
218
- if (gpuBuffersChanged) {
219
- data.maskRenderBundle = buildMaskRenderBundle(device, data)
213
+ setIndirectInstanceCount(instanceCount) {
214
+ const drawIndexedIndirectParameters = new Uint32Array(this.indirectDrawing.bufferCpu);
215
+ if (drawIndexedIndirectParameters[1] !== instanceCount) {
216
+ drawIndexedIndirectParameters[1] = instanceCount;
217
+ this.uploadIndirectDrawingBuffer();
218
+ }
220
219
  }
221
- }
222
-
223
- export function setMaskLightsCount(device, data, count) {
224
- const params = new Uint32Array(data.maskIndirectBufferCpu)
225
- if (params[1] !== count) {
226
- params[1] = count
227
- uploadMaskIndirectBuffer(device, data)
220
+ buildRenderBundle() {
221
+ const renderBundleEncoder = this.device.createRenderBundleEncoder(this.renderBundleEncoderDescriptor);
222
+ if (this.obstacles) {
223
+ renderBundleEncoder.setPipeline(this.renderPipeline);
224
+ renderBundleEncoder.setVertexBuffer(0, this.obstacles.positionsBufferGpu);
225
+ renderBundleEncoder.setVertexBuffer(1, this.lightsBuffer.gpuBuffer, LightsBuffer.structs.lightsBuffer.lights.offset);
226
+ renderBundleEncoder.setIndexBuffer(this.obstacles.indexBufferGpu, "uint16");
227
+ renderBundleEncoder.drawIndexedIndirect(this.indirectDrawing.bufferGpu, 0);
228
+ }
229
+ return renderBundleEncoder.finish({ label: "LightsTextureMask renderbundle" });
228
230
  }
229
- }
230
-
231
- export function destroyMask(data) {
232
- data.maskIndirectBufferGpu.destroy()
233
- data.maskObstacles?.positionsBufferGpu.destroy()
234
- data.maskObstacles?.indexBufferGpu.destroy()
235
- }
236
-
237
- function buildMaskRenderBundle(device, data) {
238
- const renderBundleEncoder = device.createRenderBundleEncoder(data.maskRenderBundleDescriptor)
239
- if (data.maskObstacles) {
240
- renderBundleEncoder.setPipeline(data.maskPipeline)
241
- renderBundleEncoder.setVertexBuffer(0, data.maskObstacles.positionsBufferGpu)
242
- renderBundleEncoder.setVertexBuffer(
243
- 1,
244
- data.lightsBufferGpu,
245
- LIGHTS_BUFFER_STRUCTS.lightsBuffer.lights.offset,
246
- )
247
- renderBundleEncoder.setIndexBuffer(data.maskObstacles.indexBufferGpu, 'uint16')
248
- renderBundleEncoder.drawIndexedIndirect(data.maskIndirectBufferGpu, 0)
231
+ uploadIndirectDrawingBuffer() {
232
+ this.device.queue.writeBuffer(this.indirectDrawing.bufferGpu, 0, this.indirectDrawing.bufferCpu);
249
233
  }
250
- return renderBundleEncoder.finish({ label: 'LightsTextureMask renderbundle' })
251
- }
252
-
253
- function uploadMaskIndirectBuffer(device, data) {
254
- device.queue.writeBuffer(data.maskIndirectBufferGpu, 0, data.maskIndirectBufferCpu)
255
234
  }
235
+ export { LightsTextureMask };
@@ -0,0 +1,85 @@
1
+ import { LightsTextureInitializer } from "./lights-texture-initializer.js";
2
+ import { LightsTextureMask } from "./lights-texture-mask.js";
3
+
4
+ class LightsTexture {
5
+ lightsBuffer;
6
+ texture;
7
+ gridSize;
8
+ textureMultisampled = null;
9
+ textureRenderpassDescriptor;
10
+ textureInitializer;
11
+ textureMask;
12
+ constructor(device, lightsBuffer, lightsTextureProperties) {
13
+ this.lightsBuffer = lightsBuffer;
14
+ const cellsCount = this.lightsBuffer.maxLightsCount / 4;
15
+ const gridSize = {
16
+ x: Math.ceil(Math.sqrt(cellsCount)),
17
+ y: 0,
18
+ };
19
+ gridSize.y = Math.ceil(cellsCount / gridSize.x);
20
+ this.gridSize = gridSize;
21
+ const lightTextureSize = {
22
+ width: gridSize.x * lightsTextureProperties.resolutionPerLight,
23
+ height: gridSize.y * lightsTextureProperties.resolutionPerLight,
24
+ };
25
+ const format = lightsTextureProperties.textureFormat;
26
+ this.texture = device.createTexture({
27
+ label: "LightsTextureMask texture",
28
+ size: [lightTextureSize.width, lightTextureSize.height],
29
+ format,
30
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
31
+ });
32
+ if (lightsTextureProperties.antialiased) {
33
+ this.textureMultisampled = device.createTexture({
34
+ label: "LightsTextureMask texture multisampled",
35
+ size: [lightTextureSize.width, lightTextureSize.height],
36
+ format,
37
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
38
+ sampleCount: 4,
39
+ });
40
+ }
41
+ const textureToRenderTo = this.textureMultisampled ?? this.texture;
42
+ const textureRenderpassColorAttachment = {
43
+ view: textureToRenderTo.createView(),
44
+ clearValue: [0, 0, 0, 1],
45
+ loadOp: "load",
46
+ storeOp: "store",
47
+ };
48
+ if (lightsTextureProperties.antialiased) {
49
+ textureRenderpassColorAttachment.resolveTarget = this.texture.createView();
50
+ }
51
+ this.textureRenderpassDescriptor = {
52
+ label: "lights-renderer render to texture renderpass",
53
+ colorAttachments: [textureRenderpassColorAttachment],
54
+ };
55
+ const lightsTexture = {
56
+ gridSize,
57
+ format,
58
+ sampleCount: this.textureMultisampled?.sampleCount ?? 1,
59
+ };
60
+ this.textureInitializer = new LightsTextureInitializer(device, lightsBuffer, lightsTexture, lightsTextureProperties.maxLightSize);
61
+ this.textureMask = new LightsTextureMask(device, lightsBuffer, lightsTexture, lightsTextureProperties.maxLightSize);
62
+ }
63
+ update(commandEncoder) {
64
+ this.textureMask.setLightsCount(this.lightsBuffer.lightsCount);
65
+ const renderpassEncoder = commandEncoder.beginRenderPass(this.textureRenderpassDescriptor);
66
+ const [textureWidth, textureHeight] = [this.texture.width, this.texture.height];
67
+ renderpassEncoder.setViewport(0, 0, textureWidth, textureHeight, 0, 1);
68
+ renderpassEncoder.setScissorRect(0, 0, textureWidth, textureHeight);
69
+ renderpassEncoder.executeBundles([
70
+ this.textureInitializer.getRenderBundle(),
71
+ this.textureMask.getRenderBundle(),
72
+ ]);
73
+ renderpassEncoder.end();
74
+ }
75
+ setObstacles(segments) {
76
+ this.textureMask.setObstacles(segments);
77
+ }
78
+ destroy() {
79
+ this.texture.destroy();
80
+ this.textureMultisampled?.destroy();
81
+ this.textureInitializer.destroy();
82
+ this.textureMask.destroy();
83
+ }
84
+ }
85
+ export { LightsTexture };
@@ -0,0 +1,40 @@
1
+ import * as wgpuMatrix from "wgpu-matrix";
2
+
3
+ class Viewport {
4
+ invViewProjectionMatrix = wgpuMatrix.mat4.identity();
5
+ viewportSize = { width: 1, height: 1 };
6
+ topLeft = [0, 0];
7
+ zoom = 1;
8
+ constructor(params) {
9
+ this.setViewportSize(params.viewportSize.width, params.viewportSize.height);
10
+ const initialTopLeft = params.center ?? this.topLeft;
11
+ this.setTopLeft(...initialTopLeft);
12
+ const initialZoom = params.zoom ?? 1;
13
+ this.setZoom(initialZoom);
14
+ }
15
+ get invertViewProjectionMatrix() {
16
+ return this.invViewProjectionMatrix;
17
+ }
18
+ setViewportSize(width, height) {
19
+ this.viewportSize.width = width;
20
+ this.viewportSize.height = height;
21
+ this.updateMatrices();
22
+ }
23
+ setTopLeft(x, y) {
24
+ this.topLeft[0] = x;
25
+ this.topLeft[1] = y;
26
+ this.updateMatrices();
27
+ }
28
+ setZoom(zoom) {
29
+ this.zoom = zoom;
30
+ this.updateMatrices();
31
+ }
32
+ updateMatrices() {
33
+ wgpuMatrix.mat4.identity(this.invViewProjectionMatrix);
34
+ wgpuMatrix.mat4.multiply(wgpuMatrix.mat4.scaling([1, -1, 0]), this.invViewProjectionMatrix, this.invViewProjectionMatrix);
35
+ wgpuMatrix.mat4.multiply(wgpuMatrix.mat4.translation([1, 1, 0]), this.invViewProjectionMatrix, this.invViewProjectionMatrix);
36
+ wgpuMatrix.mat4.multiply(wgpuMatrix.mat4.scaling([0.5 * this.viewportSize.width / this.zoom, 0.5 * this.viewportSize.height / this.zoom, 0]), this.invViewProjectionMatrix, this.invViewProjectionMatrix);
37
+ wgpuMatrix.mat4.multiply(wgpuMatrix.mat4.translation([this.topLeft[0], this.topLeft[1], 0]), this.invViewProjectionMatrix, this.invViewProjectionMatrix);
38
+ }
39
+ }
40
+ export { Viewport };
@@ -185,7 +185,7 @@ async function init(cobalt, nodeData) {
185
185
  targets: [
186
186
  // color
187
187
  {
188
- format: getPreferredFormat(cobalt),
188
+ format: nodeData.refs.color.data?.texture?.format || getPreferredFormat(cobalt),
189
189
  blend: {
190
190
  color: {
191
191
  srcFactor: 'src-alpha',
@@ -339,7 +339,7 @@ function draw(cobalt, node, commandEncoder) {
339
339
  colorAttachments: [
340
340
  // color
341
341
  {
342
- view: node.refs.color,
342
+ view: node.refs.color.data?.view || node.refs.color,
343
343
  clearValue: cobalt.clearValue,
344
344
  loadOp: loadOp,
345
345
  storeOp: 'store',
@@ -45,13 +45,14 @@ async function init(cobalt, node) {
45
45
  node.options.colorTextureUrl,
46
46
  format,
47
47
  )
48
- emissiveTexture = await createTextureFromUrl(
49
- cobalt,
50
- 'emissive sprite',
51
- node.options.emissiveTextureUrl,
52
- format,
53
- )
54
-
48
+ if (node.options.emissiveTextureUrl) {
49
+ emissiveTexture = await createTextureFromUrl(
50
+ cobalt,
51
+ 'emissive sprite',
52
+ node.options.emissiveTextureUrl,
53
+ format,
54
+ )
55
+ }
55
56
  // for some reason this needs to be done _after_ creating the material, or the rendering will be blurry
56
57
  canvas.style.imageRendering = 'pixelated'
57
58
  } else {
@@ -64,12 +65,14 @@ async function init(cobalt, node) {
64
65
  node.options.colorTexture,
65
66
  format,
66
67
  )
67
- emissiveTexture = await createTextureFromBuffer(
68
- cobalt,
69
- 'emissive sprite',
70
- node.options.emissiveTexture,
71
- format,
72
- )
68
+ if (node.options.emissiveTexture) {
69
+ emissiveTexture = await createTextureFromBuffer(
70
+ cobalt,
71
+ 'emissive sprite',
72
+ node.options.emissiveTexture,
73
+ format,
74
+ )
75
+ }
73
76
  }
74
77
 
75
78
  // Map sprite name → ID
@@ -85,5 +88,5 @@ async function init(cobalt, node) {
85
88
 
86
89
  function destroy(node) {
87
90
  node.data.colorTexture.texture.destroy()
88
- node.data.emissiveTexture.texture.destroy()
91
+ if (node.data.emissiveTexture) node.data.emissiveTexture.texture.destroy()
89
92
  }
@@ -21,7 +21,7 @@ Inspired by/ported from https://blog.tojicode.com/2012/07/sprite-tile-maps-on-gp
21
21
  * out (textureView, rgba16float, write) - render target
22
22
  */
23
23
  export default {
24
- type: 'cobalt:tileHDR',
24
+ type: 'cobalt:tile',
25
25
 
26
26
  // @params Object cobalt renderer world object
27
27
  // @params Object options optional data passed when initing this node
File without changes
File without changes