You need to enable JavaScript to run this app. 如何调整Scene Kit相机主点,实现移轴/透视控制镜头模拟效果?
优惠活动
大模型
产品
解决方案
定价
更多

如何调整Scene Kit相机主点,实现移轴/透视控制镜头模拟效果?

SceneKit实现透视控制(移轴)镜头偏移效果解决方案

核心实现思路

SCNCamera没有提供直接的镜头偏移参数,我们可以通过自定义投影矩阵或者相机平移+视口偏移两种方案实现,两种方案都可以保证被拍摄物体相对相机的位置不变,不会出现位移问题。

方案1:自定义投影矩阵实现(最稳定,推荐)

这个方案直接修改透视投影的平截头体边界,和Unity的lensShift实现原理完全一致,不需要改变相机的位置和朝向。
首先给出投影矩阵计算工具函数:

import SceneKit
import simd

/// 生成带镜头偏移的透视投影矩阵
/// - Parameters:
///   - camera: 目标SCNCamera对象,需要提前配置好FOV、zNear、zFar参数
///   - viewSize: 当前SCNView的视图尺寸
///   - shiftX: X轴镜头偏移,取值范围建议[-0.5, 0.5]
///   - shiftY: Y轴镜头偏移,取值范围建议[-0.5, 0.5]
/// - Returns: 带偏移的投影矩阵
func shiftedProjectionMatrix(camera: SCNCamera, viewSize: CGSize, shiftX: CGFloat, shiftY: CGFloat) -> SCNMatrix4 {
    let fovRadian = camera.fieldOfView * .pi / 180
    let aspectRatio = viewSize.width / viewSize.height
    let nearPlane = camera.zNear
    let farPlane = camera.zFar
    
    // 计算基础平截头体边界
    let top = nearPlane * tan(fovRadian / 2)
    let bottom = -top
    let right = top * aspectRatio
    let left = -right
    
    // 应用偏移量
    let shiftedLeft = left - shiftX * top * 2
    let shiftedRight = right - shiftX * top * 2
    let shiftedTop = top - shiftY * top * 2
    let shiftedBottom = bottom - shiftY * top * 2
    
    // 生成自定义透视矩阵
    return SCNMatrix4MakeFrustum(Float(shiftedLeft), Float(shiftedRight), Float(shiftedBottom), Float(shiftedTop), Float(nearPlane), Float(farPlane))
}

使用步骤:

  • 关闭相机自动投影调整,避免系统覆盖自定义矩阵
let camera = SCNCamera()
// 配置基础相机参数
camera.fieldOfView = 60
camera.zNear = 0.1
camera.zFar = 1000
// 关闭自动投影,必须配置否则自定义矩阵会被覆盖
camera.automaticallyAdjustsProjection = false
  • 按需更新偏移矩阵,视图尺寸变化时也需要重新调用更新
// 示例:仰视高层建筑时向上偏移0.2,消除下大上小的透视畸变
let shiftX: CGFloat = 0
let shiftY: CGFloat = 0.2
camera.projectionTransform = shiftedProjectionMatrix(
    camera: camera, 
    viewSize: scnView.bounds.size, 
    shiftX: shiftX, 
    shiftY: shiftY
)

方案2:相机平移+视口偏移等效方案

如果你不想修改投影矩阵,可以用这个等效方案:
镜头向上偏移等价于相机向下平移对应距离,再调整视口的Y轴偏移把画面拉回中心,保证被拍摄物体居中
代码示例:

// 等效Y轴偏移0.2的效果
let shiftY: CGFloat = 0.2
// 1. 相机反向平移
cameraNode.position.y -= shiftY * 2
// 2. 调整视口偏移,把目标物体拉回画面中心
camera.viewport = CGRect(x: 0, y: -shiftY, width: 1, height: 1)

注意事项

  • 偏移量shiftX和shiftY的建议取值区间为[-0.5, 0.5],超过1会导致画面完全移出视口
  • 如果是正交相机,只需要修改上述矩阵计算逻辑中的FOV部分为正交缩放值即可,逻辑和透视相机一致
  • 如果需要做偏移动画,可以对偏移值做属性动画,每次动画帧更新时重新计算投影矩阵即可

内容的提问来源于stack exchange,提问作者Andrew Chinery

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 05:00:05