From 2f35e5c76d8a17e6981a658fe26a5e09ed48458a Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Tue, 23 Sep 2025 18:08:00 +0200 Subject: [PATCH 01/14] NativeGS experiment --- Apps/Playground/Scripts/experience.js | 64 ++++++++++++++++++- Apps/package-lock.json | 48 +++++++------- Apps/package.json | 10 +-- Dependencies/CMakeLists.txt | 4 +- Plugins/NativeEngine/Source/NativeEngine.cpp | 3 +- .../Source/NativeOptimizations.cpp | 7 ++ 6 files changed, 103 insertions(+), 33 deletions(-) diff --git a/Apps/Playground/Scripts/experience.js b/Apps/Playground/Scripts/experience.js index aaa0b47bc0..dd491d5876 100644 --- a/Apps/Playground/Scripts/experience.js +++ b/Apps/Playground/Scripts/experience.js @@ -21,7 +21,69 @@ const imageTracking = false; const readPixels = false; function CreateBoxAsync(scene) { - BABYLON.Mesh.CreateBox("box1", 0.2, scene); + //BABYLON.Mesh.CreateBox("box1", 0.2, scene); + // Our built-in 'sphere' shape. + var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 1, segments: 32 }, scene); + + // Move the sphere upward 1/2 its height + sphere.position.y = 0.5; + sphere.position.z = -1; + + // Our built-in 'ground' shape. + var ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene); + + // Gaussian Splatting + /*BABYLON.SceneLoader.ImportMeshAsync(null, "https://raw.githubusercontent.com/CedricGuillemet/dump/master/", "Halo_Believe.splat", scene).then((result) => { + console.log("loaded"); + result.meshes[0].position.y = 1.7; + }); + */ + + var gs = new BABYLON.GaussianSplattingMesh("GS", undefined, scene, true); + + var generateGS = function (time) { + // size of a single splat, int bytes + const rowLength = 3 * 4 + 3 * 4 + 4 + 4; + + // chunck size of splats + const splatCount = 10000; + + const uBuffer = new Uint8Array(splatCount * rowLength); + const fBuffer = new Float32Array(uBuffer.buffer); + + for (let j = 0; j < 100; j++) { + for (let ji = 0; ji < 100; ji++) { + const i = ji + j * 100; + // position + x = j * 0.1 - 5; + y = -Math.sin(time + ji * 0.04 + j * 0.02) * 1 - 1; + + fBuffer[8 * i + 0] = Math.cos(time) * x + Math.sin(time) * y; + fBuffer[8 * i + 1] = Math.sin(time) * x - Math.cos(time) * y; + fBuffer[8 * i + 2] = ji * 0.1 - 5; + + // size + fBuffer[8 * i + 3 + 0] = 0.1; + fBuffer[8 * i + 3 + 1] = 0.1; + fBuffer[8 * i + 3 + 2] = 0.1; + + // orientation + uBuffer[32 * i + 28 + 1] = 128; + uBuffer[32 * i + 28 + 2] = 128; + uBuffer[32 * i + 28 + 3] = 128; + uBuffer[32 * i + 28 + 0] = 255; + + // color + uBuffer[32 * i + 24 + 0] = Math.cos((ji + time * 3) * 0.2) * 127 + 128; + uBuffer[32 * i + 24 + 1] = Math.cos((j + time * 4) * 0.3) * 127 + 128; + uBuffer[32 * i + 24 + 2] = Math.sin((j + ji + time * 2) * 0.3) * 127 + 128; + uBuffer[32 * i + 24 + 3] = 255; + } + } + gs.updateData(uBuffer); + }; + generateGS(0); + return Promise.resolve(); } diff --git a/Apps/package-lock.json b/Apps/package-lock.json index 52a47cb425..aca8e20fd8 100644 --- a/Apps/package-lock.json +++ b/Apps/package-lock.json @@ -11,11 +11,11 @@ "UnitTests" ], "dependencies": { - "babylonjs": "^8.17.0", - "babylonjs-gltf2interface": "^8.17.0", - "babylonjs-gui": "^8.17.0", - "babylonjs-loaders": "^8.17.0", - "babylonjs-materials": "^8.17.0", + "babylonjs": "^8.28.2", + "babylonjs-gltf2interface": "^8.28.2", + "babylonjs-gui": "^8.28.2", + "babylonjs-loaders": "^8.28.2", + "babylonjs-materials": "^8.28.2", "jsc-android": "^241213.1.0", "v8-android": "^7.8.2" } @@ -2600,44 +2600,44 @@ } }, "node_modules/babylonjs": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-8.17.0.tgz", - "integrity": "sha512-XLMAk+R/9wZMhwdRZFGO6z8rrJvvvhsiztHA0NLvi9hcdxbsdTwA4Ic5Rscqy+9O11hWSBjjuEuGsSrVXdJZDg==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-8.28.2.tgz", + "integrity": "sha512-mid1cYg2VGXKj4neNy+78MHwSV8tMCHbvSEaIXQuEj1JxKmEb+UQ6/XwqiSGMrw1IoFxRZ693kelfe1tuSdKJg==", "hasInstallScript": true, "license": "Apache-2.0" }, "node_modules/babylonjs-gltf2interface": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-8.17.0.tgz", - "integrity": "sha512-EdfH3PTIY5U1Y+gUj/mSw/fW+fUvTEZWryOBaXF4nwZzaFOfhnG/+kJ1gNEE25lNbOHOYlYw0k0S6eMaw1UJBA==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-8.28.2.tgz", + "integrity": "sha512-TGusApjAPNkPhyyU/05FNoiEc9l85Kd4ZGHO/5hsRkLLYVXvmsqAEa9yGIVLhYM3Yezf/b1DFwMPvY1D/NEiVA==", "license": "Apache-2.0" }, "node_modules/babylonjs-gui": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-gui/-/babylonjs-gui-8.17.0.tgz", - "integrity": "sha512-8pYk22jPkeOJGKZpgdox9CK+FmdZO5w9MbVMaCCYeodtAS/9QhETYsdd4LuWG7hHhFITaiIDn9FnlyaclbMTrg==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-gui/-/babylonjs-gui-8.28.2.tgz", + "integrity": "sha512-sFURHbGEfPiRPGQM4jKsPbG4ZxWj9cejNbaxbjNMCB8izc33rzXB67+yHxDdSfjkiEeB1VM30OdhdEW6/JAq+g==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.17.0" + "babylonjs": "^8.28.2" } }, "node_modules/babylonjs-loaders": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-loaders/-/babylonjs-loaders-8.17.0.tgz", - "integrity": "sha512-mkEw4aXIkPI4Ef/Wjvdv6L2UVvQ2bINYpdflYqzo77biWCm0Oq5H/QODYgnHv/EUe0RGPgGbO+T8HyLtUsb8lg==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-loaders/-/babylonjs-loaders-8.28.2.tgz", + "integrity": "sha512-WIbR3gaHhxSvRzs7Yuz578YlhPXqlB36tEEqIo0E+s5FqgzFy+o2TBN0O8nWnGuyk7s4wAZpA8CBQ58KsGfw5Q==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.17.0", - "babylonjs-gltf2interface": "^8.17.0" + "babylonjs": "^8.28.2", + "babylonjs-gltf2interface": "^8.28.2" } }, "node_modules/babylonjs-materials": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-materials/-/babylonjs-materials-8.17.0.tgz", - "integrity": "sha512-iS6gUSUlhNUcKlmaVvXq0PyrGmYR+LyVr3uSpIVUKm9svZ/fAsZEEQ+riRRKFYGdsUnhfqDVPsHv2YSfoLNQgA==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-materials/-/babylonjs-materials-8.28.2.tgz", + "integrity": "sha512-5/pURv40ugE7tIeiuW/6C4Eo6VXOcHZJhtjrwdLDlpfMFpAU7d2JTNyaa9NqnHkRVRqXtad3/cu6FoVw6+AsZw==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.17.0" + "babylonjs": "^8.28.2" } }, "node_modules/balanced-match": { diff --git a/Apps/package.json b/Apps/package.json index 3eb661afa9..10eb897c7a 100644 --- a/Apps/package.json +++ b/Apps/package.json @@ -9,11 +9,11 @@ "getNightly": "node scripts/getNightly.js" }, "dependencies": { - "babylonjs": "^8.17.0", - "babylonjs-gltf2interface": "^8.17.0", - "babylonjs-gui": "^8.17.0", - "babylonjs-loaders": "^8.17.0", - "babylonjs-materials": "^8.17.0", + "babylonjs": "^8.28.2", + "babylonjs-gltf2interface": "^8.28.2", + "babylonjs-gui": "^8.28.2", + "babylonjs-loaders": "^8.28.2", + "babylonjs-materials": "^8.28.2", "jsc-android": "^241213.1.0", "v8-android": "^7.8.2" } diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt index dd3b9f2c15..9d21825951 100644 --- a/Dependencies/CMakeLists.txt +++ b/Dependencies/CMakeLists.txt @@ -89,7 +89,7 @@ set(ENABLE_HLSL OFF) set(ENABLE_OPT OFF) set(ENABLE_CTEST OFF) set(SKIP_GLSLANG_INSTALL ON) -set(ENABLE_GLSLANG_WEBMIN ON) +set(ENABLE_GLSLANG_WEBMIN OFF) set(ENABLE_GLSLANG_WEBMIN_DEVEL OFF) if(NOT TARGET glslang) @@ -149,7 +149,7 @@ set(SPIRV_CROSS_ENABLE_REFLECT OFF) set(SPIRV_CROSS_ENABLE_C_API OFF) set(SPIRV_CROSS_ENABLE_UTIL OFF) set(SPIRV_CROSS_SKIP_INSTALL ON) -set(SPIRV_CROSS_ENABLE_WEBMIN ON) +set(SPIRV_CROSS_ENABLE_WEBMIN OFF) if(NOT GRAPHICS_API STREQUAL "OpenGL") set(SPIRV_CROSS_ENABLE_GLSL OFF) endif() diff --git a/Plugins/NativeEngine/Source/NativeEngine.cpp b/Plugins/NativeEngine/Source/NativeEngine.cpp index f933dc91c0..e1fa8a7fbd 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); diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 63ccadf8f3..7d97427ba4 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -287,5 +287,12 @@ 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")); + + env.Global().Set("sortGS", Napi::Function::New( + env, [](const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + }, + "sortGS")); } } From f498a329e6fb762cee9bb02dcbb3ad0f5009f808 Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:30:58 +0200 Subject: [PATCH 02/14] GS is rendered --- Apps/Playground/Scripts/experience.js | 5 ++-- .../Source/ShaderCompilerTraversers.cpp | 1 + .../Source/NativeOptimizations.cpp | 27 ++++++++++++++----- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Apps/Playground/Scripts/experience.js b/Apps/Playground/Scripts/experience.js index dd491d5876..fd493c22c8 100644 --- a/Apps/Playground/Scripts/experience.js +++ b/Apps/Playground/Scripts/experience.js @@ -30,7 +30,7 @@ function CreateBoxAsync(scene) { sphere.position.z = -1; // Our built-in 'ground' shape. - var ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene); + //var ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene); // Gaussian Splatting /*BABYLON.SceneLoader.ImportMeshAsync(null, "https://raw.githubusercontent.com/CedricGuillemet/dump/master/", "Halo_Believe.splat", scene).then((result) => { @@ -82,7 +82,8 @@ function CreateBoxAsync(scene) { } gs.updateData(uBuffer); }; - generateGS(0); + generateGS(0); + return Promise.resolve(); } diff --git a/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp b/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp index f3d0633c13..e0b50b52e7 100644 --- a/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp +++ b/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp @@ -719,6 +719,7 @@ 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("splatIndex", 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 7d97427ba4..593dc7a06b 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -273,6 +273,24 @@ namespace matrixTransform(finalMatrix, data[index], data[index + 1], data[index + 2]); } } + + + void SortGS(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() }; + + for (int i = 0; i < indices.ElementLength()/4; i++) + { + indices[i * 4] = float(i); + } + } } namespace Babylon::Plugins::NativeOptimizations @@ -287,12 +305,7 @@ 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")); - - env.Global().Set("sortGS", Napi::Function::New( - env, [](const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - - }, - "sortGS")); + //nativeObject.Set("sortGS", Napi::Function::New(env, SortGS, "sortGS")); + env.Global().Set("sortGS", Napi::Function::New(env, SortGS, "sortGS")); } } From 90855507696a0702f82c8c18071011886e61d20b Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:48:30 +0200 Subject: [PATCH 03/14] qsort --- .../Source/NativeOptimizations.cpp | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 593dc7a06b..c6e55f742a 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -274,6 +274,12 @@ namespace } } + static int sortSplatQSort(const void* p1, const void* p2) { + const float* a = (float*)p1; + const float* b = (float*)p2; + return (a[1] < b[1]) ? -1 : 1; + } + void SortGS(const Napi::CallbackInfo& info) { @@ -286,10 +292,22 @@ namespace auto rightHand{ info[3].As() }; - for (int i = 0; i < indices.ElementLength()/4; i++) + + float depthFactor = -1.f; + if (rightHand) { + depthFactor = 1.f; + } + + const auto vertexCount = indices.ElementLength() / 4; + float vp[3] = { m[2], m[6], m[10] }; + + for (int i = 0; i < vertexCount; i++) { - indices[i * 4] = float(i); + indices[i * 4 + 0] = float(i); + indices[i * 4 + 1] = 10000.f + (vp[0] * positions[4 * i + 0] + vp[1] * positions[4 * i + 1] + vp[2] * positions[4 * i + 2]) * depthFactor; } + + qsort(indices.Data(), vertexCount, 4 * sizeof(float), sortSplatQSort); } } From 5c6b3402b94f218649cbdfc64c47d70ec53b3896 Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:18:41 +0100 Subject: [PATCH 04/14] flip texture sampling in VS --- Plugins/NativeEngine/Source/NativeEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/NativeEngine/Source/NativeEngine.cpp b/Plugins/NativeEngine/Source/NativeEngine.cpp index e1fa8a7fbd..761da4b669 100644 --- a/Plugins/NativeEngine/Source/NativeEngine.cpp +++ b/Plugins/NativeEngine/Source/NativeEngine.cpp @@ -1011,7 +1011,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); From b2115a5639a216092c490fd8078d314ab8d1be0e Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:00:38 +0100 Subject: [PATCH 05/14] Procedural GS --- Apps/Playground/Scripts/experience.js | 32 ++++++--------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/Apps/Playground/Scripts/experience.js b/Apps/Playground/Scripts/experience.js index fd493c22c8..4b8018c8ee 100644 --- a/Apps/Playground/Scripts/experience.js +++ b/Apps/Playground/Scripts/experience.js @@ -20,25 +20,7 @@ const imageCapture = false; const imageTracking = false; const readPixels = false; -function CreateBoxAsync(scene) { - //BABYLON.Mesh.CreateBox("box1", 0.2, scene); - // Our built-in 'sphere' shape. - var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 1, segments: 32 }, scene); - - // Move the sphere upward 1/2 its height - sphere.position.y = 0.5; - sphere.position.z = -1; - - // Our built-in 'ground' shape. - //var ground = BABYLON.MeshBuilder.CreateGround("ground", { width: 6, height: 6 }, scene); - - // Gaussian Splatting - /*BABYLON.SceneLoader.ImportMeshAsync(null, "https://raw.githubusercontent.com/CedricGuillemet/dump/master/", "Halo_Believe.splat", scene).then((result) => { - console.log("loaded"); - result.meshes[0].position.y = 1.7; - }); - */ - +function CreateGSAsync(scene) { var gs = new BABYLON.GaussianSplattingMesh("GS", undefined, scene, true); var generateGS = function (time) { @@ -46,14 +28,15 @@ function CreateBoxAsync(scene) { const rowLength = 3 * 4 + 3 * 4 + 4 + 4; // chunck size of splats - const splatCount = 10000; + const b = 100; + const splatCount = b * b; const uBuffer = new Uint8Array(splatCount * rowLength); const fBuffer = new Float32Array(uBuffer.buffer); - for (let j = 0; j < 100; j++) { - for (let ji = 0; ji < 100; ji++) { - const i = ji + j * 100; + for (let j = 0; j < b; j++) { + for (let ji = 0; ji < b; ji++) { + const i = ji + j * b; // position x = j * 0.1 - 5; y = -Math.sin(time + ji * 0.04 + j * 0.02) * 1 - 1; @@ -84,7 +67,6 @@ function CreateBoxAsync(scene) { }; generateGS(0); - return Promise.resolve(); } @@ -107,7 +89,7 @@ function CreateSpheresAsync(scene) { const engine = new BABYLON.NativeEngine(); const scene = new BABYLON.Scene(engine); -CreateBoxAsync(scene).then(function () { +CreateGSAsync(scene).then(function () { //CreateSpheresAsync(scene).then(function () { //BABYLON.SceneLoader.AppendAsync("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Box/glTF/Box.gltf").then(function () { //BABYLON.SceneLoader.AppendAsync("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoxTextured/glTF/BoxTextured.gltf").then(function () { From aa918657b30a975c9dcf2a62d65bd1ea02c8735a Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:43:59 +0100 Subject: [PATCH 06/14] update for recent BJS update --- .../Source/ShaderCompilerTraversers.cpp | 5 ++++- .../Source/NativeOptimizations.cpp | 22 +++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp b/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp index e0b50b52e7..a079cfdc84 100644 --- a/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp +++ b/Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp @@ -719,7 +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("splatIndex", 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 c6e55f742a..8d30d96945 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -281,6 +281,7 @@ namespace } + // This function is not threadsafe because of static void SortGS(const Napi::CallbackInfo& info) { const auto modelView{ info[0].As() }; @@ -298,16 +299,24 @@ namespace depthFactor = 1.f; } - const auto vertexCount = indices.ElementLength() / 4; + const auto splatCount = indices.ElementLength(); float vp[3] = { m[2], m[6], m[10] }; + static std::vector depthMix; - for (int i = 0; i < vertexCount; i++) + depthMix.resize(splatCount * 2); + + for (int i = 0; i < splatCount; i++) { - indices[i * 4 + 0] = float(i); - indices[i * 4 + 1] = 10000.f + (vp[0] * positions[4 * i + 0] + vp[1] * positions[4 * i + 1] + vp[2] * positions[4 * i + 2]) * depthFactor; + 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(indices.Data(), vertexCount, 4 * sizeof(float), sortSplatQSort); + qsort(depthMix.data(), splatCount, 2 * sizeof(float), sortSplatQSort); + + for (int i = 0; i < splatCount; i++) + { + indices[i] = depthMix[i * 2 + 0]; + } } } @@ -323,7 +332,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("sortGS", Napi::Function::New(env, SortGS, "sortGS")); - env.Global().Set("sortGS", Napi::Function::New(env, SortGS, "sortGS")); + nativeObject.Set("sortGS", Napi::Function::New(env, SortGS, "sortGS")); } } From 449eddfc0d7b550057d637593a34483a93dc4f3a Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:03:41 +0100 Subject: [PATCH 07/14] signed/unsigned --- Plugins/NativeOptimizations/Source/NativeOptimizations.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 8d30d96945..c044289e60 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -305,7 +305,7 @@ namespace depthMix.resize(splatCount * 2); - for (int i = 0; i < splatCount; i++) + 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; @@ -313,7 +313,7 @@ namespace qsort(depthMix.data(), splatCount, 2 * sizeof(float), sortSplatQSort); - for (int i = 0; i < splatCount; i++) + for (size_t i = 0; i < splatCount; i++) { indices[i] = depthMix[i * 2 + 0]; } From 470efabe89bed5b42bae250da3fb864e97d8e699 Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:40:19 +0100 Subject: [PATCH 08/14] update --- Apps/Playground/Scripts/experience.js | 52 +------------------ Dependencies/CMakeLists.txt | 4 +- .../Source/NativeOptimizations.cpp | 2 +- 3 files changed, 4 insertions(+), 54 deletions(-) diff --git a/Apps/Playground/Scripts/experience.js b/Apps/Playground/Scripts/experience.js index bf693bbc33..6e3f761312 100644 --- a/Apps/Playground/Scripts/experience.js +++ b/Apps/Playground/Scripts/experience.js @@ -27,56 +27,6 @@ if (logPerf) { setTimeout(() => BABYLON.Tools.EndPerformanceCounter("test counter"), 500); } -function CreateGSAsync(scene) { - var gs = new BABYLON.GaussianSplattingMesh("GS", undefined, scene, true); - - var generateGS = function (time) { - // size of a single splat, int bytes - const rowLength = 3 * 4 + 3 * 4 + 4 + 4; - - // chunck size of splats - const b = 100; - const splatCount = b * b; - - const uBuffer = new Uint8Array(splatCount * rowLength); - const fBuffer = new Float32Array(uBuffer.buffer); - - for (let j = 0; j < b; j++) { - for (let ji = 0; ji < b; ji++) { - const i = ji + j * b; - // position - x = j * 0.1 - 5; - y = -Math.sin(time + ji * 0.04 + j * 0.02) * 1 - 1; - - fBuffer[8 * i + 0] = Math.cos(time) * x + Math.sin(time) * y; - fBuffer[8 * i + 1] = Math.sin(time) * x - Math.cos(time) * y; - fBuffer[8 * i + 2] = ji * 0.1 - 5; - - // size - fBuffer[8 * i + 3 + 0] = 0.1; - fBuffer[8 * i + 3 + 1] = 0.1; - fBuffer[8 * i + 3 + 2] = 0.1; - - // orientation - uBuffer[32 * i + 28 + 1] = 128; - uBuffer[32 * i + 28 + 2] = 128; - uBuffer[32 * i + 28 + 3] = 128; - uBuffer[32 * i + 28 + 0] = 255; - - // color - uBuffer[32 * i + 24 + 0] = Math.cos((ji + time * 3) * 0.2) * 127 + 128; - uBuffer[32 * i + 24 + 1] = Math.cos((j + time * 4) * 0.3) * 127 + 128; - uBuffer[32 * i + 24 + 2] = Math.sin((j + ji + time * 2) * 0.3) * 127 + 128; - uBuffer[32 * i + 24 + 3] = 255; - } - } - gs.updateData(uBuffer); - }; - generateGS(0); - - return Promise.resolve(); -} - function CreateSpheresAsync(scene) { const size = 12; for (let i = 0; i < size; i++) { @@ -96,7 +46,7 @@ function CreateSpheresAsync(scene) { const engine = new BABYLON.NativeEngine(); const scene = new BABYLON.Scene(engine); -CreateGSAsync(scene).then(function () { +CreateBoxAsync(scene).then(function () { //CreateSpheresAsync(scene).then(function () { //BABYLON.AppendSceneAsync("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Box/glTF/Box.gltf").then(function () { //BABYLON.AppendSceneAsync("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/BoxTextured/glTF/BoxTextured.gltf").then(function () { diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt index 7751f79d39..8f8e5091ec 100644 --- a/Dependencies/CMakeLists.txt +++ b/Dependencies/CMakeLists.txt @@ -98,7 +98,7 @@ set(ENABLE_HLSL OFF) set(ENABLE_OPT OFF) set(ENABLE_CTEST OFF) set(SKIP_GLSLANG_INSTALL ON) -set(ENABLE_GLSLANG_WEBMIN OFF) +set(ENABLE_GLSLANG_WEBMIN ON) set(ENABLE_GLSLANG_WEBMIN_DEVEL OFF) if(NOT TARGET glslang) @@ -158,7 +158,7 @@ set(SPIRV_CROSS_ENABLE_REFLECT OFF) set(SPIRV_CROSS_ENABLE_C_API OFF) set(SPIRV_CROSS_ENABLE_UTIL OFF) set(SPIRV_CROSS_SKIP_INSTALL ON) -set(SPIRV_CROSS_ENABLE_WEBMIN OFF) +set(SPIRV_CROSS_ENABLE_WEBMIN ON) if(NOT GRAPHICS_API STREQUAL "OpenGL") set(SPIRV_CROSS_ENABLE_GLSL OFF) endif() diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index c044289e60..99f3280b7f 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -332,6 +332,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("sortGS", Napi::Function::New(env, SortGS, "sortGS")); + nativeObject.Set("_SortGS", Napi::Function::New(env, SortGS, "_SortGS")); } } From e7a5ce7af98985df97688a16b906d4b78494af24 Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:44:57 +0100 Subject: [PATCH 09/14] function naming --- Apps/Playground/Scripts/experience.js | 5 +++++ Plugins/NativeOptimizations/Source/NativeOptimizations.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Apps/Playground/Scripts/experience.js b/Apps/Playground/Scripts/experience.js index 6e3f761312..514191de7b 100644 --- a/Apps/Playground/Scripts/experience.js +++ b/Apps/Playground/Scripts/experience.js @@ -27,6 +27,11 @@ if (logPerf) { setTimeout(() => BABYLON.Tools.EndPerformanceCounter("test counter"), 500); } +function CreateBoxAsync(scene) { + BABYLON.Mesh.CreateBox("box1", 0.2, scene); + return Promise.resolve(); +} + function CreateSpheresAsync(scene) { const size = 12; for (let i = 0; i < size; i++) { diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 99f3280b7f..08c24455b0 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -282,7 +282,7 @@ namespace // This function is not threadsafe because of static - void SortGS(const Napi::CallbackInfo& info) + void _SortGS(const Napi::CallbackInfo& info) { const auto modelView{ info[0].As() }; const auto m{ modelView.Get("_m").As() }; From 60a44bcacce76c398e92200cb48c09afd801323a Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Mon, 12 Jan 2026 17:06:28 +0100 Subject: [PATCH 10/14] typo --- Plugins/NativeOptimizations/Source/NativeOptimizations.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 08c24455b0..94f28f3569 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -332,6 +332,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("_SortGS", Napi::Function::New(env, SortGS, "_SortGS")); + nativeObject.Set("_SortGS", Napi::Function::New(env, _SortGS, "_SortGS")); } } From 553462d08fbb8a0745a63d7b8727c41e6f6592cb Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Tue, 13 Jan 2026 11:29:22 +0100 Subject: [PATCH 11/14] GS updatedata visualization test --- .../ReferenceImages/gsplat-update-data.png | Bin 0 -> 26946 bytes Apps/Playground/Scripts/config.json | 6 ++++++ .../Source/NativeOptimizations.cpp | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 Apps/Playground/ReferenceImages/gsplat-update-data.png diff --git a/Apps/Playground/ReferenceImages/gsplat-update-data.png b/Apps/Playground/ReferenceImages/gsplat-update-data.png new file mode 100644 index 0000000000000000000000000000000000000000..66de053260a212686c33b4ef24b6ab9959ef3b51 GIT binary patch literal 26946 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 Z@JN3+wu@6sF5;fxX{qU{)`A_P{s*=+LL~qI literal 0 HcmV?d00001 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/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 94f28f3569..92f1e4fc22 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -282,7 +282,7 @@ namespace // This function is not threadsafe because of static - void _SortGS(const Napi::CallbackInfo& info) + void sortSplats(const Napi::CallbackInfo& info) { const auto modelView{ info[0].As() }; const auto m{ modelView.Get("_m").As() }; @@ -332,6 +332,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("_SortGS", Napi::Function::New(env, _SortGS, "_SortGS")); + nativeObject.Set("sortSplats", Napi::Function::New(env, sortSplats, "sortSplats")); } } From c8e4946b3599f4a7422ec30e50312c3a9564646c Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Tue, 13 Jan 2026 11:38:12 +0100 Subject: [PATCH 12/14] Update Plugins/NativeOptimizations/Source/NativeOptimizations.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Source/NativeOptimizations.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp index 92f1e4fc22..e2c10b22cc 100644 --- a/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp +++ b/Plugins/NativeOptimizations/Source/NativeOptimizations.cpp @@ -275,9 +275,15 @@ namespace } static int sortSplatQSort(const void* p1, const void* p2) { - const float* a = (float*)p1; - const float* b = (float*)p2; - return (a[1] < b[1]) ? -1 : 1; + 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; } From 3e1b35b639895f4311431cd10f4bae601d2e0c18 Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:46:26 +0100 Subject: [PATCH 13/14] up deps --- Apps/package-lock.json | 69 +++++++++++++++++++----------------------- Apps/package.json | 12 ++++---- 2 files changed, 37 insertions(+), 44 deletions(-) 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" } From adac40db7115ac6a5b4b323e156f01efab64ffb0 Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:01:04 +0100 Subject: [PATCH 14/14] rgba reference --- .../ReferenceImages/gsplat-update-data.png | Bin 26946 -> 29492 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Apps/Playground/ReferenceImages/gsplat-update-data.png b/Apps/Playground/ReferenceImages/gsplat-update-data.png index 66de053260a212686c33b4ef24b6ab9959ef3b51..263ffdc6c1421b37452e823bd74081bb0fd88339 100644 GIT binary patch literal 29492 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

qPomg~X5Sc?9 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 literal 26946 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 Z@JN3+wu@6sF5;fxX{qU{)`A_P{s*=+LL~qI