UE Gameplay入门51(相机视锥空间的计算方法推导)

news/2024/11/7 15:01:48/

非常感谢匿名大哥一直对我的支持,本文内容由他赞助
在这里插入图片描述


#1. 视锥(Frustum)是什么
在这里插入图片描述
在相机的近裁剪面和远裁剪面之间的渲染范围内的空间叫做视锥空间(Frustum),通常情况下我们是不需要处理,但
当下比较流行动态遮挡剔除技术,只渲染视锥空间里面物体,再配合LOD等级来最大化效果,可以最小使用设备机能
Unity的FOV和Unreal的FOV有些区别
Unity的FOV是指视锥空间的张开角度,好比人眼睛的开闭角度
Unreal的FOV是指视锥空间的范围角度,基于水平面来伸开的


#2. 计算视锥需要的参数
在这里插入图片描述
相机自身的2个参数:FieldOfView(FOV)和Aspect Ratio宽高比
在这里插入图片描述
一般情况下还需要配合摇臂一起使用,Target Arm Length
CameraSpringArm默认延展的长度是反向距离,所以需要减掉forward反向的摇臂长度


#3. 计算方法
在这里插入图片描述
使用0为原点,视角FOV为90度,摇臂300米来进行推导
第一个有效计算三角形,图中绿色部分
一个角是90度,另外一个角度是45度的等腰三角形
这是视锥空间中有效的计算三角形,总计2个可用,分别位于左右两边,我们已知了一个角度和一条边

因为视锥空间是真3维空间,完全是在空间中计算的,通常情况下3维度空间的计算我们可以转为
2维空间来处理,比如玩家移动,此时朝上的轴向是固定的
在完全3维空间中计算,我们需要找投影,只有投影的向量才是有效的(相机也是投影成像)
找投影需要找一个可靠的平面来进行投影,需要是相互垂直的平面,可以构成勾股定律

计算一个有效中心点
在这里插入图片描述

原点:(0,0,0)
理论点:(300,300,0) - 摇臂(300,0,0)
未知中心点:(0, 300, 0)

在这里插入图片描述

获取相机的宽高比aspect ratio:1.5 width/height
300/1.5 = 200
未知顶点1:(0,300,200)
未知顶点1:(0,300,-200)


#4. 显示相机的视锥空间
有两种方法可以显示相机的视锥空间,编辑器显示或者代码显示
> 编辑器显示
在这里插入图片描述

> 使用UDrawFrustumComponent来显示

DrawFrustum = CreateDefaultSubobject<UDrawFrustumComponent>(TEXT("DrawFrustum"));
DrawFrustum->SetupAttachment(CameraBoom, USpringArmComponent::SocketName);
DrawFrustum->FrustumAspectRatio = FollowCamera->AspectRatio;
DrawFrustum->FrustumAngle = FollowCamera->FieldOfView;
DrawFrustum->FrustumStartDist = 10.0f;
DrawFrustum->FrustumEndDist = 1010.0f;

代码显示的好处是可以在任意位置显示,编辑器默认跟随相机显示


#5. 代码绘制DebugLine
在绘制之前,我也不知道能不在空间中把相机的视锥边缘绘制出来,最关键的是如果我们不做,
那么功能一定是不能完成的,因此我们应该尝试迈出第一步,其中有3种常见情况,
分别是镜头默认在原点,镜头往上移动,镜头往下移动
> 镜头默认在原点
在这里插入图片描述
这种情况下,我们可以直接计算

//lv1.在原点,无旋转最简单的情况下
//1.通过角度计算对边(半边)
//2.通过比例计算上下顶点
//3.计算其余的两点
void AViewFrustumCharacter::DrawFrustumPlane(float Dist)
{float Angle = FollowCamera->FieldOfView / 2;float ToRadians = FMath::DegreesToRadians(Angle);float Tan = FMath::Tan(ToRadians);float HalfWidth = Tan * Dist;float AspectRatio = FollowCamera->AspectRatio;float HalfHeight = HalfWidth / AspectRatio;GLog->Logf(TEXT("Tan:%f Angle:%f HalfWidth:%f HalfHeight:%f"), Tan, Angle, HalfWidth, HalfHeight);FVector RightUpPoint = FVector(0, HalfWidth, HalfHeight);FVector RightBottomPoint = FVector(0, HalfWidth, -HalfHeight);FVector LeftUpPoint = FVector(0, -HalfWidth, HalfHeight);FVector LeftBottomPoint = FVector(0, -HalfWidth, -HalfHeight);DrawDebugLine(GetWorld(), RightUpPoint, RightBottomPoint, FColor::Green, true, -1, 0, 5);DrawDebugLine(GetWorld(), LeftUpPoint, LeftBottomPoint, FColor::Green, true, -1, 0, 5);DrawDebugLine(GetWorld(), LeftUpPoint, RightUpPoint, FColor::Green, true, -1, 0, 5);DrawDebugLine(GetWorld(), LeftBottomPoint, RightBottomPoint, FColor::Green, true, -1, 0, 5);
}

> 镜头左右有旋转
在这里插入图片描述
这种情况下,需要计算旋转之后的偏移,我们可以直接使用集成的API来计算
我直接在Google上找到了解决办法
在这里插入图片描述

//lv2.相机有旋转,只有左右旋转的情况下
void AViewFrustumCharacter::DrawFrustumPlaneEx1(float Dist)
{float Angle = FollowCamera->FieldOfView / 2;float ToRadians = FMath::DegreesToRadians(Angle);float Tan = FMath::Tan(ToRadians);float HalfWidth = Tan * Dist;float AspectRatio = FollowCamera->AspectRatio;float HalfHeight = HalfWidth / AspectRatio;GLog->Logf(TEXT("Tan:%f Angle:%f HalfWidth:%f HalfHeight:%f"), Tan, Angle, HalfWidth, HalfHeight);FVector RightUpPoint = FVector(0, HalfWidth, HalfHeight);FVector RightBottomPoint = FVector(0, HalfWidth, -HalfHeight);FVector LeftUpPoint = FVector(0, -HalfWidth, HalfHeight);FVector LeftBottomPoint = FVector(0, -HalfWidth, -HalfHeight);FRotator Rotation = GetActorRotation();FVector EulerAngle = Rotation.Euler();FVector NewRightUpPoint = RightUpPoint.RotateAngleAxis(EulerAngle.Z, FVector::UpVector);FVector NewRightBottomPoint = RightBottomPoint.RotateAngleAxis(EulerAngle.Z, FVector::UpVector);FVector NewLeftUpPoint = LeftUpPoint.RotateAngleAxis(EulerAngle.Z, FVector::UpVector);FVector NewLeftBottomPoint = LeftBottomPoint.RotateAngleAxis(EulerAngle.Z, FVector::UpVector);DrawDebugLine(GetWorld(), NewRightUpPoint, NewRightBottomPoint, FColor::Black, true, -1, 0, 5);DrawDebugLine(GetWorld(), NewLeftUpPoint, NewLeftBottomPoint, FColor::Black, true, -1, 0, 5);DrawDebugLine(GetWorld(), NewLeftUpPoint, NewRightUpPoint, FColor::Black, true, -1, 0, 5);DrawDebugLine(GetWorld(), NewLeftBottomPoint, NewRightBottomPoint, FColor::Black, true, -1, 0, 5);
}

> 镜头上下有旋转
在这里插入图片描述
上下旋转的时候,是反方向进行的

void AViewFrustumCharacter::DrawFrustumPlaneEx2(float Dist)
{float Angle = FollowCamera->FieldOfView / 2;float ToRadians = FMath::DegreesToRadians(Angle);float Tan = FMath::Tan(ToRadians);float HalfWidth = Tan * Dist;float AspectRatio = FollowCamera->AspectRatio;float HalfHeight = HalfWidth / AspectRatio;GLog->Logf(TEXT("Tan:%f Angle:%f HalfWidth:%f HalfHeight:%f"), Tan, Angle, HalfWidth, HalfHeight);FVector RightUpPoint = FVector(0, HalfWidth, HalfHeight);FVector RightBottomPoint = FVector(0, HalfWidth, -HalfHeight);FVector LeftUpPoint = FVector(0, -HalfWidth, HalfHeight);FVector LeftBottomPoint = FVector(0, -HalfWidth, -HalfHeight);FRotator Rotation = GetActorRotation();FVector EulerAngle = Rotation.Euler();// 上下的旋转是默认取反,下显示往上,上显示往下FVector NewRightUpPoint = RightUpPoint.RotateAngleAxis(-EulerAngle.Y, FVector::RightVector);FVector NewRightBottomPoint = RightBottomPoint.RotateAngleAxis(-EulerAngle.Y, FVector::RightVector);FVector NewLeftUpPoint = LeftUpPoint.RotateAngleAxis(-EulerAngle.Y, FVector::RightVector);FVector NewLeftBottomPoint = LeftBottomPoint.RotateAngleAxis(-EulerAngle.Y, FVector::RightVector);DrawDebugLine(GetWorld(), NewRightUpPoint, NewRightBottomPoint, FColor::Purple, true, -1, 0, 5);DrawDebugLine(GetWorld(), NewLeftUpPoint, NewLeftBottomPoint, FColor::Purple, true, -1, 0, 5);DrawDebugLine(GetWorld(), NewLeftUpPoint, NewRightUpPoint, FColor::Purple, true, -1, 0, 5);DrawDebugLine(GetWorld(), NewLeftBottomPoint, NewRightBottomPoint, FColor::Purple, true, -1, 0, 5);
}


http://www.ppmy.cn/news/206450.html

相关文章

UE5 受击方位提示功能

概述&#xff1a; 很多射击游戏都有用箭头提示敌人&#xff08;受击&#xff09;方向的功能&#xff0c;比如CS中受到伤害是的六方提示。 笔者在开发DEMO的过程中&#xff0c;研究了类似功能&#xff0c;本文主要总结在制作全方向方位提示时的开发思路。 知识储备&#xff1a…

【虚幻】过场动画笔记

1.添加关卡序列 添加后场景里会出现这个标识&#xff0c;打开关卡序列。 在这个选项卡里编辑动画。 2.摄像机 添加摄像机Actor&#xff0c;根据选择添加摇臂/导轨。 按住Alt移动&#xff0c;可延伸导轨。 在大纲中将摄像机移入导轨&#xff0c;导轨成为摄像机父类。摄像…

【UE4学习】5.相机和蓝图进阶

文章目录 相机基础Project Setting控制输入按键事件控制相机设置追踪目标CameraManager实现相机切换API接口与多态蓝图之间的通信方式GameModeManager显示当前相机信息事件调度器Sequencer入门遗留问题 相机基础 UE4中的相机主要包括普通相机Camera、电影相机Cine Camera、摇臂…

Unity3D学习日记(二)使用UGUI制作虚拟摇杆控制摄像机

前天撸了一个简单的UGUI虚拟摇杆&#xff0c;今天我就利用前天做的虚拟摇杆做了一个简单的摄像机控制器&#xff0c;主要看看UGUI虚拟摇杆是否可以完美的控制移动和旋转。&#xff08;PS&#xff1a;主要是为接下来的项目做技术测试&#xff09;&#xff0c;手游版的CF的角色控…

UE4基础,Actor设置与摄像机SpringArm添加

基础知识整理 Uobject子类蓝图的创建 //.h UCLASS(Blueprintable) //使其能在UE中可被蓝图继承&#xff0c;反射系统 class PROJECT01_API UMyobject : public UObject {GENERAtED_BODY() public:UMyobject();//不参与反射系统UPROPERTY(BlueprintReadWrite&#xff0c; Cate…

(52)组件之摄像机组件

CameraComponent &#xff08;添加一个摄像机视角&#xff09;和 SpringArmComponent &#xff08;使其子项延长固定距离&#xff0c;然后在发生碰撞时收回&#xff09;&#xff0c;这两个组件一起使用&#xff0c;可提供一个第三人称视角&#xff0c;您可在游戏世界中对其进行…

UE4学习总结(5) 相机基础

UE4学习总结&#xff08;5&#xff09; 相机基础 相机种类控制自由相机定义Input事件配置各个按键的控制效果转换到相机的视角 控制摇臂相机摇臂相机搭载子相机配置各个按键的控制效果 控制滑轨相机滑轨相机搭载子相机控制相机位置控制滑轨相机对准目标转换到相机的视角 控制多…

时光剪影

关于我们 成都时光剪影文化传播有限公司&#xff0c;简称SGJY&#xff0c;是中国一家影视制作机构&#xff0c;总部位于成都。 SGJY&#xff08;时光剪影&#xff09;主要致力于服务全球影视制作业务&#xff0c;涵盖广告片、创意视频短片、强传播型微电影、宣传片、新型教学片…