我在BabylonJS中有一个脚本,可以用视频源创建一个背景层。问题是我无法将其锁定为一定的纵横比。
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});
上面的代码正确地将背景设置为网络摄像头馈送,但随着窗口的缩放而缩放。
调用 background.texture.scale(20);
无效,因为 .canRescale
的纹理返回 false
.
尝试重新缩放图层也没有用。
这就是 联系 到操场上。
我觉得解决方法一定很简单,但我还没能谷歌到它。谢谢。
我一直在寻找一种类似的方法来设置图像背景,并最终使用了一个固定长宽比的平面和一个正交相机。
(代码使用的是react-babylonjs,但同样的属性在普通的babylonjs中也可以使用)
先做正射影机
<targetCamera
name="camera1"
position={new Vector3(0, 0, -2)}
rotation={new Vector3(toRadians(0), toRadians(0), 0)}
mode={Camera.ORTHOGRAPHIC_CAMERA}
ref={scenePlaneCameraRef}
/>
然后做一个尺寸=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}
/>
这些都是一些函数,以获得平面应该是的大小。
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;
}
然后每当屏幕大小改变时,就调整飞机的大小。
fitScenePlaneToScreen(scenePlane, engine);
engine.onResizeObservable.add(() => {
fitScenePlaneToScreen(scenePlane, engine);
});
然后将该平面的材质纹理设置为视频纹理。
而作为背景的一种方法是两个场景叠加在一起,其中后面的场景使用正射摄像机