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 1/7] 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 aaa0b47bc..dd491d587 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 52a47cb42..aca8e20fd 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 3eb661afa..10eb897c7 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 dd3b9f2c1..9d2182595 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 f933dc91c..e1fa8a7fb 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 63ccadf8f..7d97427ba 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 2/7] 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 dd491d587..fd493c22c 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 f3d0633c1..e0b50b52e 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 7d97427ba..593dc7a06 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 3/7] 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 593dc7a06..c6e55f742 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 4/7] 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 e1fa8a7fb..761da4b66 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 5/7] 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 fd493c22c..4b8018c8e 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 6/7] 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 e0b50b52e..a079cfdc8 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 c6e55f742..8d30d9694 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 7/7] 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 8d30d9694..c044289e6 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]; }