创建第一个模型

我们在场景中添加一个立方体。
创建立方体需要用到babylonjsMeshBuilder.CreateBox方法。注意,老版教程中会使用Mesh.CreateBox方法,这个方法官方已经不推荐使用了。

  1. import { ArcRotateCamera, Color3, Engine, MeshBuilder, Scene, Vector3, Color4 } from 'babylonjs';
  2. /** 中间代码省略 */
  3. const createScene = (engine: Engine) => {
  4. /** 创建场景 */
  5. const scene = new Scene(engine);
  6. /** end */
  7. /** 创建相机 */
  8. const camera = new ArcRotateCamera('camera', 0, 0, 10, Vector3.Zero(), scene);
  9. camera.attachControl(true);
  10. /** end */
  11. /** 创建立方体 */
  12. const box = MeshBuilder.CreateBox('box', { width: 2, height: 3, depth: 4 }, scene);
  13. /** end */
  14. return scene;
  15. };

MeshBuild.CreateBox方法需要传入三个参数:

  1. name:和cameraname含义一样,就是我们平时理解的id,需要全局唯一
  2. option:构建立方体的初始化配置,配置表如下: | 属性 | 值 | 默认值 | | —- | —- | —- | | size | (number) box每条边的长度 | 1 | | height | (number) 在Y轴上的边的长度,会覆盖size的值 | size | | width | (number) 在X轴上的边的长度,会覆盖size的值 | size | | depth | (number) 在Z轴上的边的长度,会覆盖size的值 | size | | faceColors | (Color4[]) 由Color4组成的长度为6的数组,代表每个面的颜色 | Color4(1, 1, 1, 1) for each side | | faceUV | (Vector4[]) 由Vector4组成的长度为6的数组,代表每个面的纹理贴图的应用范围 | UVs(0, 0, 1, 1) for each side | | updatable | (boolean) 指定Mesh的顶点数据是否可以被更新 | false | | sideOrientation | (number) 定义模型的每个面的可见方式。例如正方体有六个面,每个面都有正面和反面。默认相机只能看到一个面的正面,这样比较节省计算资源。
    - Mesh.FRONTSIDE,表示正面可见
    - Mesh.BACKSIDE,表示反面可见
    - Mesh.DOUBLESIDE,表示正反面都可见
    - Mesh.DEFAULT,目前这个值和FRONTSIDE相等
    | Mesh.DEFAULTSIDE |

  3. scene:代表物体所处场景

现在场景中就多了一个234的立方体,但是我们发现,这个立方体浑身漆黑,这是为什么呢?
原因很简单,因为我们还没有设置灯光。和现实世界一样,如果没有光,所有的物体都会是黑的。那么接下来我们就给这个场景增加一个平行光DirectionalLight——也就是我们现实中的太阳。

创建灯光

  1. import { ArcRotateCamera, Color3, Engine, MeshBuilder, Scene, Vector3, Color4, DirectionalLight } from 'babylonjs';
  2. /** 中间代码省略 */
  3. const createScene = (engine: Engine) => {
  4. /** 创建场景 */
  5. const scene = new Scene(engine);
  6. scene.clearColor = Color4.FromColor3(Color3.Gray());
  7. /** end */
  8. /** 创建相机 */
  9. const camera = new ArcRotateCamera('camera', 0, 0, 10, Vector3.Zero(), scene);
  10. camera.attachControl(true);
  11. /** end */
  12. /** 创建立方体 */
  13. const box = MeshBuilder.CreateBox('box', { width: 2, height: 3, depth: 4 }, scene);
  14. /** end */
  15. /** 创建灯光 */
  16. const light = new DirectionalLight('light', Vector3.Down(), scene);
  17. light.diffuse = Color3.Red();
  18. light.specular = Color3.Green();
  19. /** end */
  20. return scene;
  21. };

DirectionalLight构造函数需要传入三个参数:

  1. name:名称,全局唯一
  2. direction:光线照射的方向。Vector3.Down(){ x: 0, y: -1, z: 0 },表示光线垂直向下
  3. scene:光线所处场景

diffuse这个属性代表光线的漫反射光色,所谓漫反射色表示光线照射到物体上时物体所反射出的颜色,我们这里设置为了红色。现在我们先注释掉light.specular这段代码,可以看到光线从上而下照射到物体上时,物体的顶面呈现出了红色,而其他五个面由于没有被光照到,所以仍然是黑色:
image.png
specular这个属性代表镜面光色(也叫高光色),即光源在物体上反射出的颜色,就好像从镜子中看灯泡一样。我们这里设置成了绿色,理论上物体表面应该会有一个绿色的高光,但是实际效果却呈现出了黄色!
image.png
这是为什么呢?
原因很简单,物体表面现在有一个红色的漫反射色和绿色的高光色,着色器会把两种颜色混合,所以呈现出了黄色。当我们把相机旋转到一定角度,可以看到光源在物体上确实还是显示绿色:
image.png
由此可见,物体最终呈现出的颜色并不一定是我们设置的某种颜色,而是由多种情况下的颜色的混合结果。这个在开发中要特别注意。

更多的模型和灯光

当然,babylonjs还内置了很多其他的创建模型的方法,包括不规则几何图形和线。灯光除了平行光DirectionalLight,还有点光PointLight、聚光灯SpotLight、半球光HemisphericLight。您可以在babylonjs官方网站找到更多的信息,或者查看镜像中文网站https://doc.cnbabylon.com/babylon101/。我们这里就不再赘述了,后面有机会再展开讲解。

现在有一个问题了,我们能不能在没有灯光照射的情况下,让物体产生颜色呢?答案当然是可以,这就需要引入一个新的概念——材质。下面我们就聊聊如何创建材质,以及设置它的相关属性。