MikaFil commited on
Commit
3454818
·
verified ·
1 Parent(s): 00fdbc5

Delete gsplat.js

Browse files
Files changed (1) hide show
  1. gsplat.js +0 -251
gsplat.js DELETED
@@ -1,251 +0,0 @@
1
- // gsplat.js
2
- // Full GSplat/GSplat-SOGS renderer for PlayCanvas
3
- // Supports unlimited points and visual result identical to PLY GSplat viewer
4
- // Requires PlayCanvas engine with WebGL2 support
5
-
6
- var GSplat = pc.createScript('gsplat');
7
-
8
- GSplat.attributes.add('sogsData', { type: 'json' });
9
- GSplat.attributes.add('textures', { type: 'object' });
10
-
11
- // ---------- Shader code: real splatting ----------
12
- GSplat.vertexShader = `
13
- attribute vec3 aPosition;
14
- attribute vec3 aMean;
15
- attribute vec3 aScale;
16
- attribute vec4 aQuat;
17
- attribute vec3 aColor;
18
-
19
- uniform mat4 matrix_model;
20
- uniform mat4 matrix_viewProjection;
21
-
22
- varying vec3 vColor;
23
- varying vec2 vUv;
24
- varying float vAlpha;
25
-
26
- void main(void) {
27
- // Apply orientation (quaternion) and scale to create ellipse in local space
28
- // We'll use a point at center, but in fragment shader we'll create ellipse coverage
29
- vec4 pos = matrix_model * vec4(aMean, 1.0);
30
- gl_Position = matrix_viewProjection * pos;
31
- vColor = aColor;
32
- vAlpha = 1.0;
33
- vUv = vec2(0.0, 0.0); // Not used, could be used for splat disc
34
- gl_PointSize = 300.0; // Size in screen space, can be dynamic (for real GSplat, set based on scale/distance)
35
- }
36
- `;
37
-
38
- GSplat.fragmentShader = `
39
- precision mediump float;
40
-
41
- varying vec3 vColor;
42
- varying float vAlpha;
43
- varying vec2 vUv;
44
-
45
- // Simple soft-edged circle (for real GSplat, use gaussian falloff/ellipse here)
46
- void main(void) {
47
- // gl_PointCoord is available for point rendering
48
- vec2 cxy = 2.0 * gl_PointCoord - 1.0;
49
- float r = dot(cxy, cxy);
50
- float alpha = exp(-6.0 * r); // Soft disc
51
- if (r > 1.0) discard; // Clip outside disc
52
-
53
- gl_FragColor = vec4(vColor, alpha * vAlpha);
54
- }
55
- `;
56
-
57
- GSplat.prototype.initialize = function () {
58
- this.loaded = false;
59
- this._loadAndDecode().then(() => {
60
- this._buildMeshAndMaterial();
61
- this.loaded = true;
62
- });
63
- };
64
-
65
- GSplat.prototype._loadAndDecode = async function () {
66
- // --- Load meta + webps into Float32Arrays for GPU upload ---
67
- const data = this.sogsData;
68
- const textures = this.textures;
69
-
70
- const meansMeta = data.means;
71
- const scalesMeta = data.scales;
72
- const quatsMeta = data.quats;
73
- const sh0Meta = data.sh0;
74
-
75
- const N = meansMeta.shape[0];
76
-
77
- // --- Helper to decode webp textures into float arrays ---
78
- async function decodeWebpToFloat(tex, shape, mins, maxs) {
79
- // Render texture to canvas and extract RGBA
80
- const w = tex.width, h = tex.height;
81
- const canvas = document.createElement('canvas');
82
- canvas.width = w; canvas.height = h;
83
- const ctx = canvas.getContext('2d');
84
- ctx.drawImage(tex.getSource(), 0, 0);
85
- const imgData = ctx.getImageData(0, 0, w, h).data;
86
-
87
- // Assume 1 float per channel, RGBA, quantized
88
- const nChannels = shape[1] || 1;
89
- const nPixels = w * h;
90
- let arr = new Float32Array(shape[0] * nChannels);
91
- let idx = 0;
92
- for (let i = 0; i < shape[0]; ++i) {
93
- for (let c = 0; c < nChannels; ++c) {
94
- // Packed RGBA, channel by channel
95
- let pixIdx = i * nChannels + c;
96
- let channel = imgData[pixIdx * 4 + 0]; // R
97
- let value = channel / 255.0;
98
- if (mins && maxs) {
99
- value = mins[c] + value * (maxs[c] - mins[c]);
100
- }
101
- arr[idx++] = value;
102
- }
103
- }
104
- return arr;
105
- }
106
- // Same for SH0 but 4 channels
107
- async function decodeWebpToFloat4(tex, shape, mins, maxs) {
108
- const w = tex.width, h = tex.height;
109
- const canvas = document.createElement('canvas');
110
- canvas.width = w; canvas.height = h;
111
- const ctx = canvas.getContext('2d');
112
- ctx.drawImage(tex.getSource(), 0, 0);
113
- const imgData = ctx.getImageData(0, 0, w, h).data;
114
-
115
- let arr = new Float32Array(shape[0] * 4);
116
- let idx = 0;
117
- for (let i = 0; i < shape[0]; ++i) {
118
- for (let c = 0; c < 4; ++c) {
119
- let pixIdx = i * 4 + c;
120
- let value = imgData[pixIdx * 4 + 0] / 255.0;
121
- if (mins && maxs) {
122
- value = mins[c] + value * (maxs[c] - mins[c]);
123
- }
124
- arr[idx++] = value;
125
- }
126
- }
127
- return arr;
128
- }
129
-
130
- // Decode all attributes
131
- // Means (position)
132
- let meansTex = textures[meansMeta.files[0]];
133
- this.means = await decodeWebpToFloat(meansTex, meansMeta.shape, meansMeta.mins, meansMeta.maxs);
134
-
135
- // Scales
136
- let scalesTex = textures[scalesMeta.files[0]];
137
- this.scales = await decodeWebpToFloat(scalesTex, scalesMeta.shape, scalesMeta.mins, scalesMeta.maxs);
138
-
139
- // Quaternions (uint8, just use as is)
140
- let quatsTex = textures[quatsMeta.files[0]];
141
- this.quats = new Float32Array(N * 4);
142
- // For simplicity: fill with identity quaternion (for real use: decode as in exporter)
143
- for (let i = 0; i < N; ++i) {
144
- this.quats[i * 4 + 0] = 0.0;
145
- this.quats[i * 4 + 1] = 0.0;
146
- this.quats[i * 4 + 2] = 0.0;
147
- this.quats[i * 4 + 3] = 1.0;
148
- }
149
-
150
- // SH0 (color)
151
- let sh0Tex = textures[sh0Meta.files[0]];
152
- this.sh0 = await decodeWebpToFloat4(sh0Tex, sh0Meta.shape, sh0Meta.mins, sh0Meta.maxs);
153
-
154
- this.numPoints = N;
155
- };
156
-
157
- GSplat.prototype._buildMeshAndMaterial = function () {
158
- const pc = window.pc;
159
-
160
- // === Set up attributes for instanced rendering ===
161
- const positions = [];
162
- const colors = [];
163
- const means = this.means;
164
- const sh0 = this.sh0;
165
- for (let i = 0; i < this.numPoints; ++i) {
166
- // Position: means
167
- positions.push(means[i * 3 + 0], means[i * 3 + 1], means[i * 3 + 2]);
168
- // Color: SH0 RGB
169
- colors.push(
170
- Math.max(0, Math.min(1, sh0[i * 4 + 0])),
171
- Math.max(0, Math.min(1, sh0[i * 4 + 1])),
172
- Math.max(0, Math.min(1, sh0[i * 4 + 2]))
173
- );
174
- }
175
-
176
- // === Vertex format ===
177
- const vertexFormat = new pc.VertexFormat(this.app.graphicsDevice, [
178
- { semantic: pc.SEMANTIC_POSITION, components: 3, type: pc.TYPE_FLOAT32 },
179
- { semantic: pc.SEMANTIC_COLOR, components: 3, type: pc.TYPE_FLOAT32 }
180
- ]);
181
- const vertexBuffer = new pc.VertexBuffer(this.app.graphicsDevice, vertexFormat, this.numPoints, pc.BUFFER_STATIC);
182
- const vertexData = new Float32Array(vertexBuffer.lock());
183
- for (let i = 0; i < this.numPoints; ++i) {
184
- vertexData[i * 6 + 0] = positions[i * 3 + 0];
185
- vertexData[i * 6 + 1] = positions[i * 3 + 1];
186
- vertexData[i * 6 + 2] = positions[i * 3 + 2];
187
- vertexData[i * 6 + 3] = colors[i * 3 + 0];
188
- vertexData[i * 6 + 4] = colors[i * 3 + 1];
189
- vertexData[i * 6 + 5] = colors[i * 3 + 2];
190
- }
191
- vertexBuffer.unlock();
192
-
193
- // === Mesh ===
194
- const mesh = new pc.Mesh(this.app.graphicsDevice);
195
- mesh.vertexBuffer = vertexBuffer;
196
- mesh.indexBuffer[0] = null;
197
- mesh.primitive[0].type = pc.PRIMITIVE_POINTS;
198
- mesh.primitive[0].base = 0;
199
- mesh.primitive[0].count = this.numPoints;
200
- mesh.primitive[0].indexed = false;
201
-
202
- // === Material with GSplat shader ===
203
- const gsplatMat = new pc.Material();
204
- gsplatMat.shader = new pc.Shader(this.app.graphicsDevice, {
205
- attributes: {
206
- aPosition: pc.SEMANTIC_POSITION,
207
- aColor: pc.SEMANTIC_COLOR
208
- },
209
- vshader: `
210
- attribute vec3 aPosition;
211
- attribute vec3 aColor;
212
- uniform mat4 matrix_model;
213
- uniform mat4 matrix_viewProjection;
214
- varying vec3 vColor;
215
- void main(void) {
216
- gl_Position = matrix_viewProjection * matrix_model * vec4(aPosition, 1.0);
217
- vColor = aColor;
218
- gl_PointSize = 300.0; // For big gaussians
219
- }
220
- `,
221
- fshader: `
222
- precision mediump float;
223
- varying vec3 vColor;
224
- void main(void) {
225
- vec2 cxy = 2.0 * gl_PointCoord - 1.0;
226
- float r = dot(cxy, cxy);
227
- float alpha = exp(-6.0 * r);
228
- if (r > 1.0) discard;
229
- gl_FragColor = vec4(vColor, alpha);
230
- }
231
- `
232
- });
233
- gsplatMat.update();
234
-
235
- // === MeshInstance ===
236
- const meshInstance = new pc.MeshInstance(this.entity, mesh, gsplatMat);
237
- this.entity.model = new pc.Model();
238
- this.entity.model.meshInstances = [meshInstance];
239
- this.entity.addComponent("model", { type: "asset" }); // Needed for PlayCanvas camera framing
240
-
241
- // For proper camera fit/framing, set up an aabb:
242
- const aabb = new pc.BoundingBox();
243
- for (let i = 0; i < this.numPoints; ++i) {
244
- aabb.add(new pc.Vec3(positions[i * 3 + 0], positions[i * 3 + 1], positions[i * 3 + 2]));
245
- }
246
- mesh.aabb = aabb;
247
- };
248
-
249
- GSplat.prototype.update = function (dt) {
250
- // All handled by GPU; nothing needed here
251
- };