Reputation: 4565
I have a script in BabylonJS that creates a background layer with the video feed. The problem is that I can not lock it to a certain aspect ratio.
const background = new BABYLON.Layer("back", null, scene);
BABYLON.VideoTexture.CreateFromWebCam(scene, function (videoTexture) {
background.texture = videoTexture;
background.texture.level = 0;
background.texture.wAng = Math.PI;
}, { maxWidth: window.innerWidth, maxHeight: window.innerHeight});
Code above properly sets the background to the webcam feed, but scales it with the window.
Calling background.texture.scale(20);
has no effect since .canRescale
for that texture returns false
.
Trying to rescale the layer didn't help either.
This is the link to the playground.
I feel like the solution must be simple but I haven't managed to google it. Thanks.
Upvotes: 1
Views: 853
Reputation: 11
I was looking for a simmilar way to set an image background, and ended up using a plane with a fixed aspect ratio and an orthographic camera
(code is using react-babylonjs, but the same properties should work in normal babylonjs)
first make an orthographic camera
<targetCamera
name="camera1"
position={new Vector3(0, 0, -2)}
rotation={new Vector3(toRadians(0), toRadians(0), 0)}
mode={Camera.ORTHOGRAPHIC_CAMERA}
ref={scenePlaneCameraRef}
/>
then make a plane with size = 1
// the real size will be stretched with scale,
// this works because 1 unit on the orthographic camera is the size of 1 pixel
<plane
ref={planeRef}
name="backdropPlane"
size={1}
billboardMode={AbstractMesh.BILLBOARDMODE_ALL}
/>
These are some functions to get the size the plane should be
export function defaultSize(engine) {
return { width: 0, height: 0 };
}
export function getViewSize(engine) {
if (!engine) return defaultSize();
return {
width: engine.getRenderWidth(),
height: engine.getRenderHeight(),
};
}
// this gets the wanted plane size so it fills the screen but keeps the aspect ratio
export function getPlaneSize(engine) {
const viewSize = getViewSize(engine);
const viewAspectRatio = viewSize.width / viewSize.height;
const planeAspectRatio = 16 / 9;
const viewIsThinner = viewAspectRatio < planeAspectRatio;
if (viewIsThinner) {
return {
width: viewSize.height * planeAspectRatio,
height: viewSize.height,
};
} else {
return {
width: viewSize.width,
height: viewSize.width * (1.0 / planeAspectRatio),
};
}
}
export default function fitScenePlaneToScreen(planeMesh, engine) {
const planeSize = getPlaneSize(engine);
planeMesh.scaling.y = planeSize.height;
planeMesh.scaling.x = planeSize.width;
}
Then resize the plane whenever the screen size changes
fitScenePlaneToScreen(scenePlane, engine);
engine.onResizeObservable.add(() => {
fitScenePlaneToScreen(scenePlane, engine);
});
Then set the materials texture for that plane as the video texture
And one way to use it as a background is to have two scenes on top of eachother, where the behind scene uses the orthographic camera
Upvotes: 1