playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
144 lines (111 loc) • 4.83 kB
JavaScript
var gsplatCopyToWorkbuffer_default = (
/* wgsl */
`
// pre-computed model matrix decomposition (declared before includes, used by
// gsplatWorkBufferGeometryPS)
uniform model_scale: vec3f;
uniform model_rotation: vec4f; // (x,y,z,w) format
// Module-scope output for write functions to access
var<private> processOutput: FragmentOutput;
// Work buffer output write functions (generated by GSplatFormat.getOutputDeclarations)
// Packed sub-draw params: (sourceBase, colStart, rowWidth, rowStart)
varying @interpolate(flat) vSubDraw: vec4i;
uniform uColorMultiply: vec3f;
uniform uId: u32;
@fragment
fn fragmentMain(input: FragmentInput) -> FragmentOutput {
// Compute source index from packed sub-draw varying: (sourceBase, colStart, rowWidth, rowStart)
let localRow = i32(input.position.y) - input.vSubDraw.w;
let localCol = i32(input.position.x) - input.vSubDraw.y;
let originalIndex = u32(input.vSubDraw.x + localRow * input.vSubDraw.z + localCol);
// Initialize global splat for format read functions
setSplat(originalIndex);
// World-space geometry to store. Rotation/scale default to identity and are only computed on
// the full-render path; under GSPLAT_COLOR_ONLY they are ignored by writeSplat (DCE'd).
var worldCenter: vec3f;
var worldRotation = vec4f(0.0, 0.0, 0.0, 1.0);
var worldScale = vec3f(1.0);
var dir: vec3f; // model-space view direction
// Color-only update sourcing geometry from previously written work buffer data at this
// destination pixel. The stored center already includes the model transform and
// modifySplatCenter / modifySplatRotationScale, so neither is re-applied here.
initWorkBufferGeometry(vec2i(input.position.xy));
worldCenter = workBufferWorldCenter();
// model-space view direction (matches the source path up to non-uniform model scale)
dir = normalize(quatRotateInv(uniform.model_rotation, worldCenter - uniform.uCameraPosition));
// read center in local space
var modelCenter = getCenter();
// compute world-space center for storage
worldCenter = (uniform.matrix_model * vec4f(modelCenter, 1.0)).xyz;
var center: SplatCenter;
initCenter(modelCenter, ¢er);
// Get source rotation and scale
// getRotation() returns (w,x,y,z) format, convert to (x,y,z,w) for quatMul
let srcRotation = getRotation().yzwx;
let srcScale = getScale();
// Combine: world = model * source (both in x,y,z,w format)
worldRotation = vec4f(quatMul(half4(uniform.model_rotation), half4(srcRotation)));
// Ensure w is positive so sqrt() reconstruction works correctly
// (quaternions q and -q represent the same rotation)
if (worldRotation.w < 0.0) {
worldRotation = -worldRotation;
}
worldScale = uniform.model_scale * srcScale;
// Apply custom center modification
let originalCenter = worldCenter;
modifySplatCenter(&worldCenter);
// Apply custom rotation/scale modification
modifySplatRotationScale(originalCenter, worldCenter, &worldRotation, &worldScale);
// calculate the model-space view direction
dir = normalize(center.view * mat3x3f(center.modelView[0].xyz, center.modelView[1].xyz, center.modelView[2].xyz));
// read color
var color = getColor();
// evaluate spherical harmonics
// read sh coefficients
var sh: array<half3, SH_COEFFS>;
var scale: f32;
readSHData(&sh, &scale);
// evaluate
color = vec4f(color.xyz + vec3f(evalSH(&sh, dir) * half(scale)), color.w);
// Apply custom color modification
modifySplatColor(worldCenter, &color);
color = vec4f(color.xyz * uniform.uColorMultiply, color.w);
// write color + transform using format-specific encoding (rotation/scale ignored under
// GSPLAT_COLOR_ONLY)
writeSplat(worldCenter, worldRotation, worldScale, color);
writePcId(vec4u(uniform.uId, 0u, 0u, 0u));
return processOutput;
}
`
);
export {
gsplatCopyToWorkbuffer_default as default
};