2021SC@SDUSC
目录
Camera
1.矩阵计算
1.1CalculateProjectionMatrix
1.2CalculateViewMatrix
2.Cache函数
本节我们来讨论游戏引擎中一个很重要的内容camera(摄像机),在了解相关的代码时,我们需要用到OvTools函数库中的工具,可点击ReferenceOrValue 前往了解。
Camera类中包含的成员变量较多,大多数数据类型都已在前文提到,例如m_frustum(视锥体对象)、m_viewMatrix(观察矩阵)、m_projectionMatrix(投影矩阵)、m_projectionMode(投影模式,分为ORTHOGRAPHIC(正交投影)与PERSPECTIVE(透视投影),见OvRendering::Settings::EProjectionMode 文件)。
class Camera
{
private:
OvRendering::Data::Frustum m_frustum;
OvMaths::FMatrix4 m_viewMatrix;
OvMaths::FMatrix4 m_projectionMatrix;
OvRendering::Settings::EProjectionMode m_projectionMode;
float m_fov;
float m_size;
float m_near;
float m_far;
OvMaths::FVector3 m_clearColor;
bool m_frustumGeometryCulling;
bool m_frustumLightCulling;
};
除了以上特殊类型的变量外,还有m_fov(视角范围)、m_size(正交投影时视角立方体的边长)、m_near\m_far(摄像机到近\远平面)、m_几何集合剔除)、m_frustumLightCulling(是否进行视锥体灯光剔除)。
接下来大致浏览一遍相关的函数:
public:
Camera();
void CacheMatrices(uint16_t p_windowWidth, uint16_t p_windowHeight, const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation);
void CacheProjectionMatrix(uint16_t p_windowWidth, uint16_t p_windowHeight);
void CacheViewMatrix(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation);
void CacheFrustum(const OvMaths::FMatrix4& p_view, const OvMaths::FMatrix4& p_projection);
float GetFov() const;
float GetSize() const;
float GetNear() const;
float GetFar() const;
const OvMaths::FVector3& GetClearColor() const;
const OvMaths::FMatrix4& GetProjectionMatrix() const;
const OvMaths::FMatrix4& GetViewMatrix() const;
const OvRendering::Data::Frustum& GetFrustum() const;
bool HasFrustumGeometryCulling() const;
bool HasFrustumLightCulling() const;
OvRendering::Settings::EProjectionMode GetProjectionMode() const;
void SetFov(float p_value);
void SetSize(float p_value);
void SetNear(float p_value);
void SetFar(float p_value);
void SetClearColor(const OvMaths::FVector3& p_clearColor);
void SetFrustumGeometryCulling(bool p_enable);
void SetFrustumLightCulling(bool p_enable);
void SetProjectionMode(OvRendering::Settings::EProjectionMode p_projectionMode);
private:
OvMaths::FMatrix4 CalculateProjectionMatrix(uint16_t p_windowWidth, uint16_t p_windowHeight) const;
OvMaths::FMatrix4 CalculateViewMatrix(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation) const;
以上函数中包含着大量set与get函数,即对成员变量赋值与取值,这里就不作介绍,接下来我们一一来看几个关键的函数。
OvMaths::FMatrix4 OvRendering::LowRenderer::Camera::CalculateProjectionMatrix(uint16_t p_windowWidth, uint16_t p_windowHeight) const
{
using namespace OvMaths;
using namespace OvRendering::Settings;
const auto ratio = p_windowWidth / static_cast(p_windowHeight);
switch (m_projectionMode)
{
case EProjectionMode::ORTHOGRAPHIC:
return FMatrix4::CreateOrthographic(m_size, ratio, m_near, m_far);
case EProjectionMode::PERSPECTIVE:
return FMatrix4::CreatePerspective(m_fov, ratio, m_near, m_far);
default:
return FMatrix4::Identity;
}
}
CalculateProjectionMatrix函数用于计算当前摄像机的投影矩阵,需要传入的参数是投影窗口的宽度和高度。
首先我们利用窗口的宽高计算宽高比,这里为了使比值的结果为浮点数,需要对宽高做强制类型转换。接下来根据自身的m_projectionMode变量进行分类,对应不同的投影模式调用创建函数,创建函数详见【Overload游戏引擎】源码分析之二:OvMaths函数库(下)。
OvMaths::FMatrix4 OvRendering::LowRenderer::Camera::CalculateViewMatrix(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation) const
{
const auto& up = p_rotation * OvMaths::FVector3::Up;
const auto& forward = p_rotation * OvMaths::FVector3::Forward;
return OvMaths::FMatrix4::CreateView
(
p_position.x, p_position.y, p_position.z, // Position
p_position.x + forward.x, p_position.y + forward.y, p_position.z + forward.z, // LookAt (Position + Forward)
up.x, up.y, up.z // Up Vector
);
}
观察矩阵的计算与上述类似,需要传入当前摄像机的世界坐标以及对应的旋转变量,这里需要使用OvMaths中定义的默认摄像机的up向量与forward向量,并对其进行旋转变换,最后调用创建函数获得观察矩阵。
void OvRendering::LowRenderer::Camera::CacheMatrices(uint16_t p_windowWidth, uint16_t p_windowHeight, const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation)
{
CacheProjectionMatrix(p_windowWidth, p_windowHeight);
CacheViewMatrix(p_position, p_rotation);
CacheFrustum(m_viewMatrix, m_projectionMatrix);
}
void OvRendering::LowRenderer::Camera::CacheProjectionMatrix(uint16_t p_windowWidth, uint16_t p_windowHeight)
{
m_projectionMatrix = CalculateProjectionMatrix(p_windowWidth, p_windowHeight);
}
void OvRendering::LowRenderer::Camera::CacheViewMatrix(const OvMaths::FVector3& p_position, const OvMaths::FQuaternion& p_rotation)
{
m_viewMatrix = CalculateViewMatrix(p_position, p_rotation);
}
void OvRendering::LowRenderer::Camera::CacheFrustum(const OvMaths::FMatrix4& p_view, const OvMaths::FMatrix4& p_projection)
{
m_frustum.CalculateFrustum(p_projection * p_view);
}
以上函数完成了对摄像机的所有变换矩阵的赋值,包括投影矩阵、观察矩阵与视锥体变换矩阵,其中涉及的图形学原理已在前文讨论过,相关内容详见【Overload游戏引擎】源码分析之二:OvMaths函数库(下)。