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.
- package/README.md +27 -0
- package/package.json +33 -0
- package/src/assets/decoders/README.md +13 -0
- package/src/assets/decoders/basis_transcoder.js +19 -0
- package/src/assets/decoders/basis_transcoder.wasm +0 -0
- package/src/assets/decoders/draco_decoder.wasm +0 -0
- package/src/assets/decoders/draco_wasm_wrapper.js +117 -0
- package/src/assets/neutral_ibl128.ktx +0 -0
- package/src/core/animBridge.ts +51 -0
- package/src/core/boneNames.ts +22 -0
- package/src/core/frame.ts +230 -0
- package/src/core/glbStructure.ts +100 -0
- package/src/core/headlessBridge.ts +92 -0
- package/src/core/mapView.ts +195 -0
- package/src/core/math3d.ts +275 -0
- package/src/core/particleBridge.ts +154 -0
- package/src/core/physicsBridge.ts +305 -0
- package/src/core/recording.ts +59 -0
- package/src/core/sceneCore.ts +833 -0
- package/src/core/serialize.ts +144 -0
- package/src/gen/unsupported.gen.ts +212 -0
- package/src/index.ts +5 -0
- package/src/vendor/creator-anim/dist/creatorAnim.d.ts +123 -0
- package/src/vendor/creator-anim/dist/creatorAnim.js +14 -0
- package/src/vendor/creator-anim/js/index.ts +656 -0
- package/src/vendor/creator-nav/dist/creatorNav.d.ts +56 -0
- package/src/vendor/creator-nav/dist/creatorNav.js +14 -0
- package/src/vendor/creator-nav/js/index.ts +400 -0
- package/src/vendor/creator-particles/dist/creatorParticles.d.ts +43 -0
- package/src/vendor/creator-particles/dist/creatorParticles.js +14 -0
- package/src/vendor/creator-particles/js/index.ts +137 -0
- package/src/vendor/creator-physics/dist/creatorPhysics.d.ts +107 -0
- package/src/vendor/creator-physics/dist/creatorPhysics.js +14 -0
- package/src/vendor/creator-physics/js/index.ts +515 -0
- package/src/vite-env.d.ts +1 -0
- package/src/webgl/batching.ts +453 -0
- package/src/webgl/createViewerLite.ts +1627 -0
- package/src/webgl/customMaterial.ts +228 -0
- package/src/webgl/decoders/basis.ts +123 -0
- package/src/webgl/decoders/draco.ts +110 -0
- package/src/webgl/decoders/index.ts +68 -0
- package/src/webgl/decoders/worker.ts +45 -0
- package/src/webgl/editor.ts +1297 -0
- package/src/webgl/glb.ts +593 -0
- package/src/webgl/ibl.ts +137 -0
- package/src/webgl/shaders.ts +779 -0
package/src/webgl/ibl.ts
ADDED
|
@@ -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
|
+
}
|