场景即为LayaAir引擎的3D世界容器,用于呈现游戏的3D画面和加载各种3D元素,游戏中的摄像机,灯光,人物,物品等都需要放到场景中才能展示出画面,相当于一个游戏3D播放器或者3D视图。
//实例化一个相机,设置纵横比0为自动匹配。0.1最近看到的距离(近裁剪面),100最远看到的距离(远裁剪面)。
var camera = new Laya.Camera(0, 0.1, 100)
//正交投影属性设置
camera.orthographicProjection = true;
//正交垂直矩阵距离,控制3D物体远近与显示大小
camera.orthographicVerticalSize = 7;
//设置相机的视野范围90度
camera.fieldOfView = 90;
//手动设置横纵比
camera.aspectRatio = 2;
//重置
camera.aspectRatio = 0;
//相机设置清楚标记,使用固定颜色
camera.clearFlag = Laya.BaseCamera.CLEARFLAG_SOLIDCOLOR;
//设置背景颜色
camera.clearColor = new Laya.Vector4(0.5,0.5,0.6,1);
2.天空盒://天空盒代码
Laya.BaseMaterial.load("res/.../skyBox.lmat", this.Handler.create(null, function(mat) {
//设置相机的清除标识为天空盒
camera.clearFlag = Laya.BaseCamera.CLEARFLAG_SKY;
//获取相机的天空渲染器
var skyRenderer = camera.skyRenderer;
//创建天空盒的mesh
skyRenderer.mesh = Laya.SkyBox.instance;
//设置天空盒材质
skyRenderer.material = mat;
}));
在使用背景色和天空盒时,一定要保证Camera(摄像机)的clearFlag清除标记属性,与自己需要的效果对应。
网格和纹理决定了一个物体的形状和外观,光源决定了环境的颜色和氛围。灯光的种类有多种,不同的光源呈现的效果不同,可以设置不同的参数。目前的种类有:PointLight(点光),DirectionLight(平行光),SpotLight(聚光)3种
点光源:向四面八方发射光线的光源,又称全向光或者球状光,现实中的点光源比如灯泡、蜡烛。点光源是有强度、颜色和衰减半径属性
//创建点光源
var pointLight = scene.addChild(new Laya.PointLight()) as Laya.PointLight;
//设置点光源位置
pointLight.transform.position = new Laya.Vector3(0.4, 0.4, 0.0);
//设置点光源的范围
pointLight.range = 6.0;
range 为设置点光源的范围,相当于点光的照射范围,数值越大,光照范围越大。
方向光:有固定的一个方向,可通过弧度值设定,并且也没有衰减和光照范围,会对全场景所有模型进行照亮。3D世界中经常用来模拟固定方向的太阳光。
//创建方向光
var directionLight = scene.addChild(new Laya.DirectionLight()) as Laya.DirectionLight;
//方向光的颜色
directionLight.color = new Laya.Vector3(1, 1, 1);
//设置平行光的方向
var mat = directionLight.transform.worldMatrix;
mat.setForward(new Laya.Vector3(-1.0, -1.0, -1.0));
directionLight.transform.worldMatrix=mat;
setForward 平行光的方向,分别代表x、y、z轴上的方向,负数为负轴,正数为正轴,值的范围为-1—0—1,超过范围后为-1或1
聚光:从特定光源方向射出的光,比如手电筒,舞台筒灯等。光照区域根据距离因素逐渐放大,同时光照区域边缘也有衰减现象。
//聚光灯
var spotLight = scene.addChild(new Laya.SpotLight()) as Laya.SpotLight;
//设置聚光灯颜色
spotLight.color = new Laya.Vector3(1, 1, 0);
//设置聚光灯位置
spotLight.transform.position = new Laya.Vector3(0.0, 1.2, 0.0);
//设置聚光灯方向
var mat = spotLight.transform.worldMatrix;
mat.setForward(new Laya.Vector3(0.15, -1.0, 0.0));
spotLight.transform.worldMatrix = mat;
//设置聚光灯范围
spotLight.range = 6.0;
//设置聚光灯锥形角度
spotLight.spotAngle = 32;
range 为聚光的照射范围,与点光类似,区别只是聚光有方向,而点光无方向。
spotAngle 为聚光灯的锥形角度,设置的值越小,聚光光圈的越小,反之光圈越大。
为灯光添加阴影:投影是灯光照射模型时产生的即时阴影,可随着灯光角度、灯光强度、模型位置等变化而变化。投影是3D世界最重要的因素之一,能产生更加强烈的立体感。即时阴影非常损耗性能,不能用得太多,特别是游戏场景,模型量较大,一般我们不使用即时投影,而使用静态的光照贴图。
要让场景中产生投影,我们需了解灯光的以下属性:
除此之外,还要需要在模型上设置投影属性:
//灯光开启阴影
directionLight.shadow = true;
//可见阴影距离
directionLight.shadowDistance = 3;
//生成阴影贴图尺寸
directionLight.shadowResolution = 2048;
//生成阴影贴图数量
directionLight.shadowPSSMCount = 1;
//模糊等级,越大越高,更耗性能
directionLight.shadowPCFType = 3;
//地面加到场景上 并且获取地面
var grid = this.scene.addChild(Laya.Loader.getRes("res/threeDimen/staticModel/grid/plane.lh")) as Laya.Sprite3D;
//地面接收阴影
(grid.getChildAt(0) as Laya.MeshSprite3D).meshRenderer.receiveShadow = true;
.......
//设置猴子能产生阴影
(layaMonkey.getChildAt(0).getChildAt(0) as Laya.SkinnedMeshSprite3D).skinnedMeshRenderer.castShadow = true;
Component 组件是附加到所有3D对象的内容的基类 。组件的种类也是非常多的,比较常用的像Animator动画组件,PhysicsCollider物理碰撞器和RigidBody3D刚体这些物理组件等
//创建一个空节点用来防止各模型
sprite3D = scene.addChild(new Laya.Sprite3D());
//正方体
var box = sprite3D.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createBox(0.5, 0.5, 0.5)));
box.transform.position = new Laya.Vector3(2.0, 0.25, 0.6);
box.transform.rotate(new Laya.Vector3(0, 45, 0), false, false);
//球体
var sphere = sprite3D.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createSphere(0.25, 20, 20)));
sphere.transform.position = new Laya.Vector3(1.0, 0.25, 0.6);
//圆柱体
var cylinder = sprite3D.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createCylinder(0.25, 1, 20)));
cylinder.transform.position = new Laya.Vector3(0, 0.5, 0.6);
//胶囊体
var capsule = sprite3D.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createCapsule(0.25, 1, 10, 20)));
capsule.transform.position = new Laya.Vector3(-1.0, 0.5, 0.6);
//圆锥体
var cone = sprite3D.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createCone(0.25, 0.75)));
cone.transform.position = new Laya.Vector3(-2.0, 0.375, 0.6);
//平面
var plane = sprite3D.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createPlane(6, 6, 10, 10)));
//加载一个场景的.ls文件,然后获取它的子对象。在获取子对象之前,建议打开.ls文件查看模型的父子层级关系,因为在制作模型时,我们也不能确定模型是由多少个子对象模型构成,及它们的命名规则。
//初始化3D场景
var scene = Laya.stage.addChild(Laya.Loader.getRes("res/threeDimen/scene/ChangeMaterialDemo/Conventional/scene.ls"));
//获取球型精灵
var sphere = scene.getChildByName("Sphere");
//获取精灵的mesh
var sphereMesh = sphere.meshFilter.sharedMesh;
//此时已经拿到了场景中的球体的网格
获取子对象时还应注意一个问题,就是模型与材质未加载完成,是无法获取子对象的,因此需要资源预加载,或异步加载时进行完成事件监听。//新建四个mesh
var box = Laya.PrimitiveMesh.createBox(0.5, 0.5, 0.5);//立方体
var capsule = Laya.PrimitiveMesh.createCapsule(0.25, 1, 10, 20);
var cylinder = Laya.PrimitiveMesh.createCylinder(0.25, 1, 20);
var cone = Laya.PrimitiveMesh.createCone(0.25, 0.75);
var index = 0;
//.............按钮点击事件 监听
changeMeshButton.on(Laya.Event.CLICK, this, function(){
index++;
if (index % 5 === 1 ){
//切换mesh
sphere.meshFilter.sharedMesh = box;
}
else if (index % 5 === 2){
//切换mesh
sphere.meshFilter.sharedMesh = capsule;
}
else if(index % 5 === 3){
//切换mesh
sphere.meshFilter.sharedMesh = cylinder;
}
else if(index % 5 === 4){
//切换mesh
sphere.meshFilter.sharedMesh = cone;
}
else{
//切换mesh
sphere.meshFilter.sharedMesh = sphereMesh;
}
});
//添加自定义模型
var box = scene.addChild(new Laya.MeshSprite3D(Laya.PrimitiveMesh.createBox(1, 1, 1)));
box.transform.rotate(new Vector3(0, 45, 0), false, false);
//创建材质
var material = new Laya.BlinnPhongMaterial();
Laya.Texture2D.load("res/layabox.png", Laya.Handler.create(this, function(tex){
//纹理加载完成后赋值
material.albedoTexture = tex;
}));
//将材质赋值给自定义模型
box.meshRenderer.material = material;
//材质加载
Laya.BaseMaterial.load("res/skyBox2/skyBox2.lmat",Laya.Handler.create(this,function(mat) {
var skyRenderer = camera.skyRenderer;
//创建天空盒的mesh
skyRenderer.mesh = Laya.SkyBox.instance;
//设置天空盒材质
skyRenderer.material = mat;
}));
Script3D脚本在开发过程中使用的非常频繁的。脚本是一种特殊的组件,为了方便开发者使用,他有自己的生命周期。脚本的功能也是非常大的,例如角色控制脚本,NPC控制脚本、场景物体控制脚本等,实现了控制与显示分离。
(有关显示对象变化的都会用到他)
//移动摄像机 true代表是局部坐标,false是相对世界坐标
camera.transform.translate(new Laya.Vector3(0, 3, 3),false);
//旋转摄像机 参数:局部坐标,弧度制(false为角度制)
camera.transform.rotate(new Laya.Vector3(-30, 0, 0), true, false);
//雾化代码
scene.enableFog = true;
//设置雾化的颜色
scene.fogColor = new Laya.Vector3(0,0,0.6);
//设置雾化的起始位置,相对于相机的距离
scene.fogStart = 10;
//设置雾化最浓处的距离。
scene.fogRange = 40
//加载相机天空盒材质
Laya.BaseMaterial.load("res/.../SkyBox.lmat", Laya.Handler.create(null, function(mat){})
//设置场景环境光
scene.ambientColor = new Laya.Vector3(0.6, 0, 0);