虚幻引擎 C++ 实现平面阴影

1、平面阴影介绍

        平面阴影是一种相对简单的渲染阴影的方式,可以理解为对一个模型渲染两次,一次是渲染模型本身,另一次是渲染模型的投影。渲染投影可以看作是将模型的顶点变换到地面的投影空间再渲染,可以理解为渲染了一个“压扁”的模型。

        相对于shadowMap,平面阴影对性能的损耗相对较小。shadowMap相当于对场景做了两次渲染(第一次在光源位置渲染记录深度纹理,第二次正常渲染);而平面阴影只对模型本身做两次渲染。且shadowMap受限于深度纹理的分辨率,渲染出的阴影会出现锯齿;平面阴影由于阴影本身也是模型,故不会出现明显的锯齿。

        但是平面阴影不会在模型上产生阴影(如手臂遮住脸,脸上会有手臂的阴影);且只能投影在平面上(如果地面有其他模型,则阴影会被挡住)。

2、虚幻引擎实现平面阴影

2.1、实现思路

图2-1

        思路是将模型通过全局位置偏移的方式,变换到投影的位置。如图2-1,在光线light作用下,模型上的一点p投射的阴影为p'。我们要计算的是px到px'、py到py'以及pz到0的偏移。pz到0好处理,偏移为-pz。要计算px到px'、py到py',首先要得到图2-1中的L,设光线方向向量为lightDir(已单位化)。则点p到点p'的向量为K=L*lightDir,则px到px'的偏移为向量K的X分量、py到py'的偏移为向量K的Y分量。

2.1、材质

2.2、C++部分:动态加载模型、材质

        创建一个AMyActorShadow(继承AActor),作为平面阴影模型,添加与玩家控制人物相同的骨骼网格体,添加上平面阴影材质。然后在tick函数里获取玩家人物骨骼网格体的TransForm以及姿态,并更新至当前的骨骼网格体。代码如下:

	AMyActorShadow(){// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;//skeleMesh 为成员变量if (skeleMesh == nullptr) {// 实例化一个网格体skeleMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("mesh"));skeleMesh->SetupAttachment(RootComponent);static ConstructorHelpers::FObjectFinder<USkeletalMesh> locMesh(TEXT("玩家人物骨骼网格体的引用"));if (locMesh.Succeeded()) {skeleMesh->SetSkeletalMesh(locMesh.Object, false);}// 关闭阴影skeleMesh->SetCastShadow(false);static UMaterialInterface* MiniMapmatInst = LoadObject<UMaterialInterface>(NULL, TEXT("平面阴影材质的引用"));UMaterialInstanceDynamic* MiniMapmatInstDynamic = UMaterialInstanceDynamic::Create(MiniMapmatInst, nullptr);if (MiniMapmatInstDynamic != nullptr) {int matNum = skeleMesh->GetNumMaterials();for (int i = 0; i < matNum; i++) {skeleMesh->SetMaterial(i, MiniMapmatInstDynamic);}}}}

code2-1 构造函数

// Called every frame
void AMyActorShadow::Tick(float DeltaTime)
{Super::Tick(DeltaTime);USkeletalMeshComponent* source = nullptr;for (TActorIterator<AthridPersonCharacter> itr(GetWorld()); itr; ++itr){AthridPersonCharacter* master = *itr;master->GetTransform();source = itr->FindComponentByClass<USkeletalMeshComponent>();break;}if (source){// 同步位置和朝向this->SetActorTransform(source->GetComponentTransform());// 同步骨骼模型姿态skeleMesh->SetMasterPoseComponent(source);}
}

code2-2 tick事件

3、最终效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/397768.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux内核编程(十二)热插拔

本文目录 一、知识点1. 热插拔概念2. 热插拔机制3. Netlink机制 二、内核发送uevent事件到用户空间1. kobject发送uevent事件2. udevadm命令查看★示例代码&#xff1a;★优化&#xff1a;完善kset_uevent_ops&#xff08;热插拔事件结构体&#xff09; 三、用户空间使用Netlin…

Dubbo源码深度解析(四)

接上篇博客《Dubbo源码深度解析(三)》&#xff0c;上篇博文&#xff0c;主要讲的是DubboBootstrap#start()方法中调用到的其他方法&#xff0c;以及讲到ServiceConfig#export()方法的调用链路。其中讲到最核心的方法为ServiceConfig#doExportUrlsFor1Protocol()&#xff0c;还没…

CentOS7 配置 nginx 和 php 方案

配置方案 一、安装软件二、编写配置文件&#xff0c;连接PHP三、引用文件四、测试 鉴于网上教程错综复杂&#xff0c;写下一这篇文章 本教程只需要三步即可 一、安装软件 yum install -y nginx php php-fpm二、编写配置文件&#xff0c;连接PHP 一般情况下在安装完 nginx 后…

python-质因数分解(赛氪OJ)

[题目描述] 已知正整数 n 是两个不同的质数的乘积&#xff0c;试求出两者中较大的那个质数。输入格式&#xff1a; 输入一个正整数 n。输出格式&#xff1a; 输出一个正整数 p&#xff0c;即较大的那个质数。样例 #1样例输入 #1 21样例输出 #1 7提示&#xff1a; 1≤n≤2109 来…

无字母数字的绕过方法

php代码 <?phpif(isset($_GET[code])){$code $_GET[code];if(strlen($code)>35){die("Long.");}if(preg_match("/[A-Za-z0-9_$]/",$code)){die("NO.");}eval($code);}else{highlight_file(__FILE__);} 题目的限制&#xff1a; webshell…

书籍分享:【矩阵力量】豆瓣评分高达9.6,看完感叹《矩阵论》又白学了

书籍分享&#xff1a;【矩阵力量】豆瓣评分高达9.6&#xff0c;看完感叹《矩阵论》又白学了 《矩阵力量》简要介绍书籍下载链接 《矩阵力量》简要介绍 《矩阵力量》是姜伟生精心编写的线性代数的深度理解之作&#xff0c;作者将抽象的线性代数概念用通俗易懂的语言和大量生动形…

Windows下,C# 通过FastDDS高效通信

目录 1、安装FastDDS 库2、使用IDL定义自己的数据格式3、生成DLL3.1 托管 &#xff08;Managed&#xff09;模式3.2 非托管 &#xff08;Unmanaged&#xff09;模式 -- 可用于Unity 代码示例 eprosima Fast DDS is a C implementation of the DDS (Data Distribution Service) …

vscode用快捷键一键生成vue模板

项目中有些代码模块是固定的&#xff0c;如下面的代码所示&#xff0c;为了不重复写这些相同的代码&#xff0c;我们可以使用快键键一键生成模板。 流程&#xff1a; 中文&#xff1a;首选项-> 用户代码片段 -> 输入框中输入vue,找到vue.json文件&#xff08;没有vue.j…

Vue-07.生命周期

生命周期&#xff1a; 生命周期&#xff1a;指一个对象从创建到销毁的全过程 生命周期的八个阶段&#xff1a;每触发一个阶段&#xff0c;就会自动执行一个生命周期方法&#xff08;钩子方法&#xff09; 状态 阶段周期 beforeCreated 创…

内部排序(插入、交换、选择)

一、排序的部分基本概念 1. 算法的稳定性 若待排序表中有两个元素 Ri 和 Rj &#xff0c;其对应的关键字相同即 keyi keyj&#xff0c;且在排序前 Ri 在 Rj 的前面&#xff0c;若使用某一排序算法排序后&#xff0c;Ri 仍然在 Rj 的前面&#xff0c;则称这个排序算法是稳定的…

【MySQL】详解数据库约束、聚合查询和联合查询

数据库约束 约束类型 数据库的约束类型主要包括以下几种&#xff1a; 主键约束&#xff08;Primary Key Constraint&#xff09;&#xff1a;确保表中的每一行都有唯一的标识&#xff0c;且不能为NULL。 外键约束&#xff08;Foreign Key Constraint&#xff09;&#xff1a…

5.ADC(模拟信号转数字信号)

理论 3个ADC控制器 转换&#xff1a;单次转换模式、 连续转换模式 转换时间 采样时间 12.5周期 当ADCCLK(时钟) 14MHz&#xff0c;采样时间为1.5周期&#xff0c;TcoNv(转换时间) 1.5 12.5 14 周期 1us 采样精度&#xff1a;12位/16位(212 4096) 实际电压值 (通道采…

Java面试题--JVM大厂篇之破解 JVM 性能瓶颈:实战优化策略大全

目录 引言: 正文: 1. 常见的JVM性能问题 频繁的GC导致应用暂停 内存泄漏导致的内存不足 线程争用导致的CPU利用率过高 类加载问题导致的启动时间过长 2. 优化策略大全 2.1 代码层面的优化 2.1.1 避免不必要的对象创建 2.1.2 优化数据结构的选择 2.1.3 使用并发工具…

Python爬虫:下载4K壁纸

&#x1f381;&#x1f381;创作不易&#xff0c;关注作者不迷路&#x1f380;&#x1f380; 目录 &#x1f338;完整代码 &#x1f338;分析 &#x1f381;基本思路 &#x1f381;需要的库 &#x1f381;提取图片的链接和标题 &#x1f453;寻找Cookie和User-Agent &…

突破•指针六

听说这是目录哦 数组和指针笔试题解析&#x1fae7;一维数组1&#x1f355;&#x1f355;&#x1f355;&#x1f355;&#x1f355;&#x1f355;&#x1f355; 字符数组1&#x1f354;&#x1f354;&#x1f354;&#x1f354;&#x1f354;&#x1f354;&#x1f354;2&#…

PCL 采样一致性模型介绍

采样一致性可以简单高效的检测出一些具有数学表达式的目标模型。PCL中的sample consensus模块中不仅包含各种的采样一致性估计方法,也包含一些已经编写好的数学模型,下面主要介绍一下PCL中的采样一致性模型。 1. 二维圆模型 pcl::SampleConsensusModelCircle2D< PointT …

AI学习记录 - 自注意力机制的计算流程图

画图不易&#xff0c;如果你从这个图当中得到灵感&#xff0c;大佬赏个赞 过段时间解释一下&#xff0c;为啥这样子计算&#xff0c;研究这个自注意力花了不少时间&#xff0c;网上很多讲概念&#xff0c;但是没有具体的流程图和计算方式总结…

Win11表情符号输入详细教程,一学就会!

在Win11电脑操作中&#xff0c;用户可以根据自己的需求&#xff0c;点击输入想要的表情符合。但许多新手用户不知道怎么操作才能输入&#xff1f;这时候用户按下快捷键&#xff0c;快速打开表情符号选择界面&#xff0c;然后选择需要的表情符号点击输入即可。以下系统之家小编给…

Can GPT-3 Perform Statutory Reasoning?

文章目录 题目摘要相关工作SARAGPT-3 对美国法典的了解GPT-3 在对合成法规进行简单推理时遇到困难结论 题目 GPT-3 可以进行法定推理吗&#xff1f; 论文地址&#xff1a;https://arxiv.org/abs/2302.06100 摘要 法定推理是用事实和法规进行推理的任务&#xff0c;法规是立法机…

Linux嵌入式学习——C++学习(2)

一、标识符的作用域和可见性 &#xff08;一&#xff09;作用域 1、全局作用域 在函数外部声明的变量和函数具有全局作用域。这些变量和函数在程序的任何地方都可以被访问。 2.局部作用域 在函数内部、循环体内部或条件语句内部声明的变量具有局部作用域。这些变量只能在其…