Skip to content

Commit fd561dd

Browse files
mvaligurskyMartin Valigursky
andauthored
Add gsplatModifyVS shader customization chunk for gaussian splats (playcanvas#8246)
* Add gsplatModifySplatVS shader customization chunk for gaussian splats * ignore tag * hide constructor * lint * renamed --------- Co-authored-by: Martin Valigursky <mvaligursky@snapchat.com>
1 parent 59fa736 commit fd561dd

File tree

24 files changed

+403
-199
lines changed

24 files changed

+403
-199
lines changed

examples/src/examples/gaussian-splatting/multi-splat.example.mjs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ assetListLoader.load(() => {
7575
asset: assets.guitar
7676
});
7777
const customShaderFile = shaderLanguage === 'wgsl' ? 'shader.wgsl.vert' : 'shader.glsl.vert';
78-
guitar.gsplat.material.getShaderChunks(shaderLanguage).set('gsplatCustomizeVS', files[customShaderFile]);
78+
guitar.gsplat.material.getShaderChunks(shaderLanguage).set('gsplatModifyVS', files[customShaderFile]);
7979
guitar.setLocalPosition(0, 0.8, 0);
8080
guitar.setLocalEulerAngles(0, 0, 180);
8181
guitar.setLocalScale(0.4, 0.4, 0.4);
@@ -125,17 +125,17 @@ assetListLoader.load(() => {
125125

126126
const mat1 = biker.gsplat.material;
127127
if (useCustomShader) {
128-
mat1.getShaderChunks(shaderLanguage).set('gsplatCustomizeVS', vs);
128+
mat1.getShaderChunks(shaderLanguage).set('gsplatModifyVS', vs);
129129
} else {
130-
mat1.getShaderChunks(shaderLanguage).delete('gsplatCustomizeVS');
130+
mat1.getShaderChunks(shaderLanguage).delete('gsplatModifyVS');
131131
}
132132
mat1.update();
133133

134134
const mat2 = skull.gsplat.material;
135135
if (useCustomShader) {
136-
mat2.getShaderChunks(shaderLanguage).set('gsplatCustomizeVS', vs);
136+
mat2.getShaderChunks(shaderLanguage).set('gsplatModifyVS', vs);
137137
} else {
138-
mat2.getShaderChunks(shaderLanguage).delete('gsplatCustomizeVS');
138+
mat2.getShaderChunks(shaderLanguage).delete('gsplatModifyVS');
139139
}
140140
mat2.setDefine('CUTOUT', true);
141141
mat2.update();

examples/src/examples/gaussian-splatting/multi-splat.shader.glsl.vert

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
uniform float uTime;
22

3-
void modifyCenter(inout vec3 center) {
3+
void modifySplatCenter(inout vec3 center) {
44
// modify center
55
float heightIntensity = center.y * 0.2;
66
center.x += sin(uTime * 5.0 + center.y) * 0.3 * heightIntensity;
77
}
88

9-
void modifyCovariance(vec3 originalCenter, vec3 modifiedCenter, inout vec3 covA, inout vec3 covB) {
9+
void modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter, inout vec4 rotation, inout vec3 scale) {
1010
// no modification
1111
}
1212

13-
void modifyColor(vec3 center, inout vec4 clr) {
13+
void modifySplatColor(vec3 center, inout vec4 clr) {
1414
float sineValue = abs(sin(uTime * 5.0 + center.y));
1515

1616
#ifdef CUTOUT
@@ -25,4 +25,3 @@ void modifyColor(vec3 center, inout vec4 clr) {
2525
clr.xyz = mix(clr.xyz, gold, blend);
2626
#endif
2727
}
28-

examples/src/examples/gaussian-splatting/multi-splat.shader.wgsl.vert

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
uniform uTime: f32;
22

3-
fn modifyCenter(center: ptr<function, vec3f>) {
3+
fn modifySplatCenter(center: ptr<function, vec3f>) {
44
// modify center
55
let heightIntensity = (*center).y * 0.2;
66
(*center).x += sin(uniform.uTime * 5.0 + (*center).y) * 0.3 * heightIntensity;
77
}
88

9-
fn modifyCovariance(originalCenter: vec3f, modifiedCenter: vec3f, covA: ptr<function, vec3f>, covB: ptr<function, vec3f>) {
9+
fn modifySplatRotationScale(originalCenter: vec3f, modifiedCenter: vec3f, rotation: ptr<function, vec4f>, scale: ptr<function, vec3f>) {
1010
// no modification
1111
}
1212

13-
fn modifyColor(center: vec3f, clr: ptr<function, vec4f>) {
13+
fn modifySplatColor(center: vec3f, clr: ptr<function, vec4f>) {
1414
let sineValue = abs(sin(uniform.uTime * 5.0 + center.y));
1515

1616
#ifdef CUTOUT
@@ -25,4 +25,3 @@ fn modifyColor(center: vec3f, clr: ptr<function, vec4f>) {
2525
(*clr) = vec4f(mix((*clr).xyz, gold, blend), (*clr).a);
2626
#endif
2727
}
28-

scripts/esm/gsplat/gsplat-shader-effect.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class GsplatShaderEffect extends Script {
101101
const device = this.app.graphicsDevice;
102102
const shaderLanguage = device?.isWebGPU ? 'wgsl' : 'glsl';
103103

104-
this.material.getShaderChunks(shaderLanguage).delete('gsplatCustomizeVS');
104+
this.material.getShaderChunks(shaderLanguage).delete('gsplatModifyVS');
105105
this.material.update();
106106
this.material = null;
107107
}
@@ -139,7 +139,7 @@ class GsplatShaderEffect extends Script {
139139
const shaderLanguage = device?.isWebGPU ? 'wgsl' : 'glsl';
140140
const customShader = shaderLanguage === 'wgsl' ? this.getShaderWGSL() : this.getShaderGLSL();
141141

142-
material.getShaderChunks(shaderLanguage).set('gsplatCustomizeVS', customShader);
142+
material.getShaderChunks(shaderLanguage).set('gsplatModifyVS', customShader);
143143
material.update();
144144
}
145145

scripts/esm/gsplat/reveal-grid-eruption.mjs

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void initShared(vec3 center) {
3434
g_tEnd = g_tStart + uDuration;
3535
}
3636
37-
void modifyCenter(inout vec3 center) {
37+
void modifySplatCenter(inout vec3 center) {
3838
vec3 originalCenter = center;
3939
initShared(center);
4040
@@ -59,47 +59,47 @@ void modifyCenter(inout vec3 center) {
5959
// After movement: original position (no change needed)
6060
}
6161
62-
void modifyCovariance(vec3 originalCenter, vec3 modifiedCenter, inout vec3 covA, inout vec3 covB) {
62+
void modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter, inout vec4 rotation, inout vec3 scale) {
6363
// Check if animation is complete (after landing transition)
6464
float timeSinceLanding = uTime - g_tEnd;
6565
if (timeSinceLanding >= 0.3) return; // Effect complete, no modifications
6666
6767
// Early exit for distant splats during animation
6868
if (g_blockDist > uEndRadius) {
69-
gsplatMakeRound(covA, covB, 0.0);
69+
scale = vec3(0.0);
7070
return;
7171
}
7272
7373
// Before movement: invisible
7474
if (uTime < g_tStart) {
75-
gsplatMakeRound(covA, covB, 0.0);
75+
scale = vec3(0.0);
7676
return;
7777
}
7878
79+
// Store original scale for shape preservation
80+
vec3 origScale = scale;
81+
float origSize = gsplatGetSizeFromScale(scale);
82+
7983
// During landing transition after movement
8084
if (timeSinceLanding < 0.3) {
81-
float originalSize = gsplatExtractSize(covA, covB);
82-
8385
if (timeSinceLanding < 0.0) {
84-
// During movement: small round dots
85-
gsplatMakeRound(covA, covB, min(uDotSize, originalSize));
86+
// During movement: small spherical dots
87+
float targetSize = min(uDotSize, origSize);
88+
gsplatMakeSpherical(scale, targetSize);
8689
} else {
8790
// Landing transition: lerp from dots to original over 0.3s
8891
float t = timeSinceLanding * 3.333333; // normalize [0, 0.3] to [0, 1]
89-
float size = mix(uDotSize, originalSize, t);
92+
float size = mix(uDotSize, origSize, t);
9093
91-
// Lerp between round and original shape
92-
vec3 origCovA = covA;
93-
vec3 origCovB = covB;
94-
gsplatMakeRound(covA, covB, size);
95-
covA = mix(covA, origCovA, t);
96-
covB = mix(covB, origCovB, t);
94+
// Lerp between spherical (uniform) and original scale
95+
vec3 sphericalScale = vec3(size);
96+
scale = mix(sphericalScale, origScale, t);
9797
}
9898
}
9999
// After transition: original shape/size (no-op)
100100
}
101101
102-
void modifyColor(vec3 center, inout vec4 color) {
102+
void modifySplatColor(vec3 center, inout vec4 color) {
103103
// Check if animation is complete
104104
float timeSinceLanding = uTime - g_tEnd;
105105
if (timeSinceLanding >= uLandDuration) return; // Effect complete, no modifications
@@ -155,7 +155,7 @@ fn initShared(center: vec3f) {
155155
g_tEnd = g_tStart + uniform.uDuration;
156156
}
157157
158-
fn modifyCenter(center: ptr<function, vec3f>) {
158+
fn modifySplatCenter(center: ptr<function, vec3f>) {
159159
let originalCenter = *center;
160160
initShared(*center);
161161
@@ -184,7 +184,7 @@ fn modifyCenter(center: ptr<function, vec3f>) {
184184
// After movement: original position (no change needed)
185185
}
186186
187-
fn modifyCovariance(originalCenter: vec3f, modifiedCenter: vec3f, covA: ptr<function, vec3f>, covB: ptr<function, vec3f>) {
187+
fn modifySplatRotationScale(originalCenter: vec3f, modifiedCenter: vec3f, rotation: ptr<function, vec4f>, scale: ptr<function, vec3f>) {
188188
// Check if animation is complete (after landing transition)
189189
let timeSinceLanding = uniform.uTime - g_tEnd;
190190
if (timeSinceLanding >= 0.3) {
@@ -193,40 +193,40 @@ fn modifyCovariance(originalCenter: vec3f, modifiedCenter: vec3f, covA: ptr<func
193193
194194
// Early exit for distant splats during animation
195195
if (g_blockDist > uniform.uEndRadius) {
196-
gsplatMakeRound(covA, covB, 0.0);
196+
*scale = vec3f(0.0);
197197
return;
198198
}
199199
200200
// Before movement: invisible
201201
if (uniform.uTime < g_tStart) {
202-
gsplatMakeRound(covA, covB, 0.0);
202+
*scale = vec3f(0.0);
203203
return;
204204
}
205205
206+
// Store original scale for shape preservation
207+
let origScale = *scale;
208+
let origSize = gsplatGetSizeFromScale(*scale);
209+
206210
// During landing transition after movement
207211
if (timeSinceLanding < 0.3) {
208-
let originalSize = gsplatExtractSize(*covA, *covB);
209-
210212
if (timeSinceLanding < 0.0) {
211-
// During movement: small round dots
212-
gsplatMakeRound(covA, covB, min(uniform.uDotSize, originalSize));
213+
// During movement: small spherical dots
214+
let targetSize = min(uniform.uDotSize, origSize);
215+
gsplatMakeSpherical(scale, targetSize);
213216
} else {
214217
// Landing transition: lerp from dots to original over 0.3s
215218
let t = timeSinceLanding * 3.333333; // normalize [0, 0.3] to [0, 1]
216-
let size = mix(uniform.uDotSize, originalSize, t);
219+
let size = mix(uniform.uDotSize, origSize, t);
217220
218-
// Lerp between round and original shape
219-
let origCovA = *covA;
220-
let origCovB = *covB;
221-
gsplatMakeRound(covA, covB, size);
222-
*covA = mix(*covA, origCovA, t);
223-
*covB = mix(*covB, origCovB, t);
221+
// Lerp between spherical (uniform) and original scale
222+
let sphericalScale = vec3f(size);
223+
*scale = mix(sphericalScale, origScale, t);
224224
}
225225
}
226226
// After transition: original shape/size (no-op)
227227
}
228228
229-
fn modifyColor(center: vec3f, color: ptr<function, vec4f>) {
229+
fn modifySplatColor(center: vec3f, color: ptr<function, vec4f>) {
230230
// Check if animation is complete
231231
let timeSinceLanding = uniform.uTime - g_tEnd;
232232
if (timeSinceLanding >= uniform.uLandDuration) {

0 commit comments

Comments
 (0)