Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
0418e9f
Canvas Context angle/fontsize fixes
CedricGuillemet Feb 6, 2025
bbdcce3
Text/shape/state test script
CedricGuillemet Feb 6, 2025
e0f88f3
readme update
CedricGuillemet Feb 6, 2025
57ec8d7
Merge branch 'master' into CanvasTest
ryantrem Feb 7, 2025
a9737fc
Canvas transform implementation (#1460)
mattbirman Feb 17, 2025
dadeca3
plumb lineCap, lineJoin, miterLimit to nanovg
Pheo Feb 18, 2025
975e0dd
Add textMetrics implementation (#1461)
mattbirman Feb 18, 2025
7bbca53
Add letterSpacing polyfill and implementation (#1462)
mattbirman Feb 18, 2025
ef0b545
Merge branch 'master' of https://github.com/BabylonJS/BabylonNative i…
CedricGuillemet Feb 19, 2025
b733ab3
Canvas test update (#1463)
CedricGuillemet Feb 19, 2025
bbe83fa
map strings to lineCaps
Pheo Feb 19, 2025
c9be817
Merge branch 'CanvasLineImplementation' of https://github.com/Pheo/Ba…
CedricGuillemet Feb 20, 2025
1538543
Add lineCap, lineJoin, miterLimit (#1464)
Pheo Feb 20, 2025
aab744e
Gradient color stop (#1467)
CedricGuillemet Feb 25, 2025
d599479
Merge branch 'CanvasTest' of https://github.com/BabylonJS/BabylonNati…
CedricGuillemet Feb 25, 2025
4d03c02
fix merge conflicts
CedricGuillemet Feb 25, 2025
e404270
JSI build
CedricGuillemet Feb 25, 2025
73693f9
Path2D Implementation (#1469)
Pheo Feb 28, 2025
146210b
Merge branch 'master' of https://github.com/BabylonJS/BabylonNative i…
CedricGuillemet Mar 4, 2025
3235ff7
Canvas Transforms: getTransform setTransform, addPath (Path2D) (#1473)
Pheo Mar 4, 2025
4c60d74
Merge branch 'master' of https://github.com/BabylonJS/BabylonNative i…
CedricGuillemet Mar 5, 2025
a4a0082
Merge branch 'CanvasTest' of https://github.com/BabylonJS/BabylonNati…
CedricGuillemet Mar 5, 2025
7304a31
nanovg Compositor
CedricGuillemet Mar 7, 2025
05ddd44
method visibility
CedricGuillemet Mar 7, 2025
09aa481
a bit of clean up
CedricGuillemet Mar 7, 2025
de71606
Implement round rect (#1471)
hwarmington Mar 11, 2025
2aacc5e
remove 2nd encoder
CedricGuillemet Mar 11, 2025
7cb49ba
Copy nanovg into Canvas sources (#1480)
matanui159 Mar 13, 2025
e154eb9
fixed MSVC build
CedricGuillemet Mar 13, 2025
c914be2
Use bgfx more recent glslang/spirv for NativeEngine (#1478)
CedricGuillemet Mar 13, 2025
2c1dcfe
fix mac build
CedricGuillemet Mar 13, 2025
f7a563d
Canvas gradient text (#1475)
CedricGuillemet Mar 14, 2025
58d3b2f
Add strokeText support to canvas via SDFs (#1482)
matanui159 Mar 18, 2025
6a4f4f3
Merge branch 'CanvasTest' of https://github.com/BabylonJS/BabylonNati…
CedricGuillemet Mar 18, 2025
704650a
Merge branch 'master' of https://github.com/BabylonJS/BabylonNative i…
CedricGuillemet Mar 18, 2025
d1223cb
filter stack PoC
CedricGuillemet Mar 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 166 additions & 1 deletion Apps/Playground/Scripts/experience.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const imageTracking = false;
const readPixels = false;

function CreateBoxAsync(scene) {
BABYLON.Mesh.CreateBox("box1", 0.2, scene);
//BABYLON.Mesh.CreateBox("box1", 0.2, scene);
return Promise.resolve();
}

Expand Down Expand Up @@ -64,6 +64,171 @@ CreateBoxAsync(scene).then(function () {
//BABYLON.SceneLoader.AppendAsync("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/ClearCoatTest/glTF/ClearCoatTest.gltf").then(function () {
BABYLON.Tools.Log("Loaded");

var textureGround;

BABYLON.Tools.LoadFile("https://raw.githubusercontent.com/CedricGuillemet/dump/master/droidsans.ttf", (data) => {
_native.Canvas.loadTTFAsync("droidsans", data).then(function () {
var ground = BABYLON.MeshBuilder.CreateGround("ground1", { width: 0.5, height: 0.5, subdivisions: 2 }, scene);
ground.rotation.x = -Math.PI * 0.5;
ground.rotation.y = Math.PI;

var texSize = 512;
var dynamicTexture = new BABYLON.DynamicTexture("dynamic texture", texSize, scene);

var materialGround = new BABYLON.StandardMaterial("Mat", scene);
materialGround.diffuseTexture = dynamicTexture;
ground.material = materialGround;
materialGround.backFaceCulling = false;
dynamicTexture.clear();
var context = dynamicTexture.getContext();

// Text with gradient
const gradientText = context.createLinearGradient(0, 0, 256, 0);
gradientText.addColorStop(0, "magenta");
gradientText.addColorStop(0.5, "blue");
gradientText.addColorStop(1.0, "red");

// gradient
let gradient = context.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, "green");
gradient.addColorStop(0.7, "white");
gradient.addColorStop(1, "pink");

var t = 0;
scene.onBeforeRenderObservable.add(() => {
// animated shape
context.save();
context.fillStyle = "DarkRed";
context.fillRect(0, 0, texSize, texSize);
const left = 0;
const top = texSize - (texSize * 0.25);
const width = 0.25 * texSize;
const height = 0.25 * texSize;
const offsetU = ((Math.sin(t) * 0.5) + 0.5) * (texSize - (texSize * 0.25));
const offsetV = ((Math.sin(t) * 0.5) + 0.5) * (-texSize + (texSize * 0.25));
const rectangleU = width * 0.5 + left;
const rectangleV = height * 0.5 + top;
context.translate(rectangleU + offsetU, rectangleV + offsetV);
context.rotate(t);
context.fillStyle = "DarkOrange";
context.transform(1, t, 0.8, 1, 0, 0);
context.fillRect(-width * 0.5, -height * 0.5, width, height);
context.restore();
// curve
context.beginPath();
context.moveTo(75 * 2, 25 * 2);
context.quadraticCurveTo(25 * 2, 25 * 2, 25 * 2, 62.5 * 2);
context.quadraticCurveTo(25 * 2, 100 * 2, 50 * 2, 100 * 2);
context.quadraticCurveTo(50 * 2, 120 * 2, 30 * 2, 125 * 2);
context.quadraticCurveTo(60 * 2, 120 * 2, 65 * 2, 100 * 2);
context.quadraticCurveTo(125 * 2, 100 * 2, 125 * 2, 62.5 * 2);
context.quadraticCurveTo(125 * 2, 25 * 2, 75 * 2, 25 * 2);
context.fillStyle = "blue";
context.fill();

// text
var scale = Math.sin(t) * 0.5 + 0.54;
context.save();
context.translate(Math.cos(t) * 100, 246);
context.font = `bold ${scale * 200}px monospace`;
context.strokeStyle = "Green";
context.lineWidth = scale * 16;
context.strokeText("BabylonNative", 0, 0);
context.fillStyle = "White";
context.fillText("BabylonNative", 0, 0);
context.restore();

// Draw guides
context.strokeStyle = "#09f";
context.beginPath();
context.moveTo(10, 10);
context.lineTo(140, 10);
context.moveTo(10, 140);
context.lineTo(140, 140);
context.stroke();

// Draw lines
context.strokeStyle = "black";
["butt", "round", "square"].forEach((lineCap, i) => {
context.lineWidth = 15;
context.lineCap = lineCap;
context.beginPath();
context.moveTo(25 + i * 50, 10);
context.lineTo(25 + i * 50, 140);
context.stroke();
});

// line join
context.lineWidth = 10;
var offset = 200;
["round", "bevel", "miter"].forEach((join, i) => {
context.lineJoin = join;
context.beginPath();
context.moveTo(-5 + offset, 15 + i * 40);
context.lineTo(35 + offset, 55 + i * 40);
context.lineTo(75 + offset, 15 + i * 40);
context.lineTo(115 + offset, 55 + i * 40);
context.lineTo(155 + offset, 15 + i * 40);
context.stroke();
});

// rect with gradient
context.fillStyle = gradient;
context.fillRect(10, 310, 400, 60);

// Fill with gradient
context.fillStyle = gradientText;
context.font = "bold 60px monospace";
context.fillText("Gradient Text!", 10, 420);


context.lineWidth = 5;
// Rounded rectangle with zero radius (specified as a number)
context.strokeStyle = "red";
context.beginPath();
context.roundRect(10, 220, 150, 100, 0);
context.stroke();

// Rounded rectangle with 40px radius (single element list)
context.strokeStyle = "blue";
context.beginPath();
context.roundRect(10, 220, 150, 100, [40]);
context.stroke();

// Rounded rectangle with 2 different radii
context.strokeStyle = "orange";
context.beginPath();
context.roundRect(10, 350, 150, 100, [10, 40]);
context.stroke();

// Rounded rectangle with four different radii
context.strokeStyle = "green";
context.beginPath();
context.roundRect(200, 220, 200, 100, [0, 30, 50, 60]);
context.stroke();

// Same rectangle drawn backwards
context.strokeStyle = "magenta";
context.beginPath();
context.roundRect(400, 350, -200, 100, [0, 30, 50, 60]);
context.stroke();

// Draw clipped round rect
// TODO: this is currently broken, clipping area does not have round corners
context.beginPath();
context.roundRect(40, 450, 100, 50, 10);
context.clip();
context.fillStyle = "blue";
context.fillRect(0, 0, 1000, 1000);

// tick update
dynamicTexture.update();
t += 0.01;
});

});
}, undefined, undefined, true);

// This creates and positions a free camera (non-mesh)
scene.createDefaultCamera(true, true, true);
scene.activeCamera.alpha += Math.PI;
Expand Down
49 changes: 34 additions & 15 deletions Plugins/NativeEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,40 @@ target_include_directories(NativeEngine
PUBLIC "Include"
PRIVATE "${BIMG_DIR}/3rdparty")

target_link_libraries(NativeEngine
PUBLIC napi
PRIVATE JsRuntime
PRIVATE GraphicsDevice
PRIVATE arcana
PRIVATE bgfx
PRIVATE bimg
PRIVATE bimg_encode
PRIVATE bimg_decode
PRIVATE bx
PRIVATE glslang
PRIVATE glslang-default-resource-limits
PRIVATE SPIRV
PRIVATE GraphicsDeviceContext)
warnings_as_errors(NativeEngine)

if(BGFX_BUILD_TOOLS)
target_link_libraries(NativeEngine
PUBLIC napi
PRIVATE JsRuntime
PRIVATE GraphicsDevice
PRIVATE arcana
PRIVATE bgfx
PRIVATE bimg
PRIVATE bimg_encode
PRIVATE bimg_decode
PRIVATE bx
PRIVATE glslang
PRIVATE spirv-opt
PRIVATE GraphicsDeviceContext)
target_compile_definitions(NativeEngine PRIVATE BGFX_BUILD_TOOLS)
else()
target_link_libraries(NativeEngine
PUBLIC napi
PRIVATE JsRuntime
PRIVATE GraphicsDevice
PRIVATE arcana
PRIVATE bgfx
PRIVATE bimg
PRIVATE bimg_encode
PRIVATE bimg_decode
PRIVATE bx
PRIVATE glslang
PRIVATE glslang-default-resource-limits
PRIVATE SPIRV
PRIVATE GraphicsDeviceContext)

warnings_as_errors(NativeEngine)
endif()

if(TARGET spirv-cross-hlsl)
target_link_libraries(NativeEngine
Expand Down
1 change: 1 addition & 0 deletions Plugins/NativeEngine/Source/ShaderCompilerMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <bgfx/bgfx.h>
#include <glslang/Public/ShaderLang.h>
#include <glslang/Public/ResourceLimits.h>
#include <glslang/MachineIndependent/localintermediate.h>
#include <SPIRV/GlslangToSpv.h>
#include <spirv_parser.hpp>
#include <spirv_msl.hpp>
Expand Down
25 changes: 20 additions & 5 deletions Plugins/NativeEngine/Source/ShaderCompilerTraversers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,11 @@ namespace Babylon::ShaderCompilerTraversers
// Create the symbol for the actual struct. The name of this symbol, "anon@0",
// mirrors the kinds of strings glslang generates automatically for these sorts
// of objects.
TIntermSymbol* structSymbol = intermediate->addSymbol(TIntermSymbol{ids.Next(), "anon@0", structType});

#ifdef BGFX_BUILD_TOOLS
TIntermSymbol* structSymbol = intermediate->addSymbol(TIntermSymbol{ids.Next(), "anon@0", intermediate->getStage(), structType});
#else
TIntermSymbol* structSymbol = intermediate->addSymbol(TIntermSymbol{ ids.Next(), "anon@0", structType });
#endif
// Every affected symbol in the AST (except linker objects) must be replaced
// with a new operation to retrieve its value from the struct. This operation
// consists of a binary operation indexing into the struct at a specified
Expand Down Expand Up @@ -521,7 +524,11 @@ namespace Babylon::ShaderCompilerTraversers

TType newType{publicType};
newType.setBasicType(symbol->getType().getBasicType());
auto* newSymbol = intermediate->addSymbol(TIntermSymbol{ids.Next(), newName, newType});
#ifdef BGFX_BUILD_TOOLS
auto* newSymbol = intermediate->addSymbol(TIntermSymbol{ids.Next(), newName, intermediate->getStage(), newType});
#else
auto* newSymbol = intermediate->addSymbol(TIntermSymbol{ ids.Next(), newName, newType });
#endif
originalNameToReplacement[name] = newSymbol;
replacementToOriginalName[newName] = name;
}
Expand Down Expand Up @@ -794,7 +801,11 @@ namespace Babylon::ShaderCompilerTraversers

TType newType{publicType};
std::string newName = name + "Texture";
newTexture = intermediate->addSymbol(TIntermSymbol{ids.Next(), newName.c_str(), newType});
#ifdef BGFX_BUILD_TOOLS
newTexture = intermediate->addSymbol(TIntermSymbol{ids.Next(), newName.c_str(), intermediate->getStage(), newType});
#else
newTexture = intermediate->addSymbol(TIntermSymbol{ ids.Next(), newName.c_str(), newType });
#endif
}

// Create the new sampler symbol.
Expand All @@ -809,7 +820,11 @@ namespace Babylon::ShaderCompilerTraversers
publicType.sampler.sampler = true;

TType newType{publicType};
newSampler = intermediate->addSymbol(TIntermSymbol{ids.Next(), name.c_str(), newType});
#ifdef BGFX_BUILD_TOOLS
newSampler = intermediate->addSymbol(TIntermSymbol{ids.Next(), name.c_str(), intermediate->getStage(), newType});
#else
newSampler = intermediate->addSymbol(TIntermSymbol{ ids.Next(), name.c_str(), newType });
#endif
}

nameToNewTextureAndSampler[name] = std::pair<TIntermSymbol*, TIntermSymbol*>{newTexture, newSampler};
Expand Down
Loading
Loading