Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert gsplat material to be chunk-based #7164

Merged
merged 19 commits into from
Dec 3, 2024
1 change: 0 additions & 1 deletion examples/src/examples/loaders/gsplat-many.example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ assetListLoader.load(() => {

// instantiate guitar with a custom shader
const guitar = assets.guitar.resource.instantiate({
fragment: files['shader.frag'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to do the color animation in fragment shader as an example on how to do it .. it handles long splats better than per vertex.

vertex: files['shader.vert']
});
guitar.name = 'guitar';
Expand Down
34 changes: 0 additions & 34 deletions examples/src/examples/loaders/gsplat-many.shader.frag

This file was deleted.

103 changes: 51 additions & 52 deletions examples/src/examples/loaders/gsplat-many.shader.vert
Original file line number Diff line number Diff line change
@@ -1,79 +1,78 @@
#include "gsplatCommonVS"

varying mediump vec2 gaussianUV;
varying mediump vec4 gaussianColor;

#ifndef DITHER_NONE
varying float id;
#endif

mediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0);

uniform float uTime;
varying float height;

void animate(inout vec3 center) {
vec3 animatePosition(vec3 center) {
// modify center
float heightIntensity = center.y * 0.2;
center.x += sin(uTime * 5.0 + center.y) * 0.3 * heightIntensity;

// output y-coordinate
height = center.y;
return center;
}

uniform vec3 view_position;

uniform sampler2D splatColor;

varying mediump vec2 texCoord;
varying mediump vec4 color;
vec4 animateColor(float height, vec4 clr) {
float sineValue = abs(sin(uTime * 5.0 + height));

#ifdef CUTOUT
// in cutout mode, remove pixels along the wave
if (sineValue < 0.5) {
clr.a = 0.0;
}
#else
// in non-cutout mode, add a golden tint to the wave
vec3 gold = vec3(1.0, 0.85, 0.0);
float blend = smoothstep(0.9, 1.0, sineValue);
clr.xyz = mix(clr.xyz, gold, blend);
#endif

mediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0);
return clr;
}

void main(void)
{
// calculate splat uv
if (!calcSplatUV()) {
void main(void) {
// read gaussian center
SplatState state;
if (!readCenter(state)) {
gl_Position = discardVec;
return;
}

// get center
vec3 center = getCenter();

animate(center);
state.center = animatePosition(state.center);

// handle transforms
mat4 model_view = matrix_view * matrix_model;
vec4 splat_cam = model_view * vec4(center, 1.0);
vec4 splat_proj = matrix_projection * splat_cam;

// cull behind camera
if (splat_proj.z < -splat_proj.w) {
// project center to screen space
ProjectedState projState;
if (!projectCenter(state, projState)) {
gl_Position = discardVec;
return;
}

// get covariance
vec3 covA, covB;
getCovariance(covA, covB);

vec4 v1v2 = calcV1V2(splat_cam.xyz, covA, covB, transpose(mat3(model_view)));

// get color
color = texelFetch(splatColor, splatUV, 0);
// read color
vec4 clr = readColor(state);

// calculate scale based on alpha
float scale = min(1.0, sqrt(-log(1.0 / 255.0 / color.a)) / 2.0);

v1v2 *= scale;

// early out tiny splats
if (dot(v1v2.xy, v1v2.xy) < 4.0 && dot(v1v2.zw, v1v2.zw) < 4.0) {
gl_Position = discardVec;
return;
}
// evaluate spherical harmonics
#if SH_BANDS > 0
clr.xyz = max(clr.xyz + evalSH(state, projState), 0.0);
#endif

gl_Position = splat_proj + vec4((vertex_position.x * v1v2.xy + vertex_position.y * v1v2.zw) / viewport * splat_proj.w, 0, 0);
clr = animateColor(state.center.y, clr);

texCoord = vertex_position.xy * scale / 2.0;
applyClipping(projState, clr.w);

#ifdef USE_SH1
vec4 worldCenter = matrix_model * vec4(center, 1.0);
vec3 viewDir = normalize((worldCenter.xyz / worldCenter.w - view_position) * mat3(matrix_model));
color.xyz = max(color.xyz + evalSH(viewDir), 0.0);
#endif
// write output
gl_Position = projState.cornerProj;
gaussianUV = projState.cornerUV;
gaussianColor = vec4(prepareOutputFromGamma(clr.xyz), clr.w);

#ifndef DITHER_NONE
id = float(splatId);
id = float(state.id);
#endif
}
}
3 changes: 3 additions & 0 deletions src/core/hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* @returns {number} Hash value.
*/
function hashCode(str) {
if (str === null || str === undefined) {
return 0;
}
let hash = 0;
for (let i = 0, len = str.length; i < len; i++) {
hash = ((hash << 5) - hash) + str.charCodeAt(i);
Expand Down
Loading
Loading