Camera 摄像机组件

相机是用户获取图像的视角,游戏中的一帧图像是由若干个相机的渲染结果组成。

在方案工具中创建Camera组件

在属性检查器中点击新增->others->Camera即可创建Camera组件:

使用代码创建Camera组件

示例:

  // 创建Entity
  const mainCameraEntity = engine.game.createEntity3D("MainCamera");
  // 设置相机Entity位置
  mainCameraEntity.transform.position = engine.Vector3.createFromNumber(0, 0 , -10);

  // 添加Camera组件
  const mainCameraComp = mainCameraEntity.addComponent(engine.Camera);
  // 设置为透视相机
  mainCameraComp.projectionType = engine.Camera.ProjectionType.Perspective;
  // 添加到世界
  engine.game.sceneRoot.transform.addChild(mainCameraEntity.transform);

在方案工具中查看相机视锥体预览

在层级管理器点击具有Camera组件的Entity,即可在场景编辑器视角中看到相机产生的视锥体线框:

视口宽高比自适应

Camera的Aspect属性决定了视口的宽高比,如图所示:

如果宽高比与渲染目标的宽高比不匹配,则会出现画面被拉伸的情况,如图所示:

自适应aspect,aspect = 1.77,画面比例正常

指定aspect,aspect = 1.0,画面明显被拉伸

想要开启Aspect自适应,只需在Camera的属性面板中,将aspectType设置为Auto。

使用多相机渲染

场景的一帧允许由多个相机渲染而成,顺序由场景中的所有相机的depth从小到大渲染。

示例:

  // 设置主相机深度值为0
  mainCameraComp.depth = 0;
  // 主相机绘制前需要清屏
  mainCameraComp.clearFlag = 1;
  // 设置clearColor
  mainCameraComp.clearColor = new engine.Color(255,255,255,0);

  // 创建第二个相机的Entity
  const secondCameraEntity = engine.Entity.createEntity3D("MainCamera");
  secondCameraEntity.transform.position = engine.Vector3.createFromNumber(0, 0 , 100);
  // 添加Camera组件
  const secondCameraComp = secondCameraEntity.addComponent(engine.Camera);
  // 设置为正交相机
  secondCameraComp.projectionType = engine.Camera.ProjectionType.Orthographic;
  // 设置深度值为1,在主相机之后渲染
  secondCameraComp.depth = 1;
  // 绘制前不需要清屏
  secondCameraComp.clearFlag = 0;
  // 添加到世界
  game.world.add(secondCameraComp);

渲染到贴图

Camera可以将图像渲染到主屏,也可以渲染到一张贴图上,从而实现例如镜面、装备面板展示等效果。

示例:


  // 创建 200x400 大小的渲染贴图
  const rtWidth = 200;
  const rtHeight = 400;
  const rt = new engine.RenderTexture(rtWidth, rtHeight);

  secondCameraComp.targetTexture = rt;

射线检测 & 对象拾取

有时候需要在点击屏幕时拾取对象,拾取对象通常有两种实现方式:

  1. 像素拾取
  2. 包围球拾取

其中像素拾取的方式精度较高,在移动平台上开销非常高,通常不建议使用 目前支持包围球拾取的方式,使用方法如下:


  declare let cameraComp;
  declare let visibleList: engine.Entity;
  const rayCaster = new engine.Raycaster();
  // touchX,touchY为归一化的屏幕坐标
  rayCaster.setFromCamera([touchX, touchY], cameraComp.entity);

  const intersections = rayCaster.intersectEntities();