Laya.Camera

概述

Laya.Camera 是 LayaAir 3D 引擎中的摄像机类,继承自 BaseCamera。摄像机用于捕捉 3D 场景并将其渲染到屏幕。每个 3D 场景至少需要一个摄像机才能显示内容。

继承关系

EventDispatcher → Node → Sprite3D → BaseCamera → Camera
                                                    ↓
                                              WebXRCamera

命名空间约定

必须使用 Laya. 前缀访问所有引擎类。

// ✅ 正确
const camera = new Laya.Camera();
camera.fieldOfView = 60;

// ❌ 错误
const camera = new Camera();

构造函数

constructor(aspectRatio: number = 0, nearPlane: number = 0.3, farPlane: number = 1000)
参数 类型 默认值 描述
aspectRatio number 0 横纵比(0 为自动计算)
nearPlane number 0.3 近裁剪面距离
farPlane number 1000 远裁剪面距离
// 创建默认摄像机
const camera = new Laya.Camera();

// 自定义裁剪面
const camera = new Laya.Camera(0, 0.1, 100);

// 设置横纵比
const camera = new Laya.Camera(16 / 9, 0.1, 100);

实例属性

视野和投影

fieldOfView
get fieldOfView(): number
set fieldOfView(value: number)

视野角度(FOV),单位为度。仅透视投影模式有效。

camera.fieldOfView = 60; // 60度视野
orthographic
get orthographic(): boolean
set orthographic(value: boolean)

是否使用正交投影。

// 透视投影(默认)
camera.orthographic = false;

// 正交投影
camera.orthographic = true;
orthographicVerticalSize
get orthographicVerticalSize(): number
set orthographicVerticalSize(value: number)

正交投影垂直尺寸。仅正交投影模式有效。

camera.orthographic = true;
camera.orthographicVerticalSize = 10;
aspectRatio
get aspectRatio(): number
set aspectRatio(value: number)

横纵比。

camera.aspectRatio = 16 / 9;

裁剪面

nearPlane
get nearPlane(): number
set nearPlane(value: number)

近裁剪面距离。小于此距离的对象不会被渲染。

camera.nearPlane = 0.1;
farPlane
get farPlane(): number
set farPlane(value: number)

远裁剪面距离。大于此距离的对象不会被渲染。

camera.farPlane = 500;

清除设置

clearFlag
clearFlag: CameraClearFlags

清除标志,定义如何清除渲染目标。

  • CameraClearFlags.SolidColor - 使用纯色清除
  • CameraClearFlags.DepthOnly - 仅清除深度
  • CameraClearFlags.Sky - 渲染天空盒
camera.clearFlag = Laya.CameraClearFlags.SolidColor;
clearColor
get clearColor(): Color
set clearColor(value: Color)

背景清除颜色。

camera.clearColor = new Laya.Color(0.2, 0.2, 0.2, 1.0);

图层遮罩

cullingMask
get cullingMask(): number
set cullingMask(value: number)

渲染图层遮罩,控制摄像机渲染哪些层的对象。

// 只渲染第0层
camera.cullingMask = 1 << 0;

// 渲染第0层和第1层
camera.cullingMask = (1 << 0) | (1 << 1);

// 渲染所有层
camera.addAllLayers();

渲染设置

enableRender
enableRender: boolean

是否允许渲染。

camera.enableRender = true;
enableHDR
get enableHDR(): boolean
set enableHDR(value: boolean)

是否开启 HDR(高动态范围渲染)。开启后对性能有一定影响。

camera.enableHDR = true;
msaa
get msaa(): boolean
set msaa(value: boolean)

多重采样抗锯齿。

camera.msaa = true;
fxaa
get fxaa(): boolean
set fxaa(value: boolean)

空间抗锯齿(FXAA)。

camera.fxaa = true;
opaquePass
get opaquePass(): boolean
set opaquePass(value: boolean)

OpaquePass 模式。

camera.opaquePass = false;
renderingOrder
get renderingOrder(): number
set renderingOrder(value: number)

渲染顺序。数值越小越先渲染。

camera.renderingOrder = 0;

矩阵

viewMatrix
get viewMatrix(): Matrix4x4

视图矩阵(只读)。

projectionMatrix
get projectionMatrix(): Matrix4x4
set projectionMatrix(value: Matrix4x4)

投影矩阵。

const projMatrix = camera.projectionMatrix;
projectionViewMatrix
get projectionViewMatrix(): Matrix4x4

视图投影矩阵(只读)。

视口

viewport
get viewport(): Viewport
set viewport(value: Viewport)

屏幕像素坐标的视口。

camera.viewport = new Laya.Viewport(0, 0, Laya.stage.width, Laya.stage.height);
normalizedViewport
get normalizedViewport(): Viewport
set normalizedViewport(value: Viewport)

归一化视口(0-1 范围)。

camera.normalizedViewport = new Laya.Viewport(0, 0, 0.5, 1.0); // 左半屏
clientWidth / clientHeight
get clientWidth(): number
get clientHeight(): number

视口宽度和高度(只读)。

渲染目标

renderTarget
get renderTarget(): RenderTexture
set renderTarget(value: RenderTexture)

自定义渲染目标。

const renderTexture = new Laya.RenderTexture(512, 512, Laya.RenderTargetFormat.R8G8B8A8, Laya.RenderTargetFormat.DEPTH_16);
camera.renderTarget = renderTexture;
depthTexture
set depthTexture(value: BaseTexture)

深度贴图。

camera.depthTexture = depthTexture;
depthTextureMode
get depthTextureMode(): DepthTextureMode
set depthTextureMode(value: DepthTextureMode)

深度贴图模式。

  • DepthTextureMode.None - 无深度贴图
  • DepthTextureMode.Depth - 深度贴图
  • DepthTextureMode.DepthNormals - 深度法线贴图
camera.depthTextureMode = Laya.DepthTextureMode.Depth;
depthTextureFormat
get depthTextureFormat(): RenderTargetFormat
set depthTextureFormat(value: RenderTargetFormat)

深度贴图格式。

camera.depthTextureFormat = Laya.RenderTargetFormat.DEPTH_16;
enableBlitDepth
get enableBlitDepth(): boolean
set enableBlitDepth(value: boolean)

是否使用内置深度贴图。

camera.enableBlitDepth = true;

后期处理

postProcess
get postProcess(): PostProcess
set postProcess(value: PostProcess)

后期处理。

const postProcess = new Laya.PostProcess();
// 配置后期处理效果...
camera.postProcess = postProcess;

其他属性

boundFrustum
get boundFrustum(): BoundFrustum

摄像机视锥体(只读)。

const frustum = camera.boundFrustum;
enableBuiltInRenderTexture
get enableBuiltInRenderTexture(): boolean
set enableBuiltInRenderTexture(value: boolean)

是否使用内置 RenderTexture 为 CommandBuffer 服务。

camera.enableBuiltInRenderTexture = true;
opaqueTextureSize
opaqueTextureSize: number

不透明纹理大小。

camera.opaqueTextureSize = 512;
useOcclusionCulling
useOcclusionCulling: boolean

是否使用遮挡剔除。

camera.useOcclusionCulling = true;

实例方法

坐标转换

viewportPointToRay()

计算从屏幕空间生成的射线。

viewportPointToRay(point: Vector2, out: Ray): void
const point = new Laya.Vector2(Laya.stage.mouseX, Laya.stage.mouseY);
const ray = new Laya.Ray(new Laya.Vector3(), new Laya.Vector3());
camera.viewportPointToRay(point, ray);

// 用于射线检测
const hitResult = new Laya.HitResult();
scene.physicsSimulation.rayCast(ray, hitResult);
normalizedViewportPointToRay()

计算从裁切空间(归一化坐标)生成的射线。

normalizedViewportPointToRay(point: Vector2, out: Ray): void
const point = new Laya.Vector2(0.5, 0.5); // 屏幕中心
const ray = new Laya.Ray();
camera.normalizedViewportPointToRay(point, ray);
worldToViewportPoint()

将一个点从世界空间转换到视口空间。

worldToViewportPoint(position: Vector3, out: Vector4): void
const worldPos = new Laya.Vector3(0, 0, 0);
const viewportPos = new Laya.Vector4();
camera.worldToViewportPoint(worldPos, viewportPos);
console.log(viewportPos.x, viewportPos.y); // 屏幕坐标
worldToNormalizedViewportPoint()

将一个点从世界空间转换到归一化视口空间。

worldToNormalizedViewportPoint(position: Vector3, out: Vector4): void
convertScreenCoordToOrthographicCoord()

转换 2D 屏幕坐标到 3D 正交投影下的坐标系统。仅正交投影模式下有效。

convertScreenCoordToOrthographicCoord(source: Vector3, out: Vector3): boolean
const screenPos = new Laya.Vector3(Laya.stage.mouseX, Laya.stage.mouseY, 0);
const worldPos = new Laya.Vector3();
camera.convertScreenCoordToOrthographicCoord(screenPos, worldPos);
sprite.transform.position = worldPos;

CommandBuffer

addCommandBuffer()

添加渲染命令缓存。

addCommandBuffer(event: CameraEventFlags, commandBuffer: CommandBuffer): void
const commandBuffer = new Laya.CommandBuffer();
// 配置命令缓冲...
camera.addCommandBuffer(Laya.CameraEventFlags.BeforeTransparent, commandBuffer);
removeCommandBuffer()

移除指定的渲染命令缓存。

removeCommandBuffer(event: CameraEventFlags, commandBuffer: CommandBuffer): void
camera.removeCommandBuffer(Laya.CameraEventFlags.BeforeTransparent, commandBuffer);
removeCommandBuffers()

移除指定事件的所有渲染命令缓存。

removeCommandBuffers(event: CameraEventFlags): void
camera.removeCommandBuffers(Laya.CameraEventFlags.BeforeTransparent);

图层管理

addAllLayers()

增加所有图层。

camera.addAllLayers();
removeAllLayers()

移除所有图层。

camera.removeAllLayers();
addLayer()

增加指定图层。

addLayer(layer: number): void
camera.addLayer(1);
removeLayer()

移除指定图层。

removeLayer(layer: number): void
camera.removeLayer(1);

渲染

render()

渲染场景。

render(scene: Scene3D): void
camera.render(scene);

投影矩阵

resetProjectionMatrix()

重新计算投影矩阵。

resetProjectionMatrix(): void
camera.resetProjectionMatrix();

克隆

clone()

克隆摄像机。

clone(): Camera
const newCamera = camera.clone();
scene.addChild(newCamera);

销毁

destroy()

销毁摄像机。

destroy(destroyChild: boolean = true): void
camera.destroy();

静态方法

drawRenderTextureByScene()

根据相机和场景信息获取场景某位置的渲染结果。

static drawRenderTextureByScene(
    camera: Camera,
    scene: Scene3D,
    renderTexture: RenderTexture
): RenderTexture
drawTextureCubeByScene()

根据场景中的位置绘制立方体贴图。

static drawTextureCubeByScene(
    camera: Camera,
    position: Vector3,
    scene: Scene3D,
    renderCubeSize: number,
    format: TextureFormat,
    cullingMask: number = 0
): TextureCube
getTexturePixel()

获取纹理像素。

static getTexturePixel(texture: Texture2D): ArrayBufferView
getTexturePixelAsync()

异步获取纹理像素。

static getTexturePixelAsync(texture: Texture2D): Promise<ArrayBufferView>

使用示例

创建基础摄像机

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    // 创建摄像机
    const camera = new Laya.Camera();
    camera.transform.position = new Laya.Vector3(0, 3, 10);
    camera.transform.lookAt(new Laya.Vector3(0, 0, 0), new Laya.Vector3(0, 1, 0));
    scene.addChild(camera);

    // 设置视野
    camera.fieldOfView = 60;

    // 设置裁剪面
    camera.nearPlane = 0.1;
    camera.farPlane = 100;
}

设置背景颜色

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    const camera = new Laya.Camera();
    camera.transform.position = new Laya.Vector3(0, 3, 10);
    scene.addChild(camera);

    // 设置纯色背景
    camera.clearFlag = Laya.CameraClearFlags.SolidColor;
    camera.clearColor = new Laya.Color(0.2, 0.2, 0.2, 1.0);
}

正交投影摄像机

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    // 创建正交投影摄像机
    const camera = new Laya.Camera();
    camera.orthographic = true;
    camera.orthographicVerticalSize = 10;
    camera.transform.position = new Laya.Vector3(0, 0, -10);
    scene.addChild(camera);
}

射线检测(点击场景)

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    const camera = new Laya.Camera();
    camera.transform.position = new Laya.Vector3(0, 3, 10);
    scene.addChild(camera);

    // 监听鼠标点击
    Laya.stage.on(Laya.Event.MOUSE_DOWN, this, () => {
        const point = new Laya.Vector2(Laya.stage.mouseX, Laya.stage.mouseY);
        const ray = new Laya.Ray(new Laya.Vector3(), new Laya.Vector3());
        camera.viewportPointToRay(point, ray);

        const hitResult = new Laya.HitResult();
        scene.physicsSimulation.rayCast(ray, hitResult);

        if (hitResult.succeeded) {
            console.log("点击位置:", hitResult.point);
            console.log("点击对象:", hitResult.collider.owner.name);
        }
    });
}

世界坐标转屏幕坐标

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    const camera = new Laya.Camera();
    camera.transform.position = new Laya.Vector3(0, 3, 10);
    scene.addChild(camera);

    const sprite = new Laya.Sprite3D("TestSprite");
    sprite.transform.position = new Laya.Vector3(0, 0, 0);
    scene.addChild(sprite);

    // 将 3D 位置转换为屏幕坐标
    const worldPos = sprite.transform.position;
    const viewportPos = new Laya.Vector4();
    camera.worldToViewportPoint(worldPos, viewportPos);

    console.log("屏幕X:", viewportPos.x);
    console.log("屏幕Y:", viewportPos.y);
    console.log("深度:", viewportPos.z);
}

分屏渲染(多摄像机)

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    const width = Laya.stage.width;
    const height = Laya.stage.height;

    // 左侧摄像机
    const camera1 = new Laya.Camera();
    camera1.transform.position = new Laya.Vector3(-5, 3, 10);
    camera1.viewport = new Laya.Viewport(0, 0, width / 2, height);
    camera1.clearColor = new Laya.Color(0.8, 0.8, 1.0, 1.0);
    scene.addChild(camera1);

    // 右侧摄像机
    const camera2 = new Laya.Camera();
    camera2.transform.position = new Laya.Vector3(5, 3, 10);
    camera2.viewport = new Laya.Viewport(width / 2, 0, width / 2, height);
    camera2.clearColor = new Laya.Color(1.0, 0.8, 0.8, 1.0);
    scene.addChild(camera2);
}

使用图层遮罩

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    // 主摄像机(渲染所有层)
    const mainCamera = new Laya.Camera();
    mainCamera.addAllLayers();
    scene.addChild(mainCamera);

    // 小地图摄像机(只渲染特定层)
    const miniMapCamera = new Laya.Camera();
    miniMapCamera.removeAllLayers();
    miniMapCamera.addLayer(8); // 只渲染第8层
    miniMapCamera.orthographic = true;
    scene.addChild(miniMapCamera);

    // 设置对象图层
    const sprite = new Laya.Sprite3D();
    sprite.layer = 8;
    scene.addChild(sprite);
}

渲染到纹理

export async function main() {
    await Laya.init(0, 0);

    const scene = new Laya.Scene3D();
    Laya.stage.addChild(scene);

    const camera = new Laya.Camera();
    camera.transform.position = new Laya.Vector3(0, 3, 10);
    scene.addChild(camera);

    // 创建渲染目标
    const renderTexture = new Laya.RenderTexture(512, 512, Laya.RenderTargetFormat.R8G8B8A8, Laya.RenderTargetFormat.DEPTH_16);
    camera.renderTarget = renderTexture;

    // 使用渲染纹理...
}

常见问题

Q: 新建 Scene3D 后看不到任何内容?

A: 场景必须添加摄像机才能渲染显示:

const scene = new Laya.Scene3D();
Laya.stage.addChild(scene);

// 必须添加摄像机
const camera = new Laya.Camera();
scene.addChild(camera);

Q: 如何调整摄像机视野范围?

A: 通过 fieldOfView 属性调整:

camera.fieldOfView = 60; // 数值越大,视野越广

Q: 透视投影和正交投影有什么区别?

A:

  • 透视投影: 近大远小,符合真实视觉,适用于 3D 游戏
  • 正交投影: 无透视效果,大小不随距离变化,适用于 2D 游戏或编辑器
// 透视投影
camera.orthographic = false;

// 正交投影
camera.orthographic = true;
camera.orthographicVerticalSize = 10;

Q: 如何实现点击 3D 物体?

A: 使用射线检测:

Laya.stage.on(Laya.Event.MOUSE_DOWN, this, () => {
    const point = new Laya.Vector2(Laya.stage.mouseX, Laya.stage.mouseY);
    const ray = new Laya.Ray(new Laya.Vector3(), new Laya.Vector3());
    camera.viewportPointToRay(point, ray);

    const hitResult = new Laya.HitResult();
    scene.physicsSimulation.rayCast(ray, hitResult);

    if (hitResult.succeeded) {
        console.log("点击了:", hitResult.collider.owner.name);
    }
});

Q: 如何实现小地图?

A: 使用第二个摄像机配合正交投影和图层遮罩:

// 小地图摄像机
const miniMapCamera = new Laya.Camera();
miniMapCamera.orthographic = true;
miniMapCamera.orthographicVerticalSize = 50;
miniMapCamera.removeAllLayers();
miniMapCamera.addLayer(8);
scene.addChild(miniMapCamera);

Q: nearPlane 和 farPlane 如何设置?

A: 根据场景尺度设置:

// 室内小场景
camera.nearPlane = 0.1;
camera.farPlane = 100;

// 室外大场景
camera.nearPlane = 0.3;
camera.farPlane = 2000;

Q: Camera 与 BaseCamera 的区别?

A: Camera 继承自 BaseCamera,增加了更多渲染功能:

  • HDR 支持
  • 后期处理
  • 深度贴图模式
  • CommandBuffer 支持
  • 自定义渲染目标

版本: v3.3.7
文档生成时间: 2026-01-19

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐