lecodes-gl-lite 2.0.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 (46) hide show
  1. package/README.md +27 -0
  2. package/package.json +33 -0
  3. package/src/assets/decoders/README.md +13 -0
  4. package/src/assets/decoders/basis_transcoder.js +19 -0
  5. package/src/assets/decoders/basis_transcoder.wasm +0 -0
  6. package/src/assets/decoders/draco_decoder.wasm +0 -0
  7. package/src/assets/decoders/draco_wasm_wrapper.js +117 -0
  8. package/src/assets/neutral_ibl128.ktx +0 -0
  9. package/src/core/animBridge.ts +51 -0
  10. package/src/core/boneNames.ts +22 -0
  11. package/src/core/frame.ts +230 -0
  12. package/src/core/glbStructure.ts +100 -0
  13. package/src/core/headlessBridge.ts +92 -0
  14. package/src/core/mapView.ts +195 -0
  15. package/src/core/math3d.ts +275 -0
  16. package/src/core/particleBridge.ts +154 -0
  17. package/src/core/physicsBridge.ts +305 -0
  18. package/src/core/recording.ts +59 -0
  19. package/src/core/sceneCore.ts +833 -0
  20. package/src/core/serialize.ts +144 -0
  21. package/src/gen/unsupported.gen.ts +212 -0
  22. package/src/index.ts +5 -0
  23. package/src/vendor/creator-anim/dist/creatorAnim.d.ts +123 -0
  24. package/src/vendor/creator-anim/dist/creatorAnim.js +14 -0
  25. package/src/vendor/creator-anim/js/index.ts +656 -0
  26. package/src/vendor/creator-nav/dist/creatorNav.d.ts +56 -0
  27. package/src/vendor/creator-nav/dist/creatorNav.js +14 -0
  28. package/src/vendor/creator-nav/js/index.ts +400 -0
  29. package/src/vendor/creator-particles/dist/creatorParticles.d.ts +43 -0
  30. package/src/vendor/creator-particles/dist/creatorParticles.js +14 -0
  31. package/src/vendor/creator-particles/js/index.ts +137 -0
  32. package/src/vendor/creator-physics/dist/creatorPhysics.d.ts +107 -0
  33. package/src/vendor/creator-physics/dist/creatorPhysics.js +14 -0
  34. package/src/vendor/creator-physics/js/index.ts +515 -0
  35. package/src/vite-env.d.ts +1 -0
  36. package/src/webgl/batching.ts +453 -0
  37. package/src/webgl/createViewerLite.ts +1627 -0
  38. package/src/webgl/customMaterial.ts +228 -0
  39. package/src/webgl/decoders/basis.ts +123 -0
  40. package/src/webgl/decoders/draco.ts +110 -0
  41. package/src/webgl/decoders/index.ts +68 -0
  42. package/src/webgl/decoders/worker.ts +45 -0
  43. package/src/webgl/editor.ts +1297 -0
  44. package/src/webgl/glb.ts +593 -0
  45. package/src/webgl/ibl.ts +137 -0
  46. package/src/webgl/shaders.ts +779 -0
@@ -0,0 +1,137 @@
1
+ // KTX1 environment loader for the lite engine. Reads the SAME asset the Filament build ships
2
+ // (assets/neutral_ibl128.ktx, produced by cmgen): a prefiltered R11F_G11F_B10F cubemap whose mip
3
+ // chain encodes roughness levels, plus 9 spherical-harmonics irradiance coefficients in the "sh"
4
+ // key-value metadata. So the lite engine's ambient term is fed by the exact data Filament uses.
5
+
6
+ import { Texture, type OGLRenderingContext } from 'ogl'
7
+
8
+ const KTX_MAGIC = 0xab4b5458 // ¬KTX (big-endian read of the first 4 bytes)
9
+
10
+ export type IblData = {
11
+ /** 9 × [r,g,b] irradiance SH coefficients (pre-convolved by cmgen — direct basis eval). */
12
+ sh: Float32Array // 27 floats
13
+ cubemap: Texture
14
+ maxLod: number
15
+ }
16
+
17
+ type Ktx1 = {
18
+ glType: number
19
+ glFormat: number
20
+ glInternalFormat: number
21
+ width: number
22
+ height: number
23
+ faces: number
24
+ mipLevels: number
25
+ keyValues: Map<string, string>
26
+ /** mips[level][face] — raw pixel payloads */
27
+ mips: Uint8Array[][]
28
+ }
29
+
30
+ const parseKtx1 = (buf: ArrayBuffer): Ktx1 => {
31
+ const dv = new DataView(buf)
32
+ if (dv.getUint32(0, false) !== KTX_MAGIC) throw new Error('Not a KTX1 file')
33
+ const little = dv.getUint32(12, true) === 0x04030201
34
+ const u32 = (off: number): number => dv.getUint32(off, little)
35
+
36
+ const glType = u32(16)
37
+ const glFormat = u32(24)
38
+ const glInternalFormat = u32(28)
39
+ const width = u32(36)
40
+ const height = u32(40)
41
+ const faces = u32(52)
42
+ const mipLevels = Math.max(1, u32(56))
43
+ const bytesOfKeyValueData = u32(60)
44
+
45
+ const keyValues = new Map<string, string>()
46
+ const decoder = new TextDecoder('utf-8')
47
+ let p = 64
48
+ const kvEnd = 64 + bytesOfKeyValueData
49
+ while (p < kvEnd) {
50
+ const byteSize = u32(p)
51
+ p += 4
52
+ const bytes = new Uint8Array(buf, p, byteSize)
53
+ const nul = bytes.indexOf(0)
54
+ const key = decoder.decode(bytes.subarray(0, nul))
55
+ const value = decoder.decode(bytes.subarray(nul + 1)).replace(/\0+$/, '')
56
+ keyValues.set(key, value)
57
+ p += byteSize + ((3 - ((byteSize + 3) % 4)))
58
+ }
59
+
60
+ const mips: Uint8Array[][] = []
61
+ p = kvEnd
62
+ for (let level = 0; level < mipLevels; level++) {
63
+ const imageSize = u32(p) // per-face size for cubemaps (non-array)
64
+ p += 4
65
+ const faceList: Uint8Array[] = []
66
+ for (let f = 0; f < faces; f++) {
67
+ faceList.push(new Uint8Array(buf, p, imageSize))
68
+ p += imageSize + ((3 - ((imageSize + 3) % 4)))
69
+ }
70
+ mips.push(faceList)
71
+ }
72
+
73
+ return { glType, glFormat, glInternalFormat, width, height, faces, mipLevels, keyValues, mips }
74
+ }
75
+
76
+ /** Parse cmgen's "sh" metadata: 9 lines of "r g b". */
77
+ const parseSh = (text: string | undefined): Float32Array => {
78
+ const sh = new Float32Array(27)
79
+ if (!text) return sh
80
+ const nums = text.trim().split(/[\s\n]+/).map(Number)
81
+ for (let i = 0; i < Math.min(27, nums.length); i++) sh[i] = nums[i]
82
+ return sh
83
+ }
84
+
85
+ const GL_R11F_G11F_B10F = 0x8c3a
86
+ const GL_UNSIGNED_INT_10F_11F_11F_REV = 0x8c3b
87
+ const GL_RGB = 0x1907
88
+
89
+ export const loadIbl = (gl: OGLRenderingContext & WebGL2RenderingContext, buf: ArrayBuffer): IblData => {
90
+ const ktx = parseKtx1(buf)
91
+ const sh = parseSh(ktx.keyValues.get('sh'))
92
+
93
+ // Upload the cubemap manually (OGL's Texture doesn't handle per-mip cubemap payloads).
94
+ const texture = new Texture(gl, {
95
+ target: gl.TEXTURE_CUBE_MAP,
96
+ generateMipmaps: false,
97
+ minFilter: gl.LINEAR_MIPMAP_LINEAR,
98
+ magFilter: gl.LINEAR,
99
+ flipY: false,
100
+ width: ktx.width,
101
+ height: ktx.height,
102
+ })
103
+
104
+ const packed = ktx.glInternalFormat === GL_R11F_G11F_B10F
105
+ gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture.texture)
106
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false)
107
+ gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1)
108
+ for (let level = 0; level < ktx.mipLevels; level++) {
109
+ const size = Math.max(1, ktx.width >> level)
110
+ for (let face = 0; face < ktx.faces; face++) {
111
+ const data = ktx.mips[level][face]
112
+ if (packed) {
113
+ gl.texImage2D(
114
+ gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, level, GL_R11F_G11F_B10F, size, size, 0,
115
+ GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV,
116
+ new Uint32Array(data.buffer, data.byteOffset, data.byteLength / 4),
117
+ )
118
+ } else {
119
+ // Fallback: assume RGB(A)8
120
+ const channels = ktx.glFormat === GL_RGB ? 3 : 4
121
+ gl.texImage2D(
122
+ gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, level, channels === 3 ? gl.RGB8 : gl.RGBA8, size, size, 0,
123
+ channels === 3 ? gl.RGB : gl.RGBA, gl.UNSIGNED_BYTE, data,
124
+ )
125
+ }
126
+ }
127
+ }
128
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAX_LEVEL, ktx.mipLevels - 1)
129
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR)
130
+ gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
131
+
132
+ // Tell OGL's texture state tracking the image is already uploaded.
133
+ ;(texture as any).store.image = (texture as any).image = ktx
134
+ ;(texture as any).needsUpdate = false
135
+
136
+ return { sh, cubemap: texture, maxLod: ktx.mipLevels - 1 }
137
+ }