格格她爹讲程序---用传统程序员的方式玩UE4(三)

2024-04-11 02:32

本文主要是介绍格格她爹讲程序---用传统程序员的方式玩UE4(三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

格格她爹讲程序---用传统程序员的方式玩UE4(三)

 

最近经常有人问我,什么时候出下一章,我觉得还是很高兴的,至少我写的东西得到了认可,但是我也要向大家说明一下,毕竟我现在还有工作,平时工作很忙,所以只能通过闲暇的时间来写,上次的两篇就是在出差的高铁上完成的。

上一章的一个典型应用其实只是为了让大家尽快出点“成绩”,好对UE4的代码开发有点兴趣,这次我们继续回到正规,先从UE4的基本渲染说起。

在第一章里我们也讲过了,渲染是显示平台的核心,所以渲染的代码肯定在Source\Runtime中,在这个接近核心的模块中,比较重要的内容包括三大类:渲染模块(比方RenderCore和Renderer)、RHI抽象层和RHI实现层(比方Windows里的D3D11RHI和Apple里的MetalRHI)。

RHI即Render hardware interface,一般翻译为渲染硬件层接口,目的是想做一套与硬件无关与平台无关的接口。这个概念虽然听起来很高大尚,但是不是UE4专用的,至少我知道OSG里就有GraphicsWindowsX11和GraphicsWindowsIOS等类.

UE4相对来说做的更彻底。它在平台无关之上,还想做到硬件无关,它的接口类里,其实就是几个简单的虚函数,平台运行的时候,会自动判断在哪个平台上,从而决定是调用DX11的实现,还是调用OpenGL的实现。

当然,为了具备有前瞻性,UE4还实现了Vulkan的接口,有兴趣的可以看看,所说实现的还不错,反正我是看不懂这么有技术含量的东西。

要想跟踪渲染流程,最好的办法是找到Tick()函数,在Runtime\Launch\Private中有个LaunchEngineLoop.cpp文件,LaunchEngineLoop.cpp中有一个FEngineLoop::Tick()函数。找到这个函数,可能不太容易,方法有三种:第一种连猜带蒙。第二种从网上先查资料。第三种,从初始化函数跟过来。

在这个函数中下个断点,只要程序运行起来,这是必进的,而且,不取消断点,基本上跑不动。所以,这里我们肯定发现在了正确的函数。

这个函数做了很多的事。如果想认真学习UE4,我希望大家把这个函数至少看完一遍。

这个函数其实做了很多事,首先,进行心跳帧同步,然后进行各种检测,比方不能在加载动画文件的时候进行,或者不能在基准模式下(benchmark mode)操作。

接下来,做的内容就是比较实在了。

 

然后才开始真正的处理,在这之前,调用了AdvanceFrame函数,总之,搞得特别正式,接下来,和大家说,我要处理新的一帧了,在这之前还要调用计算外部的FPS/MS的平均值,然后做些预处理的任务。

ENQUEUE_UNIQUE_RENDER_COMMAND,这个宏要注意一下,因为,和真正渲染的宏ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER,是同一类的,有兴趣的话,进去看看,这个宏写的很怪异。

接下来,还防止程序有事没事的跑一帧两帧的。

然后,就是增加外部回调了。把这些事做完。到了GEngine的Tick函数处。这里也算是接近“更核心”的地方了。

接下来又是一层保护。

再接下来是两个重要的步骤,一个是Shader管理,一个是任务同步管理。 再接下来是从属应用的管理,其实是辅助程序的管理。

再接下来是两个宏,由于是宏,所以,有可能被注释掉,所以肯定不是主线,从字面上看,就是从此是自动控制器,一个是自动操作器。

接下来,就是我们上面讲了半天的RHI,在我的电脑上,跟进去,就是FD3D11DynamicRHI,可见,我上面说的,有一定道理。

再接下来是帧统计,这里有一个甩掉前六帧的统计用法,官方给出的理由是加载时间忽略。

接下来就是清理无效的objects了。

再接下琰,我们又看到了ENQUEUE_UNIQUE_RENDER_COMMAND,只不过,这里是EndFrame,和开始的那个对应(BeginFrame)。大家可以简单的理解为,在这两个宏之间的,才是一帧里真正要做的事。

再接下来就是统计了。对主流程没有什么太大作用。

跟踪完后,我们在这个函数的任意位置,加一个断点,再回过头来看一下,最终的入口在WinMain函数里。可见,在开头说的三种方法中,我应该大概似乎可能是用的第三种方法。

从这里再跟踪一步。到GuardedMain中,我们可以看到一个循环:

玩过任何一个三维平台的同志,应该都会很清楚,几乎所有平台的最根本渲染都是一个类似的循环。而这个循环,也是最基本的一个循环,在这里,我们可以认为,我们在主线程中。

我们都知道,当前流行的平台,不可能是单线程,那么其它线程入口都在哪呢?

想一下,我们在上面跟踪的时候,是不是重点强调了GEngine->Tick,我们从这里出发,继续找,一直走到FGraphEventRefConstructAndDispatchWhenReady

看到了没,又是这个系列宏ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER,由ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER来产生一个TGraphTask,从而驱动渲染线程。

走到这里,大概明白了吧。

可以说UE4的基础渲染其实很简单,缺省和OSG了、OGRE了什么的平台也差不了多少,一个 while,然后,一堆回调,再加上一些子线程。关键是我们想要什么,就找个点切入进去。

这篇关于格格她爹讲程序---用传统程序员的方式玩UE4(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/892845

相关文章

Linux之UDP和TCP报头管理方式

《Linux之UDP和TCP报头管理方式》文章系统讲解了传输层协议UDP与TCP的核心区别:UDP无连接、不可靠,适合实时传输(如视频),通过端口号标识应用;TCP有连接、可靠,通过确认应答、序号、窗... 目录一、关于端口号1.1 端口号的理解1.2 端口号范围的划分1.3 认识知名端口号1.4 一个进程

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

Django中的函数视图和类视图以及路由的定义方式

《Django中的函数视图和类视图以及路由的定义方式》Django视图分函数视图和类视图,前者用函数处理请求,后者继承View类定义方法,路由使用path()、re_path()或url(),通过in... 目录函数视图类视图路由总路由函数视图的路由类视图定义路由总结Django允许接收的请求方法http

Python yield与yield from的简单使用方式

《Pythonyield与yieldfrom的简单使用方式》生成器通过yield定义,可在处理I/O时暂停执行并返回部分结果,待其他任务完成后继续,yieldfrom用于将一个生成器的值传递给另一... 目录python yield与yield from的使用代码结构总结Python yield与yield

pandas数据的合并concat()和merge()方式

《pandas数据的合并concat()和merge()方式》Pandas中concat沿轴合并数据框(行或列),merge基于键连接(内/外/左/右),concat用于纵向或横向拼接,merge用于... 目录concat() 轴向连接合并(1) join='outer',axis=0(2)join='o

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

Oracle数据库定时备份脚本方式(Linux)

《Oracle数据库定时备份脚本方式(Linux)》文章介绍Oracle数据库自动备份方案,包含主机备份传输与备机解压导入流程,强调需提前全量删除原库数据避免报错,并需配置无密传输、定时任务及验证脚本... 目录说明主机脚本备机上自动导库脚本整个自动备份oracle数据库的过程(建议全程用root用户)总结

Debian系和Redhat系防火墙配置方式

《Debian系和Redhat系防火墙配置方式》文章对比了Debian系UFW和Redhat系Firewalld防火墙的安装、启用禁用、端口管理、规则查看及注意事项,强调SSH端口需开放、规则持久化,... 目录Debian系UFW防火墙1. 安装2. 启用与禁用3. 基本命令4. 注意事项5. 示例配置R