UNPKG

@animech-public/playcanvas

Version:
89 lines (86 loc) 3.47 kB
import { CULLFACE_NONE } from '../../platform/graphics/constants.js'; import { ShaderProcessorOptions } from '../../platform/graphics/shader-processor-options.js'; import { DITHER_NONE, BLEND_NONE, BLEND_NORMAL, SHADER_FORWARDHDR, GAMMA_SRGBHDR, GAMMA_NONE, TONEMAP_LINEAR } from '../constants.js'; import { Material } from '../materials/material.js'; import { getProgramLibrary } from '../shader-lib/get-program-library.js'; import { gsplat } from './shader-generator-gsplat.js'; const splatMainVS = ` uniform vec3 view_position; uniform sampler2D splatColor; varying mediump vec2 texCoord; varying mediump vec4 color; mediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0); void main(void) { if (!calcSplatUV()) { gl_Position = discardVec; return; } vec3 center = getCenter(); mat4 model_view = matrix_view * matrix_model; vec4 splat_cam = model_view * vec4(center, 1.0); if (splat_cam.z > 0.0) { gl_Position = discardVec; return; } vec4 splat_proj = matrix_projection * splat_cam; splat_proj.z = clamp(splat_proj.z, -abs(splat_proj.w), abs(splat_proj.w)); vec3 covA, covB; getCovariance(covA, covB); vec4 v1v2 = calcV1V2(splat_cam.xyz, covA, covB, transpose(mat3(model_view))); color = texelFetch(splatColor, splatUV, 0); float scale = min(1.0, sqrt(-log(1.0 / 255.0 / color.a)) / 2.0); v1v2 *= scale; if (dot(v1v2.xy, v1v2.xy) < 4.0 && dot(v1v2.zw, v1v2.zw) < 4.0) { gl_Position = discardVec; return; } gl_Position = splat_proj + vec4((vertex_position.x * v1v2.xy + vertex_position.y * v1v2.zw) / viewport * splat_proj.w, 0, 0); texCoord = vertex_position.xy * scale / 2.0; #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 #ifndef DITHER_NONE id = float(splatId); #endif } `; const splatMainFS = ` varying mediump vec2 texCoord; varying mediump vec4 color; void main(void) { gl_FragColor = evalSplat(texCoord, color); } `; const createGSplatMaterial = (options = {}) => { var _options$dither; const ditherEnum = (_options$dither = options.dither) != null ? _options$dither : DITHER_NONE; const dither = ditherEnum !== DITHER_NONE; const material = new Material(); material.name = 'splatMaterial'; material.cull = CULLFACE_NONE; material.blendType = dither ? BLEND_NONE : BLEND_NORMAL; material.depthWrite = dither; material.getShaderVariant = function (device, scene, defs, unused, pass, sortedLights, viewUniformFormat, viewBindGroupFormat) { var _options$vertex, _options$fragment; const programOptions = { pass: pass, gamma: pass === SHADER_FORWARDHDR ? scene.gammaCorrection ? GAMMA_SRGBHDR : GAMMA_NONE : scene.gammaCorrection, toneMapping: pass === SHADER_FORWARDHDR ? TONEMAP_LINEAR : scene.toneMapping, vertex: (_options$vertex = options.vertex) != null ? _options$vertex : splatMainVS, fragment: (_options$fragment = options.fragment) != null ? _options$fragment : splatMainFS, dither: ditherEnum, defines: options.defines }; const processingOptions = new ShaderProcessorOptions(viewUniformFormat, viewBindGroupFormat); const library = getProgramLibrary(device); library.register('splat', gsplat); return library.getProgram('splat', programOptions, processingOptions); }; material.update(); return material; }; export { createGSplatMaterial };