Skip to content

Commit 4d0c53f

Browse files
committed
Further gsplat shader refinements (#7185)
1 parent a462235 commit 4d0c53f

File tree

16 files changed

+222
-186
lines changed

16 files changed

+222
-186
lines changed

examples/src/examples/loaders/gsplat-many.shader.vert

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,37 +40,41 @@ vec4 animateColor(float height, vec4 clr) {
4040

4141
void main(void) {
4242
// read gaussian center
43-
SplatState state;
44-
if (!initState(state)) {
43+
SplatSource source;
44+
if (!initSource(source)) {
4545
gl_Position = discardVec;
4646
return;
4747
}
4848

49-
vec3 center = animatePosition(readCenter(state));
49+
vec3 centerPos = animatePosition(readCenter(source));
50+
51+
SplatCenter center;
52+
initCenter(source, centerPos, center);
5053

5154
// project center to screen space
52-
ProjectedState projState;
53-
if (!projectCenter(state, center, projState)) {
55+
SplatCorner corner;
56+
if (!initCorner(source, center, corner)) {
5457
gl_Position = discardVec;
5558
return;
5659
}
5760

5861
// read color
59-
vec4 clr = readColor(state);
62+
vec4 clr = readColor(source);
6063

6164
// evaluate spherical harmonics
6265
#if SH_BANDS > 0
63-
clr.xyz = max(clr.xyz + evalSH(state, projState), 0.0);
66+
vec3 dir = normalize(center.view * mat3(center.modelView));
67+
clr.xyz += evalSH(state, dir);
6468
#endif
6569

66-
clr = animateColor(center.y, clr);
70+
clr = animateColor(centerPos.y, clr);
6771

68-
applyClipping(projState, clr.w);
72+
clipCorner(corner, clr.w);
6973

7074
// write output
71-
gl_Position = projState.cornerProj;
72-
gaussianUV = projState.cornerUV;
73-
gaussianColor = vec4(prepareOutputFromGamma(clr.xyz), clr.w);
75+
gl_Position = center.proj + vec4(corner.offset, 0.0, 0.0);
76+
gaussianUV = corner.uv;
77+
gaussianColor = vec4(prepareOutputFromGamma(max(clr.xyz, 0.0)), clr.w);
7478

7579
#ifndef DITHER_NONE
7680
id = float(state.id);

src/scene/gsplat/gsplat-compressed.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class GSplatCompressed {
2727

2828
numSplats;
2929

30+
numSplatsVisible;
31+
3032
/** @type {BoundingBox} */
3133
aabb;
3234

@@ -57,6 +59,7 @@ class GSplatCompressed {
5759

5860
this.device = device;
5961
this.numSplats = numSplats;
62+
this.numVisibleSplats = numSplats;
6063

6164
// initialize aabb
6265
this.aabb = new BoundingBox();
@@ -147,7 +150,7 @@ class GSplatCompressed {
147150
result.setDefine('GSPLAT_COMPRESSED_DATA', true);
148151
result.setParameter('packedTexture', this.packedTexture);
149152
result.setParameter('chunkTexture', this.chunkTexture);
150-
result.setParameter('tex_params', new Float32Array([this.numSplats, this.packedTexture.width, this.chunkTexture.width / 5]));
153+
result.setParameter('numSplats', this.numSplatsVisible);
151154
if (this.shTexture0) {
152155
result.setDefine('SH_BANDS', 3);
153156
result.setParameter('shTexture0', this.shTexture0);

src/scene/gsplat/gsplat-instance.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,7 @@ class GSplatInstance {
143143
this.meshInstance.instancingCount = Math.ceil(count / splatInstanceSize);
144144

145145
// update splat count on the material
146-
const tex_params = this.material.getParameter('tex_params');
147-
if (tex_params?.data) {
148-
tex_params.data[0] = count;
149-
}
146+
this.material.setParameter('numSplats', count);
150147
});
151148
}
152149
}

src/scene/gsplat/gsplat.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class GSplat {
3131

3232
numSplats;
3333

34+
numSplatsVisible;
35+
3436
/** @type {Float32Array} */
3537
centers;
3638

@@ -70,6 +72,7 @@ class GSplat {
7072

7173
this.device = device;
7274
this.numSplats = numSplats;
75+
this.numSplatsVisible = numSplats;
7376

7477
this.centers = new Float32Array(gsplatData.numSplats * 3);
7578
gsplatData.getCenters(this.centers);
@@ -116,7 +119,7 @@ class GSplat {
116119
result.setParameter('splatColor', this.colorTexture);
117120
result.setParameter('transformA', this.transformATexture);
118121
result.setParameter('transformB', this.transformBTexture);
119-
result.setParameter('tex_params', new Float32Array([this.numSplats, this.colorTexture.width]));
122+
result.setParameter('numSplats', this.numSplatsVisible);
120123
if (this.hasSH) {
121124
result.setDefine('SH_BANDS', 3);
122125
result.setParameter('splatSH_1to3', this.sh1to3Texture);

src/scene/shader-lib/chunks/chunks.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ import gamma2_2PS from './common/frag/gamma2_2.js';
5656
import gles3PS from '../../../platform/graphics/shader-chunks/frag/gles3.js';
5757
import gles3VS from '../../../platform/graphics/shader-chunks/vert/gles3.js';
5858
import glossPS from './standard/frag/gloss.js';
59+
import gsplatCenterVS from './gsplat/vert/gsplatCenter.js';
5960
import gsplatColorVS from './gsplat/vert/gsplatColor.js';
6061
import gsplatCommonVS from './gsplat/vert/gsplatCommon.js';
6162
import gsplatCompressedDataVS from './gsplat/vert/gsplatCompressedData.js';
6263
import gsplatCompressedSHVS from './gsplat/vert/gsplatCompressedSH.js';
64+
import gsplatCornerVS from './gsplat/vert/gsplatCorner.js';
6365
import gsplatDataVS from './gsplat/vert/gsplatData.js';
64-
import gsplatOutputPS from './gsplat/gsplatOutput.js';
66+
import gsplatOutputVS from './gsplat/vert/gsplatOutput.js';
6567
import gsplatPS from './gsplat/frag/gsplat.js';
6668
import gsplatSHVS from './gsplat/vert/gsplatSH.js';
69+
import gsplatSourceVS from './gsplat/vert/gsplatSource.js';
6770
import gsplatVS from './gsplat/vert/gsplat.js';
6871
import iridescenceDiffractionPS from './lit/frag/iridescenceDiffraction.js';
6972
import iridescencePS from './standard/frag/iridescence.js';
@@ -266,14 +269,17 @@ const shaderChunks = {
266269
gles3PS,
267270
gles3VS,
268271
glossPS,
272+
gsplatCenterVS,
273+
gsplatCornerVS,
269274
gsplatColorVS,
270275
gsplatCommonVS,
271276
gsplatCompressedDataVS,
272277
gsplatCompressedSHVS,
273278
gsplatDataVS,
274-
gsplatOutputPS,
279+
gsplatOutputVS,
275280
gsplatPS,
276281
gsplatSHVS,
282+
gsplatSourceVS,
277283
gsplatVS,
278284
iridescenceDiffractionPS,
279285
iridescencePS,

src/scene/shader-lib/chunks/gsplat/vert/gsplat.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,43 @@ mediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0);
1212
1313
void main(void) {
1414
// read gaussian details
15-
SplatState state;
16-
if (!initState(state)) {
15+
SplatSource source;
16+
if (!initSource(source)) {
1717
gl_Position = discardVec;
1818
return;
1919
}
2020
21-
vec3 center = readCenter(state);
21+
vec3 modelCenter = readCenter(source);
22+
23+
SplatCenter center;
24+
initCenter(source, modelCenter, center);
2225
2326
// project center to screen space
24-
ProjectedState projState;
25-
if (!projectCenter(state, center, projState)) {
27+
SplatCorner corner;
28+
if (!initCorner(source, center, corner)) {
2629
gl_Position = discardVec;
2730
return;
2831
}
2932
3033
// read color
31-
vec4 clr = readColor(state);
34+
vec4 clr = readColor(source);
3235
3336
// evaluate spherical harmonics
3437
#if SH_BANDS > 0
35-
clr.xyz += evalSH(state, projState);
38+
// calculate the model-space view direction
39+
vec3 dir = normalize(center.view * mat3(center.modelView));
40+
clr.xyz += evalSH(source, dir);
3641
#endif
3742
38-
applyClipping(projState, clr.w);
43+
clipCorner(corner, clr.w);
3944
4045
// write output
41-
gl_Position = projState.cornerProj;
42-
gaussianUV = projState.cornerUV;
46+
gl_Position = center.proj + vec4(corner.offset, 0, 0);
47+
gaussianUV = corner.uv;
4348
gaussianColor = vec4(prepareOutputFromGamma(max(clr.xyz, 0.0)), clr.w);
4449
4550
#ifndef DITHER_NONE
46-
id = float(state.id);
51+
id = float(source.id);
4752
#endif
4853
}
4954
`;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export default /* glsl */`
2+
uniform mat4 matrix_model;
3+
uniform mat4 matrix_view;
4+
uniform mat4 matrix_projection;
5+
6+
// project the model space gaussian center to view and clip space
7+
bool initCenter(SplatSource source, vec3 modelCenter, out SplatCenter center) {
8+
mat4 modelView = matrix_view * matrix_model;
9+
vec4 centerView = modelView * vec4(modelCenter, 1.0);
10+
11+
// early out if splat is behind the camear
12+
if (centerView.z > 0.0) {
13+
return false;
14+
}
15+
16+
vec4 centerProj = matrix_projection * centerView;
17+
18+
// ensure gaussians are not clipped by camera near and far
19+
centerProj.z = clamp(centerProj.z, -abs(centerProj.w), abs(centerProj.w));
20+
21+
center.view = centerView.xyz / centerView.w;
22+
center.proj = centerProj;
23+
center.projMat00 = matrix_projection[0][0];
24+
center.modelView = modelView;
25+
return true;
26+
}
27+
`;

src/scene/shader-lib/chunks/gsplat/vert/gsplatColor.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ export default /* glsl */`
22
33
uniform mediump sampler2D splatColor;
44
5-
vec4 readColor(in SplatState state) {
6-
return texelFetch(splatColor, state.uv, 0);
5+
vec4 readColor(in SplatSource source) {
6+
return texelFetch(splatColor, source.uv, 0);
77
}
88
99
`;

0 commit comments

Comments
 (0)