相机

相机组件

相机组件可以将 3D 场景投影到 2D 屏幕上,基于相机组件,我们可以定制各种不同的渲染效果。

首先需要将相机组件挂载到在场景中已激活的 Entity 上,编辑器项目通常已经自带了相机组件,当然我们也可以自己手动添加。

image-20231009114711623

添加完毕后,就可以在检查器里可以查看相机属性,并且左下角的相机预览可以方便地查看项目实际运行时的相机效果:

image-20240718211520816

您也可以在脚本中通过如下代码为 Entity 挂载相机组件:

// 创建实体
const entity = root.createChild("cameraEntity");
// 创建相机组件
const camera = entity.addComponent(Camera);

属性

通过修改相机组件的属性可以定制渲染效果。下方是相机组件在 检查器面板 暴露的属性设置。

image-20240718211645854

也可以通过脚本去获取相机组件并设置相应的属性。

// 从挂载相机的节点上获取相机组件
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多样本抗锯齿采样样本数量,仅当独立画布开启时才能生效,如 enableHDRenablePostProcessopaqueTextureEnabled
enableHDR是否启用 HDR 渲染,允许 shader 输出的颜色使用浮点数进行存储,可以得到更大范围的值,用于后处理等场景。
enablePostProcess是否启用后处理,后处理配置详见后处理教程

裁剪遮罩

相机组件可以通过设置 cullingMask 选择性地渲染场景内的渲染组件

渲染目标

相机组件可以通过设置 renderTarget 将渲染结果渲染到不同的目标上。

视锥剔除

enableFrustumCulling 属性默认是开启的,因为对于三维世界来说,“看不见的东西就不需要渲染”是个很自然的逻辑,属于最基本的性能优化。关闭视锥剔除意味着关闭此项优化。如果你想保留此项优化,而只想让某个节点始终渲染,可以把节点的渲染器的包围盒设置成无限大。

方法

相机组件提供各种方法(主要涉及渲染空间转换)方便开发者实现期望的定制能力,在此之前,要先学会如何获取相机组件,在知道相机组件挂载在哪个节点的前提下,可直接通过 getComponentgetComponentsIncludeChildren 获取:

// 从挂载相机的节点上获取相机组件
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通过屏幕空间中的一个点生成世界空间射线。

Shader 替换

借助 setReplacementShader 全局替换 Shader 的能力可以观测特定的渲染效果:

空间转换

需要注意的是 screenToWorldPointviewportToWorldPoint 等方法传入点的 Z 表示返回的点到相机的距离。

onBeginRender 与 onEndRender

相机组件额外包含了 onBeginRenderonEndRender 两个生命周期回调,它们的时序可参考脚本生命周期时序图

最后更新于 七月 11, 2024

这篇文档对您有帮助吗?