相机组件可以将 3D 场景投影到 2D 屏幕上,基于相机组件,我们可以定制各种不同的渲染效果。
首先需要将相机组件挂载到在场景中已激活的 Entity 上,编辑器项目通常已经自带了相机组件,当然我们也可以自己手动添加。
添加完毕后,就可以在检查器里可以查看相机属性,并且左下角的相机预览可以方便地查看项目实际运行时的相机效果:
您也可以在脚本中通过如下代码为 Entity 挂载相机组件:
// 创建实体
const entity = root.createChild("cameraEntity");
// 创建相机组件
const camera = entity.addComponent(Camera);
通过修改相机组件的属性可以定制渲染效果。下方是相机组件在 检查器面板 暴露的属性设置。
也可以通过脚本去获取相机组件并设置相应的属性。
// 从挂载相机的节点上获取相机组件
const camera = entity.getComponent(Camera);
// 设置相机类型
camera.isOrthographic = true;
// 设置相机的近平面
camera.nearClipPlane = 0.1;
// 设置相机的远平面
camera.farClipPlane = 100;
// 设置相机的 FOV(角度制)
camera.fieldOfView = 45;
// 设置相机在画布上的渲染区域(归一化)
camera.viewport = new Vector4(0, 0, 1, 1);
// 设置相机的渲染优先级(值越小,渲染优先级越高)
camera.priority = 0;
// 设置相机是否开启视锥体裁剪
camera.enableFrustumCulling = true;
// 设置相机渲染前的清除标记
camera.clearFlags = CameraClearFlags.All;
// 开启后处理
camera.enablePostProcess = true;
// 开启 HDR
camera.enableHDR = true;
其中每个属性对应的功能如下:
类型 | 属性 | 解释 |
---|---|---|
通用 | isOrthographic | 通过设置 isOrthographic 来决定透视投影或正交投影。若需要透视效果则设为 false ,默认为 false |
nearClipPlane | 近裁剪平面,若渲染物体与相机的距离小于此值则无法正常渲染 | |
farClipPlane | 远裁剪平面,若渲染 物体与相机的距离大于此值则无法正常渲染 | |
viewport | 视口,确定内容最后被渲染到目标设备里的范围,修改此值可以决定最终渲染结果在渲染目标中的位置 | |
priority | 渲染优先级,用来确定在多相机的情况下按照什么顺序去渲染相机包含的内容。 | |
enableFrustumCulling | 是否开启视锥剔除,开启后可剔除不在渲染范围内物体的渲染,默认为 true | |
clearFlags | 在渲染这个相机前清理画布缓冲的标记,通过编标记可以选择性地保留上次相机渲染的结果 | |
cullingMask | 裁剪遮罩,用来选择性地渲染场景中的渲染组件。 | |
aspectRatio | 渲染目标的宽高比,一般是根据 canvas 大小自动计算,也可以手动改变(不推荐) | |
renderTarget | 渲染目标,确定内容被渲染到哪个目标上。 | |
pixelViewport | 屏幕上相机的视口(以像素坐标表示)。若渲染目标为画布,且视口为整个画布,则左上角为(0, 0),右下角为(canvas.width, canvas.height)。 | |
透视投影 | fieldOfView | 视角,默认为 45 度(0,180) |
正交投影 | orthographicSize | 正交模式下相机取景上边框至下边框距离的一半 |
渲染相关 | depthTextureMode | 深度纹理模式,默认为DepthTextureMode.None ,如果开启,可以在 shader 中使用 camera_DepthTexture 深度纹理。详情可参考相机纹理 |
opaqueTextureEnabled | 是否启用非透明纹理,默认关闭,如果启用,可以在透明队列的 shader 中使用 camera_OpaqueTexture 非透明纹理。 | |
opaqueTextureDownsampling | 启用非透明纹理时,可以设置降采样,可以根据清晰度需求和性能要求来进行设置。 | |
msaaSamples | 多样本抗锯齿采样样本数量,仅当独立画布开启时才能生效,如 enableHDR 、enablePostProcess 、opaqueTextureEnabled 。 | |
enableHDR | 是否启用 HDR 渲染,允许 shader 输出的颜色使用浮点数进行存储,可以得到更大范围的值,用于后处理等场景。 | |
enablePostProcess | 是否启用后处理,后处理配置详见后处理教程。 |
相机组件可以通过设置 cullingMask
选择性地渲染场景内的渲染组件
相机组件可以通过设置 renderTarget
将渲染结果渲染到不同的目标上。
enableFrustumCulling
属性默认是开启的,因为对于三维世界来说,“看不见的东西就不需要渲染”是个很自然的逻辑,属于最基本的性能优化。关闭视锥剔除意味着关闭此项优化。如果你想保留此项优化,而只想让某个节点始终渲染,可以把节点的渲染器的包围盒设置成无限大。
相机组件提供各种方法(主要涉及渲染
与空间转换
)方便开发者实现期望的定制能力,在此之前,要先学会如何获取相机组件,在知道相机组件挂载在哪个节点的前提下,可直接通过 getComponent
或 getComponentsIncludeChildren
获取:
// 从挂载相机的节点上获取相机组件
const camera = entity.getComponent(Camera);
// 从挂载相机节点的父节点上获取相机组件(不推荐)
const cameras = entity.getComponentsIncludeChildren(Camera, []);
若不清楚相机组件挂载的节点,也可以通过较为 Hack 的方式获取场景中的所有相机组件:
// 获取这个场景中的所有相机组件(不推荐)
const cameras = scene._componentsManager._activeCameras;
类型 | 属性 | 解释 |
---|---|---|
渲染 | resetProjectionMatrix | 重置自定义投影矩阵,恢复到自动模式。 |
resetAspectRatio | 重置自定义渲染横纵比,恢复到自动模式。 | |
render | 手动渲染。 | |
setReplacementShader | 设置全局渲染替换着色器。 | |
resetReplacementShader | 清空全局渲染替换着色器。 | |
空间转换 | worldToViewportPoint | 将一个点从世界空间转换到视口空间。 |
viewportToWorldPoint | 将一个点从视口空间转换到世界空间。 | |
viewportPointToRay | 通过视口空间中的一个点生成世界空间射线。 | |
screenToViewportPoint | 将一个点从屏幕空间转换到视口空间。 | |
viewportToScreenPoint | 将一个点从视口空间转换到屏幕空间。 | |
worldToScreenPoint | 将一个点从世界空间转换到屏幕空间。 | |
screenToWorldPoint | 将一个点从屏幕空间转换到世界空间。 | |
screenPointToRay | 通过屏幕空间中的一个点生成世界空间射线。 |
借助 setReplacementShader
全局替换 Shader 的能力可以观测特定的渲染效果:
需要注意的是 screenToWorldPoint
、 viewportToWorldPoint
等方法传入点的 Z 表示返回的点到相机的距离。
相机组件额外包含了 onBeginRender 与 onEndRender 两个生命周期回调,它们的时序可参考脚本生命周期时序图