Unity手册精读系列---Camera相关

视锥体

  • 反映透视摄像机可渲染空间的大小形状
  • 透视摄像机的视锥体由Camera Component中的Clipping Planes裁剪平面距(即近裁剪面和远裁剪面)FOV视野来决定大小形状!
  • 视锥体剔除:摄像机视锥体范围外的所有物体都不可见(即不被摄像机所渲染)!摄像机只渲染视锥体范围内的物体!

从屏幕顶部和底部中心聚合到透视中心处的线所形成的角度称为视野(通常缩写为 FOV)。
启用 Physical Camera 属性后,Unity 将使用模拟真实摄像机属性的属性(Focal Length、Sensor Size 和 Lens Shift)计算 Field of View
在这里插入图片描述

视锥体的成像原理:

在这里插入图片描述
如果杆正对摄像机镜头,那么只有其一端可在画面中显示为圆圈;所有其他部分都会被遮挡。如果将杆向上移动,下侧将开始变得可见,但可通过向上倾斜杆再次将其隐藏。如果继续向上移动杆并进一步将其向上倾斜,则杆的末端最终将超出摄像机视锥体范围,此时就会由摄像机进行裁剪超出的部分,保留未超出的部分。

使用斜视锥体(设置视锥体倾斜):

默认情况下,视锥体围绕摄像机的水平中心线对称安放。

但如果视锥体一侧与中心线的角度不等于对侧与中心线的角度,此时认为视锥体是“倾斜的”,即为斜视锥体!。
斜视锥体

为什么要使用斜视锥体?(斜视锥体的视觉效果)

通过设置斜视锥体,使得摄像机所拍摄的画面更贴近斜视锥体平缓的一侧!
例如,在赛车游戏中,画面更靠近地面可以增加速度感!

如何设置斜视锥体?
  1. 通过物理摄像机Lens Shift镜头偏移可以设置视锥体倾斜!
    在这里插入图片描述

物理摄像机的Lens Shift镜头偏移的功能:

  • 优点:
    通过物理摄像机沿水平方向/垂直方向偏移镜头进行观察物体,可以避免原地旋转摄像机来观察水平方向上/垂直方向上的物体时所带来的“水平线会聚现象”(透视视角的特点),从而避免画面失真!
  • 缺点:
    减弱了真实观察世界的近大远小的真实感。
  • 副作用:使视锥体倾斜!

2.通过脚本设置视锥体倾斜

以下脚本示例显示了如何通过更改摄像机的投影矩阵来快速实现斜视锥体。请注意,仅当游戏运行播放模式时才能看到脚本的效果。

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    void SetObliqueness(float horizObl, float vertObl) {
        Matrix4x4 mat  = Camera.main.projectionMatrix;
        mat[0, 2] = horizObl;
        mat[1, 2] = vertObl;
        Camera.main.projectionMatrix = mat;
    }
} 

C# 脚本示例

没有必要了解投影矩阵如何使用它。horizObl 和 vertObl 值分别设置水平和垂直倾斜量。值为零表示无倾斜。正值使视锥体向右或向上移动,从而使左边或底边变平。负值使视锥体向左或向下移动,从而使视锥体的右边或顶边变平。如果将此脚本添加到摄像机并在游戏运行时将游戏切换到 Scene 视图,则可以直接看到效果;在检视面板中改变 horizObl 和 vertObl 的值时,摄像机视锥体的线框会发生变化。任一变量中的值为 1 或 –1 表示视锥体的一侧与中心线完全齐平。此范围之外的值也是允许使用的,但通常没有必要。

物理摄像机Lens Shift镜头偏移的效果:

镜头水平偏移前:
在这里插入图片描述
镜头水平偏移后:
在这里插入图片描述
镜头垂直偏移前:
在这里插入图片描述
镜头垂直偏移后:
在这里插入图片描述

摄像机射线

摄像机所渲染画面中的任何一点都可对应于世界空间中的一条线!
在这里插入图片描述

如何生成摄像机射线?

摄像机对象提供 ScreenPointToRay 和 ViewportPointToRay 函数来生成摄像机射线。
摄像机射线源自视锥体的近裁剪面而不是摄像机的 transform.position 点
注意:生成摄像机射线时所用的点的坐标时Vector3类型!

  • 通过摄像机对象的ScreenPointToRay()函数根据屏幕上的像素点坐标生成摄像机射线!
    屏幕坐标范围屏幕的左下角为 (0,0),右上角为 (pixelWidth -1,pixelHeight -1)。
Ray ray = Camera.main.ScreenPointToRay(Input.mouseposition);
Debug.DrawRay(ray.origin, ray.direction * 10, Color.yellow);
  • 通过摄像机对象的ViewportPointToRay()函数根据基于摄像机的标准化的视口坐标生成摄像机射线!
    视口坐标的范围:摄像机左下角为 (0,0),右上角为 (1,1)。
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
	print("I'm looking at " + hit.transform.name);
else
    print("I'm looking at nothing!");

摄像机射线的应用案例:

1. 基于屏幕定位世界空间中对象的的方法:摄像机射线+射线检测

使用Physics.Raycast(Ray ray,out hit)将指定射线ray用于射线(投射)检测,判断是否有命中其他碰撞器Collider,若命中则返回包含该碰撞器的相关信息的RaycastHit类对象hit。

 void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            print(Input.mousePosition);
            Ray cameraray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(cameraray, out hit))
            {
            print(hit.collider.gameObject.name+Input.mousePosition+"/"+hit.collider.transform.position);
            }
        }
    }
2. 沿射线移动摄像机:
void Update()
{
	Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    float zoomDistance = zoomSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
    Camera.main.transform.Translate(ray.direction * zoomDistance, Space.World);
}

使用多个摄像机

使用多个摄像机渲染画面时的基本原则:

深度优先原则深度值高的摄像机会将深度值低的摄像机所渲染的画面进行覆盖!相同深度值的多个摄像机渲染画面随机相互覆盖!

如何避免相同Depth深度值的摄像机渲染画面的相互覆盖可以考虑Camera Component中的Clear Flags属性值为Depth Only以及设置Culling Mask属性!

主摄像机如何唯一确定?

通过标签名MainCamera来指定主摄像机!

画中画效果的实现:

  • 多台摄像机具有不同深度值Depth(同一深度值摄像机渲染画面会相互覆盖!);
  • 通过摄像机Viewport Rect属性确定各个摄像机渲染画面在屏幕上(Game窗口)的位置和大小。

例如,在驾驶游戏中显示一个后视镜,或者在第一人视角的屏幕角落里显示俯瞰小地图。

摄像机镜头切换效果的实现:

在脚本中禁用一个摄像机并启用另一个,即可从一个摄像机的镜头切换到另一个,从而得到场景的多个镜头画面。

在某些情况下,例如要在俯瞰地图视角和第一人称视角之间切换时,就可以采用这种方法。

Camera组件的相关属性

Unity 项目使用的渲染管线不同,在 Camera组件的属性也将不同。
如果您的项目使用内置渲染管线,Camera组件会显示以下属性:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Clear Flags属性:

每个摄像机在渲染其视图时都会存储颜色和深度信息。屏幕中未绘制的部分为空,默认情况下将显示天空盒。使用多个摄像机时,每个摄像机都会在缓冲区中存储自己的颜色和深度信息,随着每个摄像机渲染而累积越来越多数据。场景中的任何特定摄像机渲染其视图时,您可以设置 Clear Flags 来清除不同的缓冲区信息集合。为此,请选择以下四个选项之一:

  • Skybox
    这是默认设置。屏幕的任何空白部分都将显示当前摄像机的天空盒。如果当前摄像机没有设置天空盒,它将默认为在 Lighting 窗口(菜单:Window> Rendering > Lighting)中选择的天空盒。或者,可将 Skybox 组件添加到摄像机。

  • Solid color
    屏幕的任何空白部分都将显示指定的Background背景颜色。

  • Depth only
    当有多台摄像机进行游戏场景的拍摄时,尤其是同一块场景的拍摄,可以通过“深度高的摄像机将深度低的摄像机拍摄的场景覆盖”。对于深度高的摄像机可以渲染UI界面,并将其Clear Flags设置为Depth Only(具有只画当层,背景透明的效果)避免原先摄像机拍摄场景被覆盖!
    如果要绘制玩家的枪支而不使其陷入环境中,可以设置一个深度 (Depth)为 0 的摄像机来绘制环境,并设置另一个深度为 1 的摄像机来单独绘制武器((单独绘制就意味着使用Culling Mask实现单独渲染该层)。将武器摄像机的 Clear Flags 设置为 Depth Only。绘制枪支时,无论枪支与墙壁的接近程度如何都能完整绘制该枪支。

例如:环境摄像机专门渲染环境(设置了Culling Mask),特用摄像机专门渲染该红色长方体(设置了Culling Mask)。
在这里插入图片描述
特用摄像机使用了Clear Flags的Depth Only属性后的最终效果呈现:
在这里插入图片描述

  • Don’t clear
    此模式不会清除颜色或深度缓冲区。结果是将每帧绘制在下一帧之上,从而产生涂抹效果。此模式通常不用于游戏,更可能与自定义着色器一起使用。
    请注意,在某些 GPU(主要是移动端 GPU)上,不清除屏幕可能会导致其内容在下一帧中未定义。在某些系统上,屏幕可能包含前一帧图像、纯黑色屏幕或随机有色像素。

Target Texture属性:

用来指定摄像机使用的Render Texture渲染纹理,将摄像机所拍摄的画面用作渲染纹理,从而当作常规纹理贴图使用!比如用作材质的纹理贴图。
可以实现监控室的监控记录效果!
以下摄像机所拍摄的场景用作Render Texture渲染纹理:
在这里插入图片描述
该Render Texture渲染纹理用作Material材质的纹理贴图,平面使用了该材质的最终效果呈现:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值