3d-spinner 0.9.4 → 0.9.6

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 (54) hide show
  1. package/dist/animations/charged-orb.js +4 -2
  2. package/dist/animations/ghost-train.d.ts +1 -1
  3. package/dist/animations/ghost-train.js +3 -1
  4. package/dist/animations/grid-assembly.d.ts +1 -1
  5. package/dist/animations/spin.d.ts +3 -1
  6. package/dist/animations/spin.js +6 -1
  7. package/dist/cjs/animations/charged-orb.cjs +177 -30
  8. package/dist/cjs/animations/grid-assembly.cjs +171 -28
  9. package/dist/cjs/animations/object-motion.cjs +163 -26
  10. package/dist/cjs/animations/particles.cjs +181 -30
  11. package/dist/cjs/animations/spin.cjs +176 -29
  12. package/dist/cjs/engines/little-3d-engine/little-3d-engine.cjs +200 -47
  13. package/dist/cjs/engines/little-3d-engine/loaders/obj.cjs +51 -13
  14. package/dist/cjs/engines/little-3d-engine/renderers/canvas2d-textured.cjs +56 -6
  15. package/dist/cjs/engines/little-3d-engine/renderers/webgl-textured.cjs +69 -10
  16. package/dist/cjs/engines/little-3d-engine/renderers/webgpu-textured.cjs +64 -11
  17. package/dist/cjs/prefabs/prefabs.cjs +200 -44
  18. package/dist/engines/little-3d-engine/core/geometry.d.ts +15 -2
  19. package/dist/engines/little-3d-engine/core/geometry.js +25 -3
  20. package/dist/engines/little-3d-engine/core/light.d.ts +28 -4
  21. package/dist/engines/little-3d-engine/core/light.js +48 -7
  22. package/dist/engines/little-3d-engine/core/mesh.d.ts +33 -0
  23. package/dist/engines/little-3d-engine/core/mesh.js +12 -0
  24. package/dist/engines/little-3d-engine/little-3d-engine.d.ts +2 -2
  25. package/dist/engines/little-3d-engine/little-3d-engine.js +1 -1
  26. package/dist/engines/little-3d-engine/loaders/obj.d.ts +8 -7
  27. package/dist/engines/little-3d-engine/loaders/obj.js +74 -20
  28. package/dist/engines/little-3d-engine/renderers/canvas2d.js +23 -1
  29. package/dist/engines/little-3d-engine/renderers/webgl-textured.js +8 -3
  30. package/dist/engines/little-3d-engine/renderers/webgl.js +41 -7
  31. package/dist/engines/little-3d-engine/renderers/webgpu.js +43 -10
  32. package/dist/engines/little-3d-engine/shapes/complex/plane.d.ts +8 -3
  33. package/dist/engines/little-3d-engine/shapes/complex/plane.js +10 -4
  34. package/dist/engines/little-3d-engine/shapes/primitives/cube.d.ts +3 -2
  35. package/dist/engines/little-3d-engine/shapes/primitives/cube.js +4 -2
  36. package/dist/engines/little-3d-engine/shapes/primitives/octahedron.d.ts +3 -2
  37. package/dist/engines/little-3d-engine/shapes/primitives/octahedron.js +4 -2
  38. package/dist/engines/little-3d-engine/shapes/primitives/pyramid.d.ts +3 -2
  39. package/dist/engines/little-3d-engine/shapes/primitives/pyramid.js +4 -2
  40. package/dist/engines/little-3d-engine/shapes/primitives/quad.d.ts +3 -2
  41. package/dist/engines/little-3d-engine/shapes/primitives/quad.js +4 -2
  42. package/dist/engines/little-3d-engine/shapes/primitives/spheres/cube-sphere.d.ts +3 -2
  43. package/dist/engines/little-3d-engine/shapes/primitives/spheres/cube-sphere.js +4 -2
  44. package/dist/engines/little-3d-engine/shapes/primitives/spheres/icosphere.d.ts +3 -2
  45. package/dist/engines/little-3d-engine/shapes/primitives/spheres/icosphere.js +4 -2
  46. package/dist/engines/little-3d-engine/shapes/primitives/spheres/octa-sphere.d.ts +3 -2
  47. package/dist/engines/little-3d-engine/shapes/primitives/spheres/octa-sphere.js +4 -2
  48. package/dist/engines/little-3d-engine/shapes/primitives/spheres/uv-sphere.d.ts +3 -2
  49. package/dist/engines/little-3d-engine/shapes/primitives/spheres/uv-sphere.js +4 -2
  50. package/dist/engines/little-3d-engine/shapes/primitives/tetrahedron.d.ts +3 -2
  51. package/dist/engines/little-3d-engine/shapes/primitives/tetrahedron.js +4 -2
  52. package/dist/umd/spinner.global.js +271 -67
  53. package/dist/umd/spinner.global.min.js +58 -17
  54. package/package.json +1 -1
@@ -107,13 +107,42 @@ var init_geometry = __esm({
107
107
  function clamp01(value) {
108
108
  return Math.min(1, Math.max(0, value));
109
109
  }
110
- function shadeColor(normal, color, light) {
110
+ function clamp255(value) {
111
+ return Math.round(Math.min(255, Math.max(0, value)));
112
+ }
113
+ function shade(normal, color, light, surface) {
111
114
  const lambert = Math.max(0, dot(normal, light.toLight));
112
115
  const brightness = clamp01(light.ambient + light.intensity * lambert);
113
- const [r, g, b] = parseColor(color);
114
- return `rgb(${Math.round(r * brightness)}, ${Math.round(g * brightness)}, ${Math.round(
115
- b * brightness
116
- )})`;
116
+ const [baseR, baseG, baseB] = parseColor(color);
117
+ let r = baseR * brightness;
118
+ let g = baseG * brightness;
119
+ let b = baseB * brightness;
120
+ const material = surface?.material;
121
+ const specular = material?.specular;
122
+ const viewDir = surface?.viewDir;
123
+ if (specular && viewDir && lambert > 0) {
124
+ const half = normalize({
125
+ x: light.toLight.x + viewDir.x,
126
+ y: light.toLight.y + viewDir.y,
127
+ z: light.toLight.z + viewDir.z
128
+ });
129
+ const shininess = material?.shininess ?? 32;
130
+ const highlight = Math.pow(Math.max(0, dot(normal, half)), shininess) * light.intensity * 255;
131
+ r += highlight * specular[0];
132
+ g += highlight * specular[1];
133
+ b += highlight * specular[2];
134
+ }
135
+ const emissive = material?.emissive;
136
+ if (emissive) {
137
+ r += emissive[0] * 255;
138
+ g += emissive[1] * 255;
139
+ b += emissive[2] * 255;
140
+ }
141
+ return [clamp255(r), clamp255(g), clamp255(b)];
142
+ }
143
+ function shadeColor(normal, color, light, surface) {
144
+ const [r, g, b] = shade(normal, color, light, surface);
145
+ return `rgb(${r}, ${g}, ${b})`;
117
146
  }
118
147
  var init_light = __esm({
119
148
  "src/engines/little-3d-engine/core/light.ts"() {
@@ -183,9 +212,30 @@ var init_canvas2d = __esm({
183
212
  depth += dot(d, d);
184
213
  }
185
214
  depth /= face.indices.length;
215
+ let surface;
216
+ const material = face.material;
217
+ if (material) {
218
+ if (material.specular) {
219
+ let cx = 0;
220
+ let cy = 0;
221
+ let cz = 0;
222
+ for (const i of face.indices) {
223
+ cx += world[i].x;
224
+ cy += world[i].y;
225
+ cz += world[i].z;
226
+ }
227
+ const inv = 1 / face.indices.length;
228
+ const viewDir = normalize(
229
+ subtract(frame.eye, { x: cx * inv, y: cy * inv, z: cz * inv })
230
+ );
231
+ surface = { material, viewDir };
232
+ } else {
233
+ surface = { material };
234
+ }
235
+ }
186
236
  polygons.push({
187
237
  points,
188
- color: shadeColor(normal, face.color, frame.light),
238
+ color: shadeColor(normal, face.color, frame.light, surface),
189
239
  depth,
190
240
  opacity: faceOpacity
191
241
  });
@@ -60,7 +60,10 @@ function expandToTriangles(mesh) {
60
60
  const positions = new Float32Array(triangles * 9);
61
61
  const normals = new Float32Array(triangles * 9);
62
62
  const colors = new Float32Array(triangles * 9);
63
+ const emissives = new Float32Array(triangles * 9);
64
+ const speculars = new Float32Array(triangles * 12);
63
65
  let o = 0;
66
+ let so = 0;
64
67
  for (const face of mesh.faces) {
65
68
  const v0 = mesh.vertices[face.indices[0]];
66
69
  const v1 = mesh.vertices[face.indices[1]];
@@ -70,6 +73,15 @@ function expandToTriangles(mesh) {
70
73
  const cr = r / 255;
71
74
  const cg = g / 255;
72
75
  const cb = b / 255;
76
+ const emissive = face.material?.emissive;
77
+ const er = emissive ? emissive[0] : 0;
78
+ const eg = emissive ? emissive[1] : 0;
79
+ const eb = emissive ? emissive[2] : 0;
80
+ const specular = face.material?.specular;
81
+ const sr = specular ? specular[0] : 0;
82
+ const sg = specular ? specular[1] : 0;
83
+ const sb = specular ? specular[2] : 0;
84
+ const sn = specular ? face.material?.shininess ?? 32 : 1;
73
85
  for (let k = 1; k < face.indices.length - 1; k++) {
74
86
  const tri = [face.indices[0], face.indices[k], face.indices[k + 1]];
75
87
  for (const index of tri) {
@@ -83,11 +95,19 @@ function expandToTriangles(mesh) {
83
95
  colors[o] = cr;
84
96
  colors[o + 1] = cg;
85
97
  colors[o + 2] = cb;
98
+ emissives[o] = er;
99
+ emissives[o + 1] = eg;
100
+ emissives[o + 2] = eb;
101
+ speculars[so] = sr;
102
+ speculars[so + 1] = sg;
103
+ speculars[so + 2] = sb;
104
+ speculars[so + 3] = sn;
86
105
  o += 3;
106
+ so += 4;
87
107
  }
88
108
  }
89
109
  }
90
- return { positions, normals, colors, count: positions.length / 3 };
110
+ return { positions, normals, colors, emissives, speculars, count: positions.length / 3 };
91
111
  }
92
112
  var init_geometry = __esm({
93
113
  "src/engines/little-3d-engine/core/geometry.ts"() {
@@ -151,28 +171,51 @@ var init_webgl = __esm({
151
171
  in vec3 aPos;
152
172
  in vec3 aNormal;
153
173
  in vec3 aColor;
174
+ in vec3 aEmissive;
175
+ in vec4 aSpecular;
154
176
  uniform mat4 uViewProj;
155
177
  uniform mat4 uModel;
156
178
  out vec3 vNormal;
157
179
  out vec3 vColor;
180
+ out vec3 vEmissive;
181
+ out vec4 vSpecular;
182
+ out vec3 vWorldPos;
158
183
  void main() {
159
184
  vNormal = mat3(uModel) * aNormal;
160
185
  vColor = aColor;
161
- gl_Position = uViewProj * uModel * vec4(aPos, 1.0);
186
+ vEmissive = aEmissive;
187
+ vSpecular = aSpecular;
188
+ vec4 world = uModel * vec4(aPos, 1.0);
189
+ vWorldPos = world.xyz;
190
+ gl_Position = uViewProj * world;
162
191
  }`;
163
192
  FRAGMENT_SHADER = `#version 300 es
164
193
  precision mediump float;
165
194
  in vec3 vNormal;
166
195
  in vec3 vColor;
196
+ in vec3 vEmissive;
197
+ in vec4 vSpecular;
198
+ in vec3 vWorldPos;
167
199
  uniform vec3 uToLight;
200
+ uniform vec3 uEye;
168
201
  uniform float uIntensity;
169
202
  uniform float uAmbient;
170
203
  uniform float uOpacity;
171
204
  out vec4 fragColor;
172
205
  void main() {
173
- float lambert = max(dot(normalize(vNormal), normalize(uToLight)), 0.0);
206
+ vec3 normal = normalize(vNormal);
207
+ vec3 toLight = normalize(uToLight);
208
+ float lambert = max(dot(normal, toLight), 0.0);
174
209
  float brightness = clamp(uAmbient + uIntensity * lambert, 0.0, 1.0);
175
- fragColor = vec4(vColor * brightness, uOpacity);
210
+ vec3 lit = vColor * brightness;
211
+ if (lambert > 0.0) {
212
+ vec3 viewDir = normalize(uEye - vWorldPos);
213
+ vec3 halfVec = normalize(toLight + viewDir);
214
+ float highlight = pow(max(dot(normal, halfVec), 0.0), vSpecular.w) * uIntensity;
215
+ lit += highlight * vSpecular.xyz;
216
+ }
217
+ lit += vEmissive;
218
+ fragColor = vec4(lit, uOpacity);
176
219
  }`;
177
220
  WebGLRenderer = class {
178
221
  constructor(options = {}) {
@@ -193,9 +236,12 @@ void main() {
193
236
  aPos: gl.getAttribLocation(this.program, "aPos"),
194
237
  aNormal: gl.getAttribLocation(this.program, "aNormal"),
195
238
  aColor: gl.getAttribLocation(this.program, "aColor"),
239
+ aEmissive: gl.getAttribLocation(this.program, "aEmissive"),
240
+ aSpecular: gl.getAttribLocation(this.program, "aSpecular"),
196
241
  uViewProj: gl.getUniformLocation(this.program, "uViewProj"),
197
242
  uModel: gl.getUniformLocation(this.program, "uModel"),
198
243
  uToLight: gl.getUniformLocation(this.program, "uToLight"),
244
+ uEye: gl.getUniformLocation(this.program, "uEye"),
199
245
  uIntensity: gl.getUniformLocation(this.program, "uIntensity"),
200
246
  uAmbient: gl.getUniformLocation(this.program, "uAmbient"),
201
247
  uOpacity: gl.getUniformLocation(this.program, "uOpacity")
@@ -219,19 +265,23 @@ void main() {
219
265
  const data = expandToTriangles(mesh);
220
266
  const vao = gl.createVertexArray();
221
267
  gl.bindVertexArray(vao);
222
- const attribute = (location, array) => {
268
+ const buffers = [];
269
+ const attribute = (location, array, size = 3) => {
223
270
  if (location < 0) return;
224
271
  const buffer = gl.createBuffer();
272
+ buffers.push(buffer);
225
273
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
226
274
  gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
227
275
  gl.enableVertexAttribArray(location);
228
- gl.vertexAttribPointer(location, 3, gl.FLOAT, false, 0, 0);
276
+ gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
229
277
  };
230
278
  attribute(loc.aPos, data.positions);
231
279
  attribute(loc.aNormal, data.normals);
232
280
  attribute(loc.aColor, data.colors);
281
+ attribute(loc.aEmissive, data.emissives);
282
+ attribute(loc.aSpecular, data.speculars, 4);
233
283
  gl.bindVertexArray(null);
234
- const result = { vao, count: data.count };
284
+ const result = { vao, buffers, count: data.count };
235
285
  this.cache.set(mesh, result);
236
286
  return result;
237
287
  }
@@ -244,6 +294,7 @@ void main() {
244
294
  gl.useProgram(this.program);
245
295
  gl.uniformMatrix4fv(loc.uViewProj, false, new Float32Array(frame.viewProjection));
246
296
  gl.uniform3f(loc.uToLight, frame.light.toLight.x, frame.light.toLight.y, frame.light.toLight.z);
297
+ gl.uniform3f(loc.uEye, frame.eye.x, frame.eye.y, frame.eye.z);
247
298
  gl.uniform1f(loc.uIntensity, frame.light.intensity);
248
299
  gl.uniform1f(loc.uAmbient, frame.light.ambient);
249
300
  gl.disable(gl.BLEND);
@@ -288,7 +339,10 @@ void main() {
288
339
  destroy() {
289
340
  const gl = this.gl;
290
341
  if (gl) {
291
- for (const mesh of this.cache.values()) gl.deleteVertexArray(mesh.vao);
342
+ for (const mesh of this.cache.values()) {
343
+ gl.deleteVertexArray(mesh.vao);
344
+ for (const buffer of mesh.buffers) gl.deleteBuffer(buffer);
345
+ }
292
346
  if (this.program) gl.deleteProgram(this.program);
293
347
  }
294
348
  this.cache.clear();
@@ -464,9 +518,11 @@ var WebGLTexturedRenderer = class {
464
518
  const data = expandToTriangles(mesh);
465
519
  const vao = gl.createVertexArray();
466
520
  gl.bindVertexArray(vao);
521
+ const buffers = [];
467
522
  const attribute = (location, array, size) => {
468
523
  if (location < 0) return;
469
524
  const buffer = gl.createBuffer();
525
+ buffers.push(buffer);
470
526
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
471
527
  gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
472
528
  gl.enableVertexAttribArray(location);
@@ -476,7 +532,7 @@ var WebGLTexturedRenderer = class {
476
532
  attribute(loc.aColor, data.colors, 3);
477
533
  attribute(loc.aUV, planarUVs(mesh), 2);
478
534
  gl.bindVertexArray(null);
479
- const result = { vao, count: data.count };
535
+ const result = { vao, buffers, count: data.count };
480
536
  this.buffers.set(mesh, result);
481
537
  return result;
482
538
  }
@@ -514,7 +570,10 @@ var WebGLTexturedRenderer = class {
514
570
  const gl = this.gl;
515
571
  if (gl) {
516
572
  for (const texture of this.textures.values()) gl.deleteTexture(texture);
517
- for (const buffers of this.buffers.values()) gl.deleteVertexArray(buffers.vao);
573
+ for (const cached of this.buffers.values()) {
574
+ gl.deleteVertexArray(cached.vao);
575
+ for (const buffer of cached.buffers) gl.deleteBuffer(buffer);
576
+ }
518
577
  if (this.program) gl.deleteProgram(this.program);
519
578
  }
520
579
  this.textures.clear();
@@ -73,7 +73,10 @@ function expandToTriangles(mesh) {
73
73
  const positions = new Float32Array(triangles * 9);
74
74
  const normals = new Float32Array(triangles * 9);
75
75
  const colors = new Float32Array(triangles * 9);
76
+ const emissives = new Float32Array(triangles * 9);
77
+ const speculars = new Float32Array(triangles * 12);
76
78
  let o = 0;
79
+ let so = 0;
77
80
  for (const face of mesh.faces) {
78
81
  const v0 = mesh.vertices[face.indices[0]];
79
82
  const v1 = mesh.vertices[face.indices[1]];
@@ -83,6 +86,15 @@ function expandToTriangles(mesh) {
83
86
  const cr = r / 255;
84
87
  const cg = g / 255;
85
88
  const cb = b / 255;
89
+ const emissive = face.material?.emissive;
90
+ const er = emissive ? emissive[0] : 0;
91
+ const eg = emissive ? emissive[1] : 0;
92
+ const eb = emissive ? emissive[2] : 0;
93
+ const specular = face.material?.specular;
94
+ const sr = specular ? specular[0] : 0;
95
+ const sg = specular ? specular[1] : 0;
96
+ const sb = specular ? specular[2] : 0;
97
+ const sn = specular ? face.material?.shininess ?? 32 : 1;
86
98
  for (let k = 1; k < face.indices.length - 1; k++) {
87
99
  const tri = [face.indices[0], face.indices[k], face.indices[k + 1]];
88
100
  for (const index of tri) {
@@ -96,11 +108,19 @@ function expandToTriangles(mesh) {
96
108
  colors[o] = cr;
97
109
  colors[o + 1] = cg;
98
110
  colors[o + 2] = cb;
111
+ emissives[o] = er;
112
+ emissives[o + 1] = eg;
113
+ emissives[o + 2] = eb;
114
+ speculars[so] = sr;
115
+ speculars[so + 1] = sg;
116
+ speculars[so + 2] = sb;
117
+ speculars[so + 3] = sn;
99
118
  o += 3;
119
+ so += 4;
100
120
  }
101
121
  }
102
122
  }
103
- return { positions, normals, colors, count: positions.length / 3 };
123
+ return { positions, normals, colors, emissives, speculars, count: positions.length / 3 };
104
124
  }
105
125
  var init_geometry = __esm({
106
126
  "src/engines/little-3d-engine/core/geometry.ts"() {
@@ -148,6 +168,7 @@ struct Uniforms {
148
168
  model: mat4x4<f32>,
149
169
  toLight: vec4<f32>,
150
170
  params: vec4<f32>,
171
+ eye: vec4<f32>,
151
172
  };
152
173
  @group(0) @binding(0) var<uniform> u: Uniforms;
153
174
 
@@ -155,23 +176,40 @@ struct VSOut {
155
176
  @builtin(position) position: vec4<f32>,
156
177
  @location(0) normal: vec3<f32>,
157
178
  @location(1) color: vec3<f32>,
179
+ @location(2) emissive: vec3<f32>,
180
+ @location(3) specular: vec4<f32>,
181
+ @location(4) worldPos: vec3<f32>,
158
182
  };
159
183
 
160
184
  @vertex
161
- fn vs(@location(0) pos: vec3<f32>, @location(1) normal: vec3<f32>, @location(2) color: vec3<f32>) -> VSOut {
185
+ fn vs(@location(0) pos: vec3<f32>, @location(1) normal: vec3<f32>, @location(2) color: vec3<f32>, @location(3) emissive: vec3<f32>, @location(4) specular: vec4<f32>) -> VSOut {
162
186
  var out: VSOut;
163
187
  let m = mat3x3<f32>(u.model[0].xyz, u.model[1].xyz, u.model[2].xyz);
164
188
  out.normal = m * normal;
165
189
  out.color = color;
166
- out.position = u.viewProj * u.model * vec4<f32>(pos, 1.0);
190
+ out.emissive = emissive;
191
+ out.specular = specular;
192
+ let world = u.model * vec4<f32>(pos, 1.0);
193
+ out.worldPos = world.xyz;
194
+ out.position = u.viewProj * world;
167
195
  return out;
168
196
  }
169
197
 
170
198
  @fragment
171
199
  fn fs(in: VSOut) -> @location(0) vec4<f32> {
172
- let lambert = max(dot(normalize(in.normal), normalize(u.toLight.xyz)), 0.0);
200
+ let normal = normalize(in.normal);
201
+ let toLight = normalize(u.toLight.xyz);
202
+ let lambert = max(dot(normal, toLight), 0.0);
173
203
  let brightness = clamp(u.params.y + u.params.x * lambert, 0.0, 1.0);
174
- return vec4<f32>(in.color * brightness, u.params.z);
204
+ var lit = in.color * brightness;
205
+ if (lambert > 0.0) {
206
+ let viewDir = normalize(u.eye.xyz - in.worldPos);
207
+ let halfVec = normalize(toLight + viewDir);
208
+ let highlight = pow(max(dot(normal, halfVec), 0.0), in.specular.w) * u.params.x;
209
+ lit = lit + highlight * in.specular.xyz;
210
+ }
211
+ lit = lit + in.emissive;
212
+ return vec4<f32>(lit, u.params.z);
175
213
  }
176
214
  `;
177
215
  CLIP_Z_FIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0.5, 0, 0, 0, 0.5, 1];
@@ -212,13 +250,15 @@ fn fs(in: VSOut) -> @location(0) vec4<f32> {
212
250
  {
213
251
  binding: 0,
214
252
  visibility: stage.VERTEX | stage.FRAGMENT,
215
- buffer: { type: "uniform", hasDynamicOffset: true, minBindingSize: 160 }
253
+ buffer: { type: "uniform", hasDynamicOffset: true, minBindingSize: 176 }
216
254
  }
217
255
  ]
218
256
  });
219
- const vertexBuffer = (location) => ({
220
- arrayStride: 12,
221
- attributes: [{ shaderLocation: location, offset: 0, format: "float32x3" }]
257
+ const vertexBuffer = (location, components = 3) => ({
258
+ arrayStride: components * 4,
259
+ attributes: [
260
+ { shaderLocation: location, offset: 0, format: `float32x${components}` }
261
+ ]
222
262
  });
223
263
  const pipelineLayout = device.createPipelineLayout({ bindGroupLayouts: [layout] });
224
264
  const blend = {
@@ -234,7 +274,13 @@ fn fs(in: VSOut) -> @location(0) vec4<f32> {
234
274
  vertex: {
235
275
  module: module2,
236
276
  entryPoint: "vs",
237
- buffers: [vertexBuffer(0), vertexBuffer(1), vertexBuffer(2)]
277
+ buffers: [
278
+ vertexBuffer(0),
279
+ vertexBuffer(1),
280
+ vertexBuffer(2),
281
+ vertexBuffer(3),
282
+ vertexBuffer(4, 4)
283
+ ]
238
284
  },
239
285
  fragment: {
240
286
  module: module2,
@@ -287,6 +333,8 @@ fn fs(in: VSOut) -> @location(0) vec4<f32> {
287
333
  position: upload(data.positions),
288
334
  normal: upload(data.normals),
289
335
  color: upload(data.colors),
336
+ emissive: upload(data.emissives),
337
+ specular: upload(data.speculars),
290
338
  count: data.count
291
339
  };
292
340
  this.cache.set(mesh, result);
@@ -338,7 +386,7 @@ fn fs(in: VSOut) -> @location(0) vec4<f32> {
338
386
  const bindGroup = this.device.createBindGroup({
339
387
  layout,
340
388
  entries: [
341
- { binding: 0, resource: { buffer: this.uniformBuffer, offset: 0, size: 160 } }
389
+ { binding: 0, resource: { buffer: this.uniformBuffer, offset: 0, size: 176 } }
342
390
  ]
343
391
  });
344
392
  draws.forEach((draw, i) => {
@@ -347,6 +395,7 @@ fn fs(in: VSOut) -> @location(0) vec4<f32> {
347
395
  data.set(draw.item.model, 16);
348
396
  data.set([frame.light.toLight.x, frame.light.toLight.y, frame.light.toLight.z, 0], 32);
349
397
  data.set([frame.light.intensity, frame.light.ambient, draw.opacity, 0], 36);
398
+ data.set([frame.eye.x, frame.eye.y, frame.eye.z, 0], 40);
350
399
  this.device.queue.writeBuffer(this.uniformBuffer, i * UNIFORM_STRIDE, data);
351
400
  });
352
401
  const encoder = this.device.createCommandEncoder();
@@ -373,6 +422,8 @@ fn fs(in: VSOut) -> @location(0) vec4<f32> {
373
422
  pass.setVertexBuffer(0, mesh.position);
374
423
  pass.setVertexBuffer(1, mesh.normal);
375
424
  pass.setVertexBuffer(2, mesh.color);
425
+ pass.setVertexBuffer(3, mesh.emissive);
426
+ pass.setVertexBuffer(4, mesh.specular);
376
427
  pass.draw(mesh.count);
377
428
  });
378
429
  pass.end();
@@ -384,6 +435,8 @@ fn fs(in: VSOut) -> @location(0) vec4<f32> {
384
435
  mesh.position.destroy?.();
385
436
  mesh.normal.destroy?.();
386
437
  mesh.color.destroy?.();
438
+ mesh.emissive.destroy?.();
439
+ mesh.specular.destroy?.();
387
440
  }
388
441
  this.cache.clear();
389
442
  this.uniformBuffer?.destroy?.();