Babylon.js

3 篇文章 0 订阅
1 篇文章 0 订阅

Babylon.js

最近想搞一搞webgl的3d小游戏,为以后的微信小游戏技术铺路。

  • Three.js: The aim of the project is to create an easy to use, lightweight, 3D library with a default WebGL renderer.
  • PlayCanvas: Fast and lightweight WebGL game engine
  • Babylon.js: Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

Three.js非常棒,但偏重render,看官网的列子就可以知道; 用作开发游戏的话,需要额外的插件补充。Babylon.js render和game并重,由法国的一个微软团队发布和维护,看起来稍微比PlayCanvas更有活力点。所以就选择了Babylon.js. ? 1

Babylon 101

About

A step-by-step turtiol;

基本架构

  • scene
  • light
  • camera
  • meshes

Shapes

  • Box
  • Sphere
  • Plane
  • Ground
let box = BABYLON.MeshBuilder.CreateBox("box", {height: 5, width: 2, depth: 0.5}, scene);
let sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 2, diameterX: 3}, scene);
let myPlane = BABYLON.MeshBuilder.CreatePlane("myPlane", {width: 5, height: 2}, scene);
let myGround = BABYLON.MeshBuilder.CreateGround("myGround", {width: 6, height: 4, subdivisions: 4}, scene);

Material

reactions to light

  • diffuse 漫反射
  • sepcular 镜面反射
  • emissive 发光
  • ambient 环境光

color

material可以设置四种属性的color

let myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);

myMaterial.diffuseColor = new BABYLON.Color3(1, 0, 1);
myMaterial.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87);
myMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1);
myMaterial.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53);

mesh.material = myMaterial;

Texture

var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);

myMaterial.diffuseTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.specularTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.emissiveTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.ambientTexture = new BABYLON.Texture("PATH TO IMAGE", scene);

mesh.material = myMaterial;

note

如果texture是带有透明通道的图片

myMaterial.diffuseTexture.hasAlpha = true;

Back Face Culling

背面剔除

WireFrame

设置显示Material的WireFrame

materialSphere1.wireframe = true;

Camera

两种最常用的?

  1. Universal Camera: for First Person Movement
  2. Arc Rotate Camera: 轨道相机

绑定到画布上

camera.attachControl(canvas, true);
// true: enable default actions  默认false

触摸事件

PEP or hand.js

Universal Camera

默认相机FPS-like Control

let camera = new BABYLON.UniversalCamera("UniversalCamera", vec3(0, 0, -10), scene);
// 将相机对准一个点
camera.setTarget(vec3_zero);
camera.attachControl(canvas, true);

Arc Camera

arc camera

运行类似卫星,可以围绕目标旋转的相机(始终面向目标)

// Parameters: alpha, beta, radius, target position, scene
let camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);

FlowCamera

Virtual Joysticks Camera

虚拟操纵杆相机

Lights

Light默认会穿过Meshes,除非Meshes 的shadow generator激活
默认最多4个Lights

Lights 类型

**The Point Light **

let light = new BABYLON.PointLight("pointLight", vec3(1, 10, 1), scene);

The Direction Light

let light = new BABYLON.DirectionLight("directionLight", vec3(0, -1, 0), scene);

The Spot Light
锥形光源

let light = new BABYLON.SpotLight("spotLight", vec3(0, 30, -10), vec3(0, -1, 0), π / 3, 2, scene);

The Hemispheric Light

模拟周围的环境光

let light = new BABYLON.HemisphericLight("HemiLight", vec3(0, 1, 0), scene);

On, Off or Dimmer

light.setEnabled(false); // or true

light.intensity = 0.5; // 默认值为 1

light.range = 100;

Animation

两种设置Animation的方式

  1. 设置一系列的关键帧
  2. 在运行时修改动画代码,为了实现更加复杂的动画

Basic Animation

function createScene() {
  let box1 = BABYLON.Mesh.CreateBox("Box1", 10.0, scene);
  box1.position.x = -20;
  
  let animationBox = new BABYLON.Animation("myAnimation", "scaling,x", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATION_CYCLE);
}
  • 参数1: 动画的名字
  • 参数2: 动画中变化的属性
  • 参数3:帧率
  • 参数4: 关键帧中,属性的值的类型
  • 参数5: 动画播放完时的行为

设置关键帧

let keys = [];

// T 为参数2, 且此处为FLOAT
const keyFrame<T> = (frame: number, value: T) => { frame: frame, value: value }
keys.push(keyFrame(0, 1));
keys.push(keyFrame(20, 0.2));
keys.push(keyFrame(100, 1));

animationBox.setKeys(keys);
box1.animations = [animationBox];

scene.beginAnimation(box1, 0, 100, true);

beginAnimation的参数

NameTypeDescriptionOptional
targetanyThe targetNo
fromnumberThe fps starting frameNo
tonumberThe fps ending frameNo
loopbooleanIf true, the animation will loop (dependent upon BABYLON.Animation.ANIMATIONLOOPMODE)Yes
speedRationumberdefault : 1. The speed ratio of this animationYes
onAnimationEnd() => voidThe function triggered on the end of the animation, even if the animation is manually stopped (also dependent upon ANIMATIONLOOPMODE)Yes
animatableAnimatableAn optional specific animationYes
stopCurrentbooleanShould we stop the current existing animations if any? Default is yesYes

With Promise

let anim = scene.beginAnimation(box1, 0, 100, false);
console.log('before');
await anim.waitAsync();
console.log('after');

Animation Blending

enabelBlending = true

使用示例:用户控制的正在运动的角色。例如从行走动画变化到跑步动画。

Animation weights

同时运行多个动画,每个动画有其权重。

Easing funtions

缓动函数

Cameras, Mesh Collisions and Gravity

三步走

1. 添加重力

2. 定义一个椭球

这个椭球代表player的大小,是碰撞体积的大小。

f i n a l P o s i t i o n = p o s i t i o n − v e c 3 ( 0 , e l l i p s o i d . y , 0 ) + e l l i p s o i d O f f s e t finalPosition = position - vec3(0, ellipsoid.y, 0) + ellipsoidOffset finalPosition=positionvec3(0,ellipsoid.y,0)+ellipsoidOffset

3. 开启碰撞

// add gravity
scene.gravity = vec3(0, -9.81, 0);
camera.applyGravity = true;

// define a ellipsoid
camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);

// enable collision 
scene.collisionEnables = true;
camera.checkCollisions = true;

ground.checkCollisions = true;
box.checkCollisions = true;

Intersect Collisions - mesh

碰撞检测

1. intersectsMesh

let result = mesh1.intersectsMesh(mesh2, false);

第二个参数 默认为false, 当设置为true是,boundingbox会更贴近mesh, 但性能开销更大。

2. intersectPoint

let result = mesh.intersectsPoint(vec3(10, -5, 0));

Picking Collisions

window.addEventListener("click", () => {
  let pickResult = scene.pick(scene.pointerX, scene.pointerY);
  if (pickResult.hit) {
    impact.position.x = pickResult.pickedPoint.x;
    impact.position.y = pickResult.pickedPoint.y;
  }
})

type PickResult = {
	hit: boolean,
	distance: number,
	pickedMesh: BABYLON.Mesh,
  pickedPoint: BABYLON.Vector3,
  faceId: number, //  position of the picked face's indices in the indices array
  submeshId: number, // id of the picked submesh inside the picked mesh
  // ...
}

Raycasts

Sprites

Sprites always face the camera.

Sprite Manager

为了优化GPU资源,使用SpriteManager

let spriteManagerPlayer = new BABYLON.SpriteManager("playManager", "assets/player.png", 2, {width: 64, height: 64}, scene);

let player = new BABYLON.Sprite("player", spriteManagerPlayer);

Sprite Animation

player.playAnimation(0, 43, true, 100);
//                 start end loop? durationEveryFrame

Particles

Particles System

let particleSystem = new BABYLON.ParticleSystem("particles", 2000, scene);
// 2000 : 系统容量
particleSystem.start();
particleSystem.stop();

//delay
particleSystem.startDelay = 3000;
// or 
particleSystem.start(3000);

particleSystem.targetStopDuration = 5; 
particleSystem.disposeOnStop = true; // 一次性粒子系统

note

调用stop后将不会产生新的粒子,但是已经存在仍然在。如要完全重置, 调用reset

Pre-warming

在真实渲染前,执行100次,且循环比渲染时快5倍

system.preWarmCycles = 100;
system.preWarmStepOffset = 5;
system.start();

Particle Texture

particleSystem.particleTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
particleSystem.textureMask = new BABYLON.Color4(0.1, 0.8, 0.8, 1.0);

Particle Emitter

particleSystem.emitter = vec3(-1, 2, 3);
// or
let source = BABYLON.Mesh.CreateBox("source", 1.0, scene);
particleSystem.emitter = source;  // position of source is used;

Location And Spread

particleSystem.minEmitBox = vec3(-2, -3, 4); 
particleSystem.maxEmitBox = vec3(4, 2, 3);

Lifetime

// Life time of each particle (random between...)
particleSystem.minLifeTime = 0.3;
particleSystem.maxLifeTime = 1.5

addLifeTimeGradient

Size

(minSize, maxSize)
(minScaleX, maxScaleX)
addSizeGradient

Color

particleSystem.addColorGradient(0, new BABYLON.Color4(1, 1, 1, 0));

Rate

particleSystem.emitRate = 100;

Direction

Gravity

Rotation

Speed

Drag

over time

Shape Emitters

The shapes:

  • Point
  • Box
  • Sphere
  • Hemisphere
  • Cylinder
  • Cone

Noise Texture

GPU Particles

WebGL2.0

Shadows

Basic

let shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
// 1024: the size of shadow
// light: 指定光源
shadowGenerator.getShadowMap().renderList.push(mesh);
// addShadowCaster
// removeShadowCaster
ground.receiveShadows = true;

Soft Shadows

更进一步,你可以激活阴影过滤,移除hard edges, 来创建更美观的阴影。

  • usePoissonSampling
  • useExponentialShadowMap
  • useBlurExponentialShadowMap
  • useCloseExponentialShadowMap
  • useBlurCloseExponentialShadowMap
  • usePercentageCloserFiltering (WebGL 2.0)

Light

每个ShadowGenerator只能被一个light使用。只要Point Light 和 spot light可以投射出阴影。

Toubleshooting

  • Bias
  • Back face rendering
  • Improving the projection matrix precision
  • Use the best option for self-shadowing
  • Frustum edge falloff
  • Freezing shadows in static world
  • Cleaning bone matrix weights
  • Self Shadow

看到的一个关于Three.js 和 Babylon.js 的简易对比1

So once again… Three.js vs. Babylon.js. This was a very short evaluation. What it came down to was that three.js had far more libraries and extensions - however, this was not the strength of three.js since there is no cohesive development cycles with three.js and although many libraries, tools, and extensions exist, more than often they are not maintained. So it was easy to demonstrate that practically any tool or extension we would require for the SXSW production would require myself or the team updating the extension or tool to be compatible with the other tools we might use on the project. This was due to the failings of the framework since each developer who writes an extension for three.js is writing for a specific compatibility for their own project needs… and not for the overall framework… as this is not within the scope of any developer or group of developers. Thus I find that it requires weeks if not months of of maintenance in three.js prior to building content, just to ensure compatibility between all of the tools and extensions needed to use for most projects. As for babylon.js, the wheel is not generally re-invented as it is with three.js, as most extensions are quickly absorbed into a cohesive framework quickly - provided they have universal appeal - and this integration ensures compatibility as there are fewer and fewer extensions to use, but instead an integrated set of tools which are thoroughly tested and used in production revealing any incompatibilities quickly.

The bottom line is that there are no alpha, beta, and development cycles in three.js, thus no stable releases. Whereas the opposite exists with babylon.js. There is a cohesive development of the tools, and Sony is smart enough to see beyond the politics and to realize that having Microsoft support the development of babylon.js is a huge bonus for an open source framework. And if anyone had to choose a company to support the development of a WebGL or any framework, who better than Microsoft? With practically every other useful WebGL framework in existence spawned by MIT, most all are barely useful at best. And why would anyone pay to use a limited WebGL framework such as PlayCanvas when Babylon.js is far more functional, stable, and free? This baffles me and most anyone who chooses one project using babylon.js. The only argument against babylon.js is that the development of the framework is now supported in house by Microsoft. But for myself and others, this is a positive, not a negative. I’ve been assured by the creators and lead developers of babylon.js that they have secured an agreement with Microsoft ensuring the framework remain open source and free. This ensures that anyone is able to contribute and review all code in the framework, and that it remains in the public domain. Sony gets this and we quickly moved forward adopting babylon.js as the WebGL framework within at least one division of Sony Electronics.


  1. babylonjs-vs-threejs-choosing-a-webgl-framework-for-sony ↩︎ ↩︎

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Babylon.js是一个用于创建3D游戏和图形的开源框架,它提供了许多功能强大的工具和功能,以便开发者能够轻松地构建各种3D场景和交互体验。为了方便将Babylon.js中创建的3D场景导出为其他格式,如.glTF、.OBJ等,Babylon.js提供了一个导出器(Exporter)的功能。 Babylon.js导出器允许开发者将他们在Babylon.js中创建的3D模型、纹理、材质以及其他相关资源导出到其他3D开发工具或平台上进行进一步编辑和使用。导出器实质上是一个插件,开发者可以根据自己的需求选择相应的导出器。例如,如果你想将Babylon.js场景导出为.glTF格式,你可以选择glTF导出器。 使用Babylon.js导出器非常简单,只需几行代码即可完成导出操作。首先,你需要引入相应的导出器插件,并将其初始化。然后,你需要指定要导出的场景或模型以及目标文件的路径和格式。最后,调用导出方法执行导出操作,将场景或模型导出到指定的文件中。 通过使用Babylon.js导出器,开发者可以将他们在Babylon.js中创建的3D体验分享给其他人,或者与其他3D开发工具进行集成。导出器的功能丰富且灵活,支持多种3D格式的导出,使得开发者能够更加自由地选择他们喜欢的导出格式。同时,导出器也提供了一些参数和选项,让开发者能够对导出的过程和结果进行一定程度的定制和调整。 总而言之,Babylon.js导出器是一个强大而便利的工具,它使得开发者能够轻松地将Babylon.js中创建的3D场景导出为其他格式,为他们的创作和开发带来了更多可能性和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值