diff --git a/Apps/Playground/ReferenceImages/gsplat-update-data.png b/Apps/Playground/ReferenceImages/gsplat-update-data.png new file mode 100644 index 0000000000..263ffdc6c1 Binary files /dev/null and b/Apps/Playground/ReferenceImages/gsplat-update-data.png differ diff --git a/Apps/Playground/Scripts/config.json b/Apps/Playground/Scripts/config.json index 75e0847859..07ed3a84bf 100644 --- a/Apps/Playground/Scripts/config.json +++ b/Apps/Playground/Scripts/config.json @@ -1,6 +1,12 @@ { "root": "https://cdn.babylonjs.com", "tests": [ + { + "title": "Gaussian Splatting Update Data", + "playgroundId": "#Q0LBM8#2", + "renderCount": 15, + "referenceImage": "gsplat-update-data.png" + }, { "title": "Native Canvas", "playgroundId": "#TKVFSA#7", diff --git a/Apps/package-lock.json b/Apps/package-lock.json index 56d20472b3..9572d55137 100644 --- a/Apps/package-lock.json +++ b/Apps/package-lock.json @@ -11,12 +11,12 @@ "UnitTests/JavaScript" ], "dependencies": { - "babylonjs": "^8.37.1", - "babylonjs-gltf2interface": "^8.37.1", - "babylonjs-gui": "^8.37.1", - "babylonjs-loaders": "^8.37.1", - "babylonjs-materials": "^8.37.1", - "babylonjs-serializers": "^8.37.1", + "babylonjs": "^8.45.5", + "babylonjs-gltf2interface": "^8.45.5", + "babylonjs-gui": "^8.45.5", + "babylonjs-loaders": "^8.45.5", + "babylonjs-materials": "^8.45.5", + "babylonjs-serializers": "^8.45.5", "jsc-android": "^241213.1.0", "v8-android": "^7.8.2" } @@ -86,7 +86,6 @@ "version": "7.28.3", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1699,8 +1698,7 @@ "node_modules/@babylonjs/core": { "version": "8.37.0", "dev": true, - "license": "Apache-2.0", - "peer": true + "license": "Apache-2.0" }, "node_modules/@babylonjs/materials": { "version": "8.37.0", @@ -2076,7 +2074,6 @@ "version": "8.15.0", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2099,7 +2096,6 @@ "version": "8.17.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -2248,54 +2244,54 @@ } }, "node_modules/babylonjs": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-8.38.0.tgz", - "integrity": "sha512-LqeN89nhsBiTVaGff8NEkNk0XnjObIxDAmJ3ZX3iwOV8dWRu6/hJAz0mobGnXNH2wN0ID9o0xeDhy22Ugi7MFA==", + "version": "8.45.5", + "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-8.45.5.tgz", + "integrity": "sha512-rN/Kma5m0GreyeRsXRs1mKGMTva/25mb1McWaMnpciKLZI86NSFMU1+DehPizA3JL8a0WiQCOp6Slea5+MsBIQ==", "hasInstallScript": true, "license": "Apache-2.0" }, "node_modules/babylonjs-gltf2interface": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-8.38.0.tgz", - "integrity": "sha512-eA98MXtjgqqwoK/9yFVOcklViiZr/GQphsvkz1FTqZ5il/V0n7swCjpMyWsHswxnlMC/A8Ec6k8dzB++FXcmNg==", + "version": "8.45.5", + "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-8.45.5.tgz", + "integrity": "sha512-o1OMBVdeKCK7b+L1VUW1w1+KIi1DTP7Po+SAJ3vwPqRG6xD2eTL+w5IaFHVue3dVjnlU8Z+9y3BP3AadmK0H9w==", "license": "Apache-2.0" }, "node_modules/babylonjs-gui": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/babylonjs-gui/-/babylonjs-gui-8.38.0.tgz", - "integrity": "sha512-7TzQsRKgVz+JbU6ALH9VO4mtLrBLx+rtcvGEpxmhjaeJ3w2JeqqJr/ZvHqYlZoupAsUlTVYsl5mn29VxT/Xt0w==", + "version": "8.45.5", + "resolved": "https://registry.npmjs.org/babylonjs-gui/-/babylonjs-gui-8.45.5.tgz", + "integrity": "sha512-uwl5bzIj4SLi5QHXcqu6jtPAMCBvWCEaN9GR/MJ1Lfxk3FzsCN5Ma93LyQETr4vzH9XjmobsdthofHd45/JHVw==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.38.0" + "babylonjs": "^8.45.5" } }, "node_modules/babylonjs-loaders": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/babylonjs-loaders/-/babylonjs-loaders-8.38.0.tgz", - "integrity": "sha512-bx1kbLwFT00F8diIADb5bQ0RPOEZwUmat+DKrz1d5ePi5aI1+uTvl6MTU8uuAoEJyPuiAee/DKEo1SVWcGIIPA==", + "version": "8.45.5", + "resolved": "https://registry.npmjs.org/babylonjs-loaders/-/babylonjs-loaders-8.45.5.tgz", + "integrity": "sha512-MbPvMG7XG9XPpo1Nl1hPpIUcnw4+8KwcK7YxT4HOatwYaAY81fuwek6vDGeucxq/TORD6X+YjjwbqSjAORfABg==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.38.0", - "babylonjs-gltf2interface": "^8.38.0" + "babylonjs": "^8.45.5", + "babylonjs-gltf2interface": "^8.45.5" } }, "node_modules/babylonjs-materials": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/babylonjs-materials/-/babylonjs-materials-8.38.0.tgz", - "integrity": "sha512-pPSpbg5743ATKSv8xjFYsXoN3uIJqcH95AaJNltS0/CO59L26+RegG7OW4di71xezy/uV+i6P86CmQOju2ql8w==", + "version": "8.45.5", + "resolved": "https://registry.npmjs.org/babylonjs-materials/-/babylonjs-materials-8.45.5.tgz", + "integrity": "sha512-rO1OYfM3fyxcQ93EcDvNaa0C/+WLQGOWVc4xgliI4FVGcjy9levNmBLbsSqo3/fATGBwpdMYC+GMj7Qd7PYrQA==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.38.0" + "babylonjs": "^8.45.5" } }, "node_modules/babylonjs-serializers": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/babylonjs-serializers/-/babylonjs-serializers-8.38.0.tgz", - "integrity": "sha512-Ly5G84ESOIqcI+dwEzPVFG5G1DiZu3tsqiWlkzTP3N3hVLjOZfqr5IPQHNu47JL1RqiAZh1IkUu/PF/NQnTALA==", + "version": "8.45.5", + "resolved": "https://registry.npmjs.org/babylonjs-serializers/-/babylonjs-serializers-8.45.5.tgz", + "integrity": "sha512-RQ0hMgtvZ5G8Xk9Za/m8bl8yatVDfUi5NJKyWFDAQRA2x7iyH7On3ptnUcL5cm9/hGO1BL/zAE3TgHG+Kv5zag==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.38.0", - "babylonjs-gltf2interface": "^8.38.0" + "babylonjs": "^8.45.5", + "babylonjs-gltf2interface": "^8.45.5" } }, "node_modules/balanced-match": { @@ -2376,7 +2372,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -4500,7 +4495,6 @@ "version": "5.101.3", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -4548,7 +4542,6 @@ "version": "6.0.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.6.1", "@webpack-cli/configtest": "^3.0.1", diff --git a/Apps/package.json b/Apps/package.json index 1049876b45..8846d072a7 100644 --- a/Apps/package.json +++ b/Apps/package.json @@ -9,12 +9,12 @@ "getNightly": "node scripts/getNightly.js" }, "dependencies": { - "babylonjs": "^8.37.1", - "babylonjs-gltf2interface": "^8.37.1", - "babylonjs-gui": "^8.37.1", - "babylonjs-loaders": "^8.37.1", - "babylonjs-materials": "^8.37.1", - "babylonjs-serializers": "^8.37.1", + "babylonjs": "^8.45.5", + "babylonjs-gltf2interface": "^8.45.5", + "babylonjs-gui": "^8.45.5", + "babylonjs-loaders": "^8.45.5", + "babylonjs-materials": "^8.45.5", + "babylonjs-serializers": "^8.45.5", "jsc-android": "^241213.1.0", "v8-android": "^7.8.2" } diff --git a/Plugins/NativeEngine/Source/NativeEngine.cpp b/Plugins/NativeEngine/Source/NativeEngine.cpp index ad7f6609f1..ffa0c60498 100644 --- a/Plugins/NativeEngine/Source/NativeEngine.cpp +++ b/Plugins/NativeEngine/Source/NativeEngine.cpp @@ -258,6 +258,7 @@ namespace Babylon image->m_format == bimg::TextureFormat::RGBA8 || image->m_format == bimg::TextureFormat::RGBA16 || image->m_format == bimg::TextureFormat::RGBA16F || + image->m_format == bimg::TextureFormat::RG16F || image->m_format == bimg::TextureFormat::RGBA32F); assert(image->m_depth == 1); @@ -287,7 +288,7 @@ namespace Babylon image = bimg::imageConvert(&allocator, bimg::TextureFormat::RGBA8, *image, false); bimg::imageFree(oldImage); } - else if (image->m_format == bimg::TextureFormat::RGBA16F || image->m_format == bimg::TextureFormat::RGBA16 || image->m_format == bimg::TextureFormat::R16) + else if (image->m_format == bimg::TextureFormat::RG16F || image->m_format == bimg::TextureFormat::RGBA16F || image->m_format == bimg::TextureFormat::RGBA16 || image->m_format == bimg::TextureFormat::R16) { bimg::ImageContainer* oldImage{image}; image = bimg::imageConvert(&allocator, bimg::TextureFormat::RGBA32F, *image, false); @@ -1009,7 +1010,7 @@ namespace Babylon if (!shaderInfo) { - bgfxShaderInfo = m_shaderCompiler.Compile(ProcessShaderCoordinates(vertexSource), ProcessSamplerFlip(fragmentSource)); + bgfxShaderInfo = m_shaderCompiler.Compile(ProcessSamplerFlip(ProcessShaderCoordinates(vertexSource)), ProcessSamplerFlip(fragmentSource)); if (ShaderCacheImpl::GetImpl()) { ShaderCacheImpl::GetImpl()->AddShader(vertexSource, fragmentSource, bgfxShaderInfo); diff --git a/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp b/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp index f3d0633c13..a079cfdc84 100644 --- a/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp +++ b/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp @@ -719,6 +719,10 @@ namespace Babylon::ShaderCompilerTraversers IF_NAME_RETURN_ATTRIB("world1", bgfx::Attrib::TexCoord5, "i_data1") IF_NAME_RETURN_ATTRIB("world2", bgfx::Attrib::TexCoord6, "i_data2") IF_NAME_RETURN_ATTRIB("world3", bgfx::Attrib::TexCoord7, "i_data3") + IF_NAME_RETURN_ATTRIB("splatIndex0", bgfx::Attrib::TexCoord4, "i_data0") + IF_NAME_RETURN_ATTRIB("splatIndex1", bgfx::Attrib::TexCoord5, "i_data1") + IF_NAME_RETURN_ATTRIB("splatIndex2", bgfx::Attrib::TexCoord6, "i_data2") + IF_NAME_RETURN_ATTRIB("splatIndex3", bgfx::Attrib::TexCoord7, "i_data3") #undef IF_NAME_RETURN_ATTRIB const unsigned int attributeLocation = FIRST_GENERIC_ATTRIBUTE_LOCATION + m_genericAttributesRunningCount++; if (attributeLocation >= static_cast(bgfx::Attrib::Count)) diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 63ccadf8f3..e2c10b22cc 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -273,6 +273,57 @@ namespace matrixTransform(finalMatrix, data[index], data[index + 1], data[index + 2]); } } + + static int sortSplatQSort(const void* p1, const void* p2) { + const float* a = (const float*)p1; + const float* b = (const float*)p2; + if (a[1] < b[1]) { + return -1; + } + if (a[1] > b[1]) { + return 1; + } + return 0; + } + + + // This function is not threadsafe because of static + void sortSplats(const Napi::CallbackInfo& info) + { + const auto modelView{ info[0].As() }; + const auto m{ modelView.Get("_m").As() }; + + auto positions{ info[1].As() }; + + auto indices{ info[2].As() }; + + auto rightHand{ info[3].As() }; + + + float depthFactor = -1.f; + if (rightHand) { + depthFactor = 1.f; + } + + const auto splatCount = indices.ElementLength(); + float vp[3] = { m[2], m[6], m[10] }; + static std::vector depthMix; + + depthMix.resize(splatCount * 2); + + for (size_t i = 0; i < splatCount; i++) + { + depthMix[i * 2 + 0] = float(i); + depthMix[i * 2 + 1] = 10000.f + (vp[0] * positions[4 * i + 0] + vp[1] * positions[4 * i + 1] + vp[2] * positions[4 * i + 2]) * depthFactor; + } + + qsort(depthMix.data(), splatCount, 2 * sizeof(float), sortSplatQSort); + + for (size_t i = 0; i < splatCount; i++) + { + indices[i] = depthMix[i * 2 + 0]; + } + } } namespace Babylon::Plugins::NativeOptimizations @@ -287,5 +338,6 @@ namespace Babylon::Plugins::NativeOptimizations nativeObject.Set("_FlipFaces", Napi::Function::New(env, FlipFaces, "_FlipFaces")); nativeObject.Set("extractMinAndMaxIndexed", Napi::Function::New(env, ExtractMinAndMaxIndexed, "extractMinAndMaxIndexed")); nativeObject.Set("extractMinAndMax", Napi::Function::New(env, ExtractMinAndMax, "extractMinAndMax")); + nativeObject.Set("sortSplats", Napi::Function::New(env, sortSplats, "sortSplats")); } }