@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 12.5 kB
JavaScript
import{CULLFACE_NONE as t,SEMANTIC_POSITION as n,SEMANTIC_ATTR13 as e}from"../../platform/graphics/constants.js";import{ShaderProcessorOptions as a}from"../../platform/graphics/shader-processor-options.js";import{DITHER_NONE as r,BLEND_NONE as c,BLEND_NORMAL as o,SHADER_FORWARDHDR as i,GAMMA_SRGBHDR as s,GAMMA_NONE as d,TONEMAP_LINEAR as v}from"../constants.js";import{Material as u}from"../materials/material.js";import{getProgramLibrary as l}from"../shader-lib/get-program-library.js";import{hashCode as f}from"../../core/hash.js";import{ShaderUtils as m}from"../../platform/graphics/shader-utils.js";import{shaderChunks as p}from"../shader-lib/chunks/chunks.js";import{ShaderGenerator as x}from"../shader-lib/programs/shader-generator.js";import{ShaderPass as h}from"../shader-pass.js";const _=new class{generateKey(t){var n,e;const a=f(t.vertex),r=f(t.fragment),c=null!=(n=null==(e=t.defines)?void 0:e.sort().join("-"))?n:"";return`splat-${t.pass}-${t.gamma}-${t.toneMapping}-${a}-${r}-${t.dither}-${c}`}createShaderDefinition(t,a){var c;const o=`${h.get(t).getByIndex(a.pass).shaderDefines}\n${(null!=(c=a.defines)?c:[]).map((t=>`#define ${t}`)).join("\n")}\n#define DITHER_${a.dither.toUpperCase()}\n#define TONEMAP_${a.toneMapping===v?"DISABLED":"ENABLED"}\n`,i=o+"\n\tuniform mat4 matrix_model;\n\tuniform mat4 matrix_view;\n\tuniform mat4 matrix_projection;\n\tuniform vec2 viewport;\n\tuniform vec4 tex_params;\n\tuniform highp usampler2D splatOrder;\n\tuniform highp usampler2D packedTexture;\n\tuniform highp sampler2D chunkTexture;\n\tattribute vec3 vertex_position;\n\tattribute uint vertex_id_attrib;\n\t#ifndef DITHER_NONE\n\t\tvarying float id;\n\t#endif\n\tuint orderId;\n\tuint splatId;\n\tivec2 packedUV;\n\tivec2 chunkUV;\n\tvec4 chunkDataA;\n\tvec4 chunkDataB;\n\tvec4 chunkDataC;\n\tvec4 chunkDataD;\n\tvec4 chunkDataE;\n\tuvec4 packedData;\n\tbool calcSplatUV() {\n\t\tuint numSplats = uint(tex_params.x);\n\t\tuint packedWidth = uint(tex_params.y);\n\t\tuint chunkWidth = uint(tex_params.z);\n\t\torderId = vertex_id_attrib + uint(vertex_position.z);\n\t\tif (orderId >= numSplats) {\n\t\t\treturn false;\n\t\t}\n\t\tivec2 orderUV = ivec2(\n\t\t\tint(orderId % packedWidth),\n\t\t\tint(orderId / packedWidth)\n\t\t);\n\t\tsplatId = texelFetch(splatOrder, orderUV, 0).r;\n\t\tpackedUV = ivec2(\n\t\t\tint(splatId % packedWidth),\n\t\t\tint(splatId / packedWidth)\n\t\t);\n\t\tuint chunkId = splatId / 256u;\n\t\tchunkUV = ivec2(\n\t\t\tint((chunkId % chunkWidth) * 5u),\n\t\t\tint(chunkId / chunkWidth)\n\t\t);\n\t\treturn true;\n\t}\n\tvoid readData() {\n\t\tchunkDataA = texelFetch(chunkTexture, chunkUV, 0);\n\t\tchunkDataB = texelFetch(chunkTexture, ivec2(chunkUV.x + 1, chunkUV.y), 0);\n\t\tchunkDataC = texelFetch(chunkTexture, ivec2(chunkUV.x + 2, chunkUV.y), 0);\n\t\tchunkDataD = texelFetch(chunkTexture, ivec2(chunkUV.x + 3, chunkUV.y), 0);\n\t\tchunkDataE = texelFetch(chunkTexture, ivec2(chunkUV.x + 4, chunkUV.y), 0);\n\t\tpackedData = texelFetch(packedTexture, packedUV, 0);\n\t}\n\tvec3 unpack111011(uint bits) {\n\t\treturn vec3(\n\t\t\tfloat(bits >> 21u) / 2047.0,\n\t\t\tfloat((bits >> 11u) & 0x3ffu) / 1023.0,\n\t\t\tfloat(bits & 0x7ffu) / 2047.0\n\t\t);\n\t}\n\tvec4 unpack8888(uint bits) {\n\t\treturn vec4(\n\t\t\tfloat(bits >> 24u) / 255.0,\n\t\t\tfloat((bits >> 16u) & 0xffu) / 255.0,\n\t\t\tfloat((bits >> 8u) & 0xffu) / 255.0,\n\t\t\tfloat(bits & 0xffu) / 255.0\n\t\t);\n\t}\n\tfloat norm = 1.0 / (sqrt(2.0) * 0.5);\n\tvec4 unpackRotation(uint bits) {\n\t\tfloat a = (float((bits >> 20u) & 0x3ffu) / 1023.0 - 0.5) * norm;\n\t\tfloat b = (float((bits >> 10u) & 0x3ffu) / 1023.0 - 0.5) * norm;\n\t\tfloat c = (float(bits & 0x3ffu) / 1023.0 - 0.5) * norm;\n\t\tfloat m = sqrt(1.0 - (a * a + b * b + c * c));\n\t\tuint mode = bits >> 30u;\n\t\tif (mode == 0u) return vec4(m, a, b, c);\n\t\tif (mode == 1u) return vec4(a, m, b, c);\n\t\tif (mode == 2u) return vec4(a, b, m, c);\n\t\treturn vec4(a, b, c, m);\n\t}\n\tvec3 getCenter() {\n\t\treturn mix(chunkDataA.xyz, vec3(chunkDataA.w, chunkDataB.xy), unpack111011(packedData.x));\n\t}\n\tvec4 getRotation() {\n\t\treturn unpackRotation(packedData.y);\n\t}\n\tvec3 getScale() {\n\t\treturn exp(mix(vec3(chunkDataB.zw, chunkDataC.x), chunkDataC.yzw, unpack111011(packedData.z)));\n\t}\n\tvec4 getColor() {\n\t\tvec4 r = unpack8888(packedData.w);\n\t\treturn vec4(mix(chunkDataD.xyz, vec3(chunkDataD.w, chunkDataE.xy), r.rgb), r.w);\n\t}\n\tmat3 quatToMat3(vec4 R) {\n\t\tfloat x = R.x;\n\t\tfloat y = R.y;\n\t\tfloat z = R.z;\n\t\tfloat w = R.w;\n\t\treturn mat3(\n\t\t\t1.0 - 2.0 * (z * z + w * w),\n\t\t\t\t 2.0 * (y * z + x * w),\n\t\t\t\t 2.0 * (y * w - x * z),\n\t\t\t\t 2.0 * (y * z - x * w),\n\t\t\t1.0 - 2.0 * (y * y + w * w),\n\t\t\t\t 2.0 * (z * w + x * y),\n\t\t\t\t 2.0 * (y * w + x * z),\n\t\t\t\t 2.0 * (z * w - x * y),\n\t\t\t1.0 - 2.0 * (y * y + z * z)\n\t\t);\n\t}\n\tvoid getCovariance(out vec3 covA, out vec3 covB) {\n\t\tmat3 rot = quatToMat3(getRotation());\n\t\tvec3 scale = getScale();\n\t\tmat3 M = transpose(mat3(\n\t\t\tscale.x * rot[0],\n\t\t\tscale.y * rot[1],\n\t\t\tscale.z * rot[2]\n\t\t));\n\t\tcovA = vec3(dot(M[0], M[0]), dot(M[0], M[1]), dot(M[0], M[2]));\n\t\tcovB = vec3(dot(M[1], M[1]), dot(M[1], M[2]), dot(M[2], M[2]));\n\t}\n\tvec4 calcV1V2(in vec3 splat_cam, in vec3 covA, in vec3 covB, mat3 W) {\n\t\tmat3 Vrk = mat3(\n\t\t\tcovA.x, covA.y, covA.z, \n\t\t\tcovA.y, covB.x, covB.y,\n\t\t\tcovA.z, covB.y, covB.z\n\t\t);\n\t\tfloat focal = viewport.x * matrix_projection[0][0];\n\t\tfloat J1 = focal / splat_cam.z;\n\t\tvec2 J2 = -J1 / splat_cam.z * splat_cam.xy;\n\t\tmat3 J = mat3(\n\t\t\tJ1, 0.0, J2.x, \n\t\t\t0.0, J1, J2.y, \n\t\t\t0.0, 0.0, 0.0\n\t\t);\n\t\tmat3 T = W * J;\n\t\tmat3 cov = transpose(T) * Vrk * T;\n\t\tfloat diagonal1 = cov[0][0] + 0.3;\n\t\tfloat offDiagonal = cov[0][1];\n\t\tfloat diagonal2 = cov[1][1] + 0.3;\n\t\tfloat mid = 0.5 * (diagonal1 + diagonal2);\n\t\tfloat radius = length(vec2((diagonal1 - diagonal2) / 2.0, offDiagonal));\n\t\tfloat lambda1 = mid + radius;\n\t\tfloat lambda2 = max(mid - radius, 0.1);\n\t\tvec2 diagonalVector = normalize(vec2(offDiagonal, lambda1 - diagonal1));\n\t\tvec2 v1 = min(sqrt(2.0 * lambda1), 1024.0) * diagonalVector;\n\t\tvec2 v2 = min(sqrt(2.0 * lambda2), 1024.0) * vec2(diagonalVector.y, -diagonalVector.x);\n\t\treturn vec4(v1, v2);\n\t}\n#if defined(USE_SH)\n\t#define SH_C1 0.4886025119029199f\n\t#define SH_C2_0 1.0925484305920792f\n\t#define SH_C2_1 -1.0925484305920792f\n\t#define SH_C2_2 0.31539156525252005f\n\t#define SH_C2_3 -1.0925484305920792f\n\t#define SH_C2_4 0.5462742152960396f\n\t#define SH_C3_0 -0.5900435899266435f\n\t#define SH_C3_1 2.890611442640554f\n\t#define SH_C3_2 -0.4570457994644658f\n\t#define SH_C3_3 0.3731763325901154f\n\t#define SH_C3_4 -0.4570457994644658f\n\t#define SH_C3_5 1.445305721320277f\n\t#define SH_C3_6 -0.5900435899266435f\n\tuniform highp usampler2D shTexture0;\n\tuniform highp usampler2D shTexture1;\n\tuniform highp usampler2D shTexture2;\n\tvec4 sunpack8888(in uint bits) {\n\t\treturn vec4((uvec4(bits) >> uvec4(0u, 8u, 16u, 24u)) & 0xffu) * (8.0 / 255.0) - 4.0;\n\t}\n\tvoid readSHData(out vec3 sh[15]) {\n\t\tuvec4 shData0 = texelFetch(shTexture0, packedUV, 0);\n\t\tuvec4 shData1 = texelFetch(shTexture1, packedUV, 0);\n\t\tuvec4 shData2 = texelFetch(shTexture2, packedUV, 0);\n\t\tvec4 r0 = sunpack8888(shData0.x);\n\t\tvec4 r1 = sunpack8888(shData0.y);\n\t\tvec4 r2 = sunpack8888(shData0.z);\n\t\tvec4 r3 = sunpack8888(shData0.w);\n\t\tvec4 g0 = sunpack8888(shData1.x);\n\t\tvec4 g1 = sunpack8888(shData1.y);\n\t\tvec4 g2 = sunpack8888(shData1.z);\n\t\tvec4 g3 = sunpack8888(shData1.w);\n\t\tvec4 b0 = sunpack8888(shData2.x);\n\t\tvec4 b1 = sunpack8888(shData2.y);\n\t\tvec4 b2 = sunpack8888(shData2.z);\n\t\tvec4 b3 = sunpack8888(shData2.w);\n\t\tsh[0] = vec3(r0.x, g0.x, b0.x);\n\t\tsh[1] = vec3(r0.y, g0.y, b0.y);\n\t\tsh[2] = vec3(r0.z, g0.z, b0.z);\n\t\tsh[3] = vec3(r0.w, g0.w, b0.w);\n\t\tsh[4] = vec3(r1.x, g1.x, b1.x);\n\t\tsh[5] = vec3(r1.y, g1.y, b1.y);\n\t\tsh[6] = vec3(r1.z, g1.z, b1.z);\n\t\tsh[7] = vec3(r1.w, g1.w, b1.w);\n\t\tsh[8] = vec3(r2.x, g2.x, b2.x);\n\t\tsh[9] = vec3(r2.y, g2.y, b2.y);\n\t\tsh[10] = vec3(r2.z, g2.z, b2.z);\n\t\tsh[11] = vec3(r2.w, g2.w, b2.w);\n\t\tsh[12] = vec3(r3.x, g3.x, b3.x);\n\t\tsh[13] = vec3(r3.y, g3.y, b3.y);\n\t\tsh[14] = vec3(r3.z, g3.z, b3.z);\n\t}\n\tvec3 evalSH(in vec3 dir) {\n\t\tvec3 sh[15];\n\t\treadSHData(sh);\n\t\tvec3 result = vec3(0.0);\n\t\tfloat x = dir.x;\n\t\tfloat y = dir.y;\n\t\tfloat z = dir.z;\n\t\tresult += SH_C1 * (-sh[0] * y + sh[1] * z - sh[2] * x);\n\t\tfloat xx = x * x;\n\t\tfloat yy = y * y;\n\t\tfloat zz = z * z;\n\t\tfloat xy = x * y;\n\t\tfloat yz = y * z;\n\t\tfloat xz = x * z;\n\t\tresult +=\n\t\t\tsh[3] * (SH_C2_0 * xy) * +\n\t\t\tsh[4] * (SH_C2_1 * yz) +\n\t\t\tsh[5] * (SH_C2_2 * (2.0 * zz - xx - yy)) +\n\t\t\tsh[6] * (SH_C2_3 * xz) +\n\t\t\tsh[7] * (SH_C2_4 * (xx - yy));\n\t\tresult +=\n\t\t\tsh[8] * (SH_C3_0 * y * (3.0 * xx - yy)) +\n\t\t\tsh[9] * (SH_C3_1 * xy * z) +\n\t\t\tsh[10] * (SH_C3_2 * y * (4.0 * zz - xx - yy)) +\n\t\t\tsh[11] * (SH_C3_3 * z * (2.0 * zz - 3.0 * xx - 3.0 * yy)) +\n\t\t\tsh[12] * (SH_C3_4 * x * (4.0 * zz - xx - yy)) +\n\t\t\tsh[13] * (SH_C3_5 * z * (xx - yy)) +\n\t\t\tsh[14] * (SH_C3_6 * x * (xx - 3.0 * yy));\n\t\treturn result;\n\t}\n#else\n\tvec3 evalSH(in vec3 dir) {\n\t\treturn vec3(0.0);\n\t}\n#endif\n"+a.vertex,s=o+p.decodePS+(a.dither===r?"":p.bayerPS+p.opacityDitherPS)+x.tonemapCode(a.toneMapping)+x.gammaCode(a.gamma)+"\n\t#ifndef DITHER_NONE\n\t\tvarying float id;\n\t#endif\n\t#ifdef PICK_PASS\n\t\tuniform vec4 uColor;\n\t#endif\n\tvec4 evalSplat(vec2 texCoord, vec4 color) {\n\t\tmediump float A = dot(texCoord, texCoord);\n\t\tif (A > 1.0) {\n\t\t\tdiscard;\n\t\t}\n\t\tmediump float B = exp(-A * 4.0) * color.a;\n\t\tif (B < 1.0 / 255.0) {\n\t\t\tdiscard;\n\t\t}\n\t\t#ifdef PICK_PASS\n\t\t\tif (B < 0.3) {\n\t\t\t\tdiscard;\n\t\t\t}\n\t\t\treturn uColor;\n\t\t#endif\n\t\t#ifndef DITHER_NONE\n\t\t\topacityDither(B, id * 0.013);\n\t\t#endif\n\t\t#ifdef TONEMAP_ENABLED\n\t\t\treturn vec4(gammaCorrectOutput(toneMap(decodeGamma(color.rgb))), B);\n\t\t#else\n\t\t\treturn vec4(color.rgb, B);\n\t\t#endif\n\t}\n"+a.fragment;return m.createDefinition(t,{name:"SplatShader",attributes:{vertex_position:n,vertex_id_attrib:e},vertexCode:i,fragmentCode:s})}},y=(n={})=>{var e;const f=null!=(e=n.dither)?e:r,m=f!==r,p=new u;return p.name="compressedSplatMaterial",p.cull=t,p.blendType=m?c:o,p.depthWrite=m,p.getShaderVariant=function(t,e,r,c,o,u,m,p){var x,h;const y={pass:o,gamma:o===i?e.gammaCorrection?s:d:e.gammaCorrection,toneMapping:o===i?v:e.toneMapping,vertex:null!=(x=n.vertex)?x:"\n\tvarying mediump vec2 texCoord;\n\tvarying mediump vec4 color;\n\tuniform vec3 view_position;\n\tmediump vec4 discardVec = vec4(0.0, 0.0, 2.0, 1.0);\n\tvoid main(void)\n\t{\n\t\tif (!calcSplatUV()) {\n\t\t\tgl_Position = discardVec;\n\t\t\treturn;\n\t\t}\n\t\treadData();\n\t\tvec3 center = getCenter();\n\t\tmat4 model_view = matrix_view * matrix_model;\n\t\tvec4 splat_cam = model_view * vec4(center, 1.0);\n\t\tvec4 splat_proj = matrix_projection * splat_cam;\n\t\tif (splat_proj.z < -splat_proj.w) {\n\t\t\tgl_Position = discardVec;\n\t\t\treturn;\n\t\t}\n\t\tvec3 covA, covB;\n\t\tgetCovariance(covA, covB);\n\t\tvec4 v1v2 = calcV1V2(splat_cam.xyz, covA, covB, transpose(mat3(model_view)));\n\t\tcolor = getColor();\n\t\tfloat scale = min(1.0, sqrt(-log(1.0 / 255.0 / color.a)) / 2.0);\n\t\tv1v2 *= scale;\n\t\tif (dot(v1v2.xy, v1v2.xy) < 4.0 && dot(v1v2.zw, v1v2.zw) < 4.0) {\n\t\t\tgl_Position = discardVec;\n\t\t\treturn;\n\t\t}\n\t\tgl_Position = splat_proj + vec4((vertex_position.x * v1v2.xy + vertex_position.y * v1v2.zw) / viewport * splat_proj.w, 0, 0);\n\t\ttexCoord = vertex_position.xy * scale / 2.0;\n\t\t#ifdef USE_SH\n\t\t\tvec4 worldCenter = matrix_model * vec4(center, 1.0);\n\t\t\tvec3 viewDir = normalize((worldCenter.xyz / worldCenter.w - view_position) * mat3(matrix_model));\n\t\t\tcolor.xyz = max(color.xyz + evalSH(viewDir), 0.0);\n\t\t#endif\n\t\t#ifndef DITHER_NONE\n\t\t\tid = float(splatId);\n\t\t#endif\n\t}\n",fragment:null!=(h=n.fragment)?h:"\n\tvarying mediump vec2 texCoord;\n\tvarying mediump vec4 color;\n\tvoid main(void)\n\t{\n\t\tgl_FragColor = evalSplat(texCoord, color);\n\t}\n",dither:f,defines:n.defines},g=new a(m,p),k=l(t);return k.register("splat-compressed",_),k.getProgram("splat-compressed",y,g)},p.update(),p};export{y as createGSplatCompressedMaterial};