【随笔】论多线程CPU离线渲染器的实现:A CPU BASED OFFLINE RENDERING ENGINE
前言
小熊挺喜欢玩游戏的,对于游戏画面有所追求,记得高中第一次玩战地的时候,惊叹于画面细腻的表现,并且还能开坦克车,这样的事情深深吸引了我。我是一个画面党,为了追求更好的画质表现我开始研究设置面板里各个选项的含义,但是并不是特别深入,上了大学幸运地拥有了时间(主要指可以逃课)让我可以重新更加深入的了解图形背后的技术原理,以及那些让人痴迷的图形算法,真是行云流水让人拍案叫绝。
所以做了这样的项目,让我对背后技术有了更深理解,和更好使用Unity或OpenGL了(
开源组件使用和版权声明
得益于前人的工作和巧妙的思想,我在阅读了这些文献后,融合了自己的想法和小思路,做出了这样的作品。虽然现在渲染器已经有很多并且五花八门,但是拥有一个属于自己思路和想法的渲染器还是挺让人有成就感的。
开源组件使用情况说明
- Windows Presentation Foundation(WPF):Licensed Under MIT;
- .NET Runtime:Licensed Under MIT;
- OpenCV4:Licensed Under BSD;
- Asp.Net Core:Licensed Under MIT;
本软件渲染部分实现只使用了C#和C++自带的一些STL库。并没有使用OpenGL或者Direct库。
版权声明
接下来的文章将会尽可能的表明外部引用资源的出处,有些是互联网的资源所以并没有找到源头,但是我会将其标注出来。如果有什么地方没有标准或者错误标注,欢迎在评论区为我指出。
在本文最后,将会给出更详细的资源使用列表。
本文不允许转载发表,一方面这是小熊的日记,写在自己的博客以此做一个纪念,另一方面本文还有很多部分尚未改善完成,待来日方长,再让我慢慢对你诉说。
接下来的文章介绍的部分,除了特别标注以外,是由我所完成和实现的。
项目简介
一个高性能,低占用,便于用户使用的CPU离线渲染器。
本项目不使用现有的相关图形库(如:OpenGL、DirectX)而是从头自己写一遍(根据现有的论文),重新设计相关算法与技术。它具有高性能,低占用的特点,它便于用户使用,采用离线算法进行渲染计算。
在这个渲染器项目中,实现了众多算法包括不限于NPR基于物理的真实渲染,PBR非真实渲染等;可以配合现有的Blender、C4D、3DMAX等DCC软件,进行协同使用;它操作简单,支持简单化云计算等创新功能;完全使用CPU进行渲染,对GPU做到了0占用。
实现了能够渲染一些画面和导出一些动画等功能。
项目特点
- 我自己写的(
- 使用简单,可以在UI界面切换渲染管线
- 拥有一个物品管理器,可以导入模型调整模型旋转位置,还能修改物体名称
- 一个简单的云计算功能,两台电脑分别渲染一点画面
- PBR基于物理的渲染,NPR卡通化渲染实现
- 占用资源很小,对比现在的套壳浏览器APP,它只占用57mb左右(打开状态下,未进行渲染计算)
项目截图
软件UI界面:

(图中像素女生来自游戏《杜若花开》,一款大二写的Unity像素风手游,设计参考于美术@鱼鱼@小勤@小满@盖子同学)
多材质插槽模型表面实现:

(上图人物是一个虚拟主播形象,见本文末的附录的资源声明)
天空HDR采样实现:

(天空HDRI文件来自互联网资源)
多线程渲染:

人机交互设计:


软件结构(架构)设计
纹理和材质

(Texture和Material类设计图(部分))
如上图所示,小熊设计了一些类如Texture来表示基础的纹理材质的模样,然后这个类派生了其他的可能纹理,用来表示材质贴图。其中设计了uv这样的变量来采样图片中的颜色信息。
而Material类则用来描述物体的表面属性,大体可以分为光滑或不光滑,粗糙的,金属类或非金属。目前研究到了这里。
渲染和管线设计

(图:自己的管线流程设计稿,上图部分摘抄自{参考文献-1})
设计了一个比较简单的渲染管线,主要就是用来模拟一些顶点和片元上的操作,最上面的图是常见的渲染流程图。

上图就是一个简单的示意图了,小熊的项目就是这样子进行运算的,而描边等算法我使用了OpenCV等功能库进行制作,主要是比较简单。
同时设计了这些小熊还设计了一个可以解耦合的渲染接口,用户只需要实现接口就能放入到渲染器之中进行使用了。
软件语言和代码实现
采用C#和C++混合编写策略,C#部分手动控制GC回收,提高软件部分的性能,C++负责编写一些需要结合OpenCV或者高性能计算的代码部分,并把C++部分编译为DLL,供前端C#调用。为了提高性能,完全发挥出CPU的实力,采用多线程的软件实现思路,设计一套无锁的内存区域。
C#部分同时负责编写ASP.NET服务器,用于做分布式云计算的基础。
C++部分
- dllmain.cpp(DLL的主要入口,用于做出一些动作在ATTACH或者DETACH上,我在这里用于关闭OpenCV的一些功能)
- imageFunc.cpp(算法的实现,在这里实现了一些函数,用于双边滤波,描边算法,图像二值化均值化等,是【NPR渲染】和【图像自动降噪】功能的实现)
C#部分
- DAO命名空间(CppFunction类,用于调用C++代码;NetWorkJsonData,用于ASPNET交互;PbIO类,自己封装的二进制读写类,用于BRGA数组写入图片和图片文件读取,模型文件二进制读取;ToRenderDispter类,用于去多线程的参数传递;)
- CameraObj命名空间:用于实现一些摄像机类,描述摄像机的行为和空间。
- And So On… 还有一些其他的如:纹理,材质,光线追踪,GobalManager全局管理类等。
在这个部分,同时也实现了一些数学算法,PbMath,用于做数学的线性变换和矩阵运算等操作。支持矩阵于向量的乘法,支持常见的点积与叉积。
public static Vector3d operator *(Matrix3x3d matx, Vector3d vector) {return new Vector3d((matx.e[0] * vector[0] + matx.e[1] * vector[1] + matx.e[2] * vector[2]),(matx.e[3] * vector[0] + matx.e[4] * vector[1] + matx.e[5] * vector[2]),(matx.e[6] * vector[0] + matx.e[7] * vector[1] + matx.e[8] * vector[2]));
}
技术概要
简介
下面本文章将介绍这个项目的核心理论,这部分参考了一些经典的论文和图形上的实现。具体请见文章的论文/资源引用声明或者文末的附录部分。
我(小熊)参考了这些前人所作的工作,在这些人的基础之上,完成了这个项目。
这部分介绍了本项目实现的理论基础。
云计算的实现
开放端口,然后接收POST和GET请求。使用MVC设计模式,虽然View部分很简陋,只用于检测Api能否发送,用了Swagger框架。
接收渲染任务和分配渲染任务,调整建立连接的计算机相关的计算任务。
云计算流程:【接收到连接】-【接收到渲染任务】-【向连接的计算机发送渲染任务的场景】-【对每台计算机设定渲染的范围,然后开始】-【一直重复上一步直到没用画面可以分配】
- GobalManager.cs(单例,用于管理现在接收的渲染任务和图像缓存,与一些其他参数)
- TestApiController.cs(控制器,测试Api能不能用)
- RenderDataController.cs(控制器,云计算算法的核心实现,也就是在这里进行相关的任务分配和其他工作)
一个物体多材质系统实现原理
用过DCC软件估计都知道,模型是可以被赋予各种不同的材质球的,我的实现是这样。

如上图,给每一个三角形图元配置不同的材质地址,当然光线求交的时候就带上材质的地址,这样就能够实现一个物体带上了多个材质,使用了指针进行实现。
基于物理的渲染技术
部分参考文献:
- 《计算机图形学原理,第四版》.
- 经典的图形学虎书
- Games101,Games102和一些其他文章博客
光学基本原理
光是一种电磁波。不同波长的可见光投射到物体上,有一部分波长的光被吸收,一部分波长的光被反射出来刺激人的眼睛,产生了对于色彩的感觉。
物理上不可分割的光有红、橙、黄、绿、蓝、靛、紫等七个颜色。事实上,小熊渲染器并不打算直接模拟这些光的波长颜色,我直接使用了Red、Green、Blue这三种颜色,进行模拟。
模拟光学折射率,直接使用数学中的乘法原理,由于光拥有干涉,衍射等特性。所以真正投射到物体上的光源应该经历了多次反弹,以下的公式出于一种简单的模拟,绝非真正遵循了物理的规律。
因为
( 0.3 0 0 0 0.2 0 0 0 0.5 ) ∗ ( 1 1 1 ) = ( 0.3 0.2 0.5 ) \begin{pmatrix} 0.3 & 0 & 0\\ 0 & 0.2 & 0\\ 0 & 0 & 0.5 \end{pmatrix} * \begin{pmatrix} 1\\ 1 \\ 1 \end{pmatrix} = \begin{pmatrix} 0.3\\ 0.2 \\ 0.5 \end{pmatrix} 0.30000.20000.5 ∗ 111 = 0.30.20.5
这样的线性代数过程可以看为,投射中,损失了一些光的能量。
V c o l o r = V 折射率 ∗ ∏ V c o l o r (光线折射) V_{color}=V_{折射率}*∏V_{color}(光线折射) Vcolor=V折射率∗∏Vcolor(光线折射)
对于上面这样的公式,V是Vector3d类型,折射率是存储在计算机类里面的一段数据,是的,这也是一种递归,光线折射拥有一个迭代深度的限制。
微表面理论
模拟真实世界物理表面,最主要的是要模拟两大物理光学方向,一种是折射,一种是反射。

在现实中,物体表面并非绝对光滑,因为表面在微观层面上,凹凸不平,所以材质展示了漫反射效应(Diffuse)和金属反射效应(Metal)。如上图。对于光的波长而言,物体的表面尺度对比它是很大的,所以可以将每一个物体表面看作一个很小的平面,这个平面上拥有法线,这样光线的各种计算才有了理论基础。这是小熊对于这方面的理解。
迭代式光线追踪
迭代式光线追踪又称递归式光线跟踪算法,通过模拟光线反射与反弹,进行下一层次的迭代计算。相比于过去,光线投射渲染的进化发生在1979年,Turner Whitted在光线投射的基础上,加入光与物体表面的交互,让光线在物体表面沿着反射,折射以及散射方式上继续传播,直到与光源相交。这一方法后来也被称为经典光线跟踪方法、递归式光线追踪(Recursive Ray Tracing)方法,或 Whitted-style 光线跟踪方法。

(上图是互联网上下载的)
我们想要得到的结果是,光打在物体上,得到的颜色样子。但是从光源点进行投射,由于光的方向性,很多光线并无作用在物体上,由于光路具有可逆性,所以本算法从屏幕表面进行投射。然后反向求解光源信息,如上图所示。
同时,我发现,光线在投射的时候,有时候会浪费迭代的机会,因为投射的都是黑色的部分,所以我想接下来再次改进,阅读一下文献,让光线投射的时候尽可能的打到有光源颜色亮度的地方上去,这样可以避免浪费,和降低时间复杂度。
下面是,本项目这个部分的相关伪代码。
1. Vector3d Ray_Color(Ray ray, HitTable world, int depth) { //投射光线2. 到达迭代次数则回退;3. if (world.Hit(ray, 0.0000001d, 0x3f3f3f3f, out hitResult)) {4. 开始下一次计算渲染,如果支持的话;5. } else {6. return emitColor; // 返回自发光的颜色7. }8. }9. // 返回背景颜色
10. return GobVar._BackColor;
11. }
本项目实现

程序实现这些光学模拟,参考了一些经典算法,简单来说,如上图所示,通过对物体表面法线方向的随机模拟光线投射样子,进行相关的物理演算。
此过程事实上是一种积分的运算,数学描述如下:
C o l o r = ∫ [ L i ( w i , x ) c o s ( w i , n ) d w i ] Color=∫[L_i (w_i,x) cos(w_i,n)dw_i ] Color=∫[Li(wi,x)cos(wi,n)dwi]
以上积分大体可以理解为,对于一个物体表面的点,它累计的光影响值是多少,本项目根据MC蒙特卡洛积分算法,对以上公式进行了如下的编写(也是函数的编写)
C o l o r = 1 n ∑ j = 0 n L i ( 不同的方向 ) P ( 不同的方向 ) Color={\frac{1}{n}}{\sum \limits _{j=0} ^{n} \frac{L_i(不同的方向)}{P(不同的方向)} } Color=n1j=0∑nP(不同的方向)Li(不同的方向)
本项目支持调整以上公式的n的部分,当n越趋向于无穷大的时候,那么结果将会越来越准确。
以下是使用项目,进行相关渲染的画面截图。通过设定,表面的光滑程度,进行相关的计算机图形学模拟,效果如下。

(上图的天空HDRI文件为互联网上下载)
通过设定粗糙度的值,从0(光滑)到1(不光滑)。可以看到下图这样的结果,符合现实中,物理光学上的表现。光滑的物体能够反射更多的场景灯光,不光滑的物体表面反射不了一些场景的信息。本项目基本实现了这样的效果。

(上图背景HDRI文件为互联网上下载)
非真实光感渲染-卡通化风格渲染技术
参考文献:
- 刘乐乐的那本UnityShader
- 网上的博客和文章
- 下面的图片来自游戏《塞尔达》,知乎上copy的图片,还有一些来自WIKI。
原理介绍

通过手动模拟高光反射,色差控制,阴影光照,以及一些轮廓光照来实现。
Phong光照实现
Phong算法又称裴祥风算法,通过计算机物体表面的高光,阴影,环境光,折射率等,得到结果。此算法时间复杂度较高为 O(N+M) 但是实现较为简单,所以应用广泛。
在卡通化渲染中,并不需要更好的物理效果,所以选择了此算法。

如上图,我们通过表面N法线,与光线方向L和眼镜方向进行相关的计算,而H则是一个半程向量,为V和L的中间那个向量,用于计算高光。

(以上两张图摘自WIKI百科,对于PHONG算法的介绍)
本项目的实现
我们实现卡通化渲染是使用Phong光照进行计算,计算完毕后使用OpenCV来进行颜色差值化(将颜色映射为两个颜色,这个部分正在研究),然后使用OpenCV进行描边检测,检测完毕后绘制边缘。这样一张卡通化渲染的图像就渲染完毕了。

(小兔子的模型请见本文末的资源引用)

这是卡通化后的结果,渲染完成后检测图形的边缘然后进行描边和一些后期处理。这部分在C++代码部分完成了。
Normal Map
参考文献:
Games101等系列,还有网络上的博客和文章
简介
法线贴图是一种将模型的切线空间下的法线位置保存在一张贴图里的技术,使用这个技术,可以使得在不增加顶点的情况下,然后模拟出顶点很多的模样,是一种视觉上的Trick。
这个部分应该有一些介绍图的,但是懒得去切换APP了,请自己去网上看一下吧。
本项目实现
通过转换切线空间的位置抵达世界空间,然后再去进行相应的计算。

通过设置不同的尺度来控制法线贴图的比例大小可以构造出不同的落差感。从左到右分别是法线贴图的:0x,01.2x,1.5x尺度。
MSAA抗锯齿
简单来说就是因为图形本身应该是连续的,但是采样是离散的,那么有些信号就采样不到了,而发生了混叠。就是频率太低了嘛~那怎么办?那就提高一下采样的频率,但是如果采样频率太高了那么就又会发生代码运行太慢的情况,所以要在重要的边缘上进行采样。

注意观察图像边缘,再多次采样过后,图像边缘变得模糊但是同时也变得更加平滑,这是因为它采样了其他像素点的信息。
BVH包围盒技术
光线求交在整个渲染流程中,是一个很大的时间占比(后文将有详细的测试报告),通过加快光线求交速度,将会有一个显著的提升。
单纯遍历内存中所有数据时间复杂度将是O(N)。如果构建BVH二叉树,则可以把时间复杂度将为O(Log N)级别。BVH算法核心是,分治算法,构建一个包围盒,左右两个包围盒再去递归。
原理是随机选取一个轴度(XYZ),将物体排序后,从中间分割开。但是这个算法有一个很大的问题,那就是,如果物体进行移动,那么就需要重新建造模型,根据《Ray Tracking In One Week》系列书籍中,提到的相关算法,我们可以只进行移动光线,而不移动模型,这样的优化思路,又成功地,让我们的项目支持了,渲染物体移动,旋转,渲染动画等功能。
一些很小很小的创新
这些东西说创新我都有点不太好意思,因为它们实在太微小了,甚至有一些我还没有研究完毕。不过我先把我的内容先发在这里,等我以后再去慢慢地研究。
红黑图的渲染方式

首先渲染一张红黑图,然后再在这个红黑图的基础上填充像素的颜色。通过划分出哪些区域需要更大的采样,哪些区域只需要更少的采样,以此来更快速的出图,并且保证质量不算特别的下降。
目前这方面我正在研究一个自适应的公式来调整采样频率的大小,此部分有待进一步的研究。


可以看到画面开始慢慢得根据红黑图的轮廓进行着色计算了。
(本部分的人物模型见本文末资源引用部分)
PbObj文件格式
这个就是用来保存自己下面的模型文件和摄像机位置以及贴图信息的文件了。它支持Hash校验,将Hash校验码直接保存在了文件的内部。
这个文件格式内部使用了XML来描述,然后本项目会读取这个文件,和保存这个文件,并且云计算中传递信息的用的就是这个文件格式。
这份文件与以往文件还有不同的地方是,它支持持久化的存储,比如现在有一个操作,修改了模型顶点位置,传统的Obj格式文件就要保存两份了,而我们的PbObj格式文件会差异化保存,然后去恢复出上下两个步骤的操作以及模型文件的样子。
从原理上来讲,这是行得通的。
1. <SphereXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">2. <objName>SkyBox天空光照盒子</objName>3. <needRender>true</needRender> // 渲染可见性4. <center>5. // 省略…6. </center>7. <mat xsi:type="SkyMat"> // 保存物体相关的,材质信息,也可以保存数组中的引用列表8. <mTexture xsi:type="Solid_Color">9. // 省略…
10. </mTexture>
11. <_tex xsi:type="Solid_Color">
12. // 省略…
13. </_tex>
14. </mat>
15. </SphereXML>
16. <History>
17. 这里通过记录每一次操作实现上下过程持久化
18. </History>
实验测试
写完了代码当然要玩一会,说错了,是实验一会,所以进行了一些相关的实验测试,下面是本项目的实验测试报告。
渲染画面对比
PBR基于物理的渲染

(左图是本项目输出的图片,而右图则是互联网上下载的照片)
以上是Cornell_Box的实机渲染画面(左),CornellBox由康奈尔大学在SIGPRA`84中提出,用于测试程序渲染的结果
是否正确。正确的结果应该如右图,场景内的小盒子上反射出墙壁的颜色,而地板因为头顶光照则产生了一些黑色的阴影。
最主要的是研究,光线的明暗变化,以及光线的漫反射,直接光是否计算正确。对比上图中的光线细节和模型产生的阴影可以知道,本项目的模拟是基本上正确的。

这张照片拍摄于学生宿舍阳台。人物为我们自己研发的软件《杜若花开》中的依依。我们通过3D打印技术,将游戏中人物在现实中复刻,由于喷漆缘故,人物并不是完全漫反射(右图),在计算机中,我们模拟了完美漫反射效果。
NPR卡通渲染

使用了Phong模型的光照和对光源的特殊处理,得到的结果。

(中间图片来自:央美@小袁(袁宇静)同学)
通过对比如上图中间和右边图片,我们的软件成功模拟了卡通手绘效果。
降噪算法

使用了OpenCV的双边滤波,主要是想要保存模型的边缘信息,所以对于这种色块颜色插值不大的就做了降噪处理。
左图是降噪后的,右图是降噪之前。
运算资源占用实验
CPU核心利用数据

(中央处理器占用数据)

(各个函数在CPU中占比时长)
通过我们的技术分析,我们发现我们程序大体上有效的利用了CPU多核心的优势,并且最占用时间的函数是AABB.Hit函数,这是在判断,光线是否和场景中的物体相交。
内存占用对比数据
我们程序完全不使用显卡进行工作,只占用内存(RAM)而不占用显存(DRAM)。证明如下:

任务管理器(GPU零占用)

内存占用数据
从总体来看,我们的渲染器内存占用小,持续渲染内存占用平稳。GC回收平顺介入及时。上文两张图片是在716个三角形,迭代100次,MSAA4x下,进行测试的,测试机详细数据在下文。
为了对比不同场景下,不同软件下的内存占用数据,我们做了相关的测试,数据汇总如下。
| 渲染图像 | 参数信息 | 内存占用 |
|---|---|---|
| 一个简单球体 | PowerBear软件(本项目) | Min:67.2mb Max:69.4mb |
| 一个简单球体 | Blender软件 | Min:720mb Max:821.2mb |
| 依依(717个三角面) | PowerBear软件(本项目软件) | Min:79.1mb Max:82.4mb |
| 依依(717个三角面) | Blender软件 | Min:802.1mb Max:874.2mb |
| 简单球(本项目) | 简单球(Blender) | 依依(本项目) | 依依(Blender) |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |

通过对内存占用的详细测试,我们对比了任务管理器中的内存占用数据,我们得到了初步结论,在性能不好的机器下,本项目的渲染器占用内存小,适应性高,具有一定的成本使用优势。
渲染时间测试报告
环境变量控制如下,画面大小:500*500px,采样次数:100spp,开启动态采样,开启多线程,如果有支持CPU计算插件,尽可能使用CPU而不是GPU进行运算。降噪关闭。
我们渲染器,在支持GPU渲染的软件对比下,速度上并无优势,部分大场景中,渲染速度显著慢于传统渲染软件的速度。这是因为GPU能够很好的处理并行任务,而CPU更擅长处理逻辑复杂的任务。
BVH包围盒对比实验
单纯遍历内存中所有数据时间复杂度将是 O(N) 。如果构建BVH二叉树,则可以把时间复杂度将为O(Log N)级别。BVH算法核心是,分治算法,构建一个包围盒,左右两个包围盒再去递归。我们对比了,不够建包围盒,和构建包围盒的时间占比,数据如下。
实验环境,随机小球,2X 20采样,多线程核心数:8 CORES,摄像机坐标:(0,3,1)(0,-0.59999,-1),场景球体数目,随机大量小球:604元素,很大的场景:30w+面数

BVH构建实验测试图

通过BVH将场景里面物体按照一定顺序划分,进行建立二叉树,从而加快了场景光线求交的速度,经过优化,从原来的 O(N) 级别复杂度成功降为了 O(LogN) 级别的复杂度。通过实验可以知道,在大量物体下,光线求交速度比未经过优化的场景更加快速。如果场景物体本身比较少,那么BVH并无显著加快对于常规光线求交算法而言。
通过动态调整采样次数加快渲染(红黑图)

我们发现,部分画面区域,提高采样次数,无显著意义。如上图左边所示,红色部分应该提高采样次数,而黑色部分不需要提高采样次数。
我们将舍弃那些,提高采样次数也没有太多作用的画面区域。这样来加快整个渲染画面的流程。规定渲染参数如下:50spp,500*500px,开启多线程。数据汇总如下:

可以看到,通过动态采样算法,屏幕占比越小的情况下,渲染时间长度越短,对于复杂的屏幕渲染,动态采样算法发挥的作用较小,但是对于屏幕占比不大,场景简单的情况,渲染时间显著减少,具有一定的意义。
多核心与单核心时间测试
测试场景,包含天空HDRI,一个金属小球和一个漫反射小球。采样为20次,光线反弹50次,画面大小500*500px。纹理大小1K分辨率。

经过测试多核心渲染速度是4.32秒,而单核心为11.424秒才渲染完毕。多线程速度比单线程速度快了3倍。
附录
这部分介绍了一些其它和本项目相关的内容。
参考文献
- 上海交通大学刘乐乐-《UnityShader》
- Cindy M. Goral, Kenneth E. Torrance, Donald P. Greenberg, and Bennett Battaile. Modeling the Interaction of Light Between Diffuse Surfaces Archived 2010-06-27 at the Wayback Machine. Siggraph 1984.
- An introduction to ray tracing[M]. Morgan Kaufmann, 1989.
- Bui Tuong Phong,University of Utah.Phong Shading. 1975. ACM
- 《计算机图形学原理,第四版》.
- Games101系列课程,闫老师的
- Shirley P. Ray tracing Series[J]. United States of America: Kindle, 2016.
资源声明
本文章的一些实验素材引用了互联网上的一些资源,现在介绍如下:
- 像素初音设计灵感:作者:霄_Q27|【Minecraft】在mc里面建只可爱的fufu!~
- 零LULU 一位虚拟主播设计形象 作者:Flyingflyx
- YYB style Sakula miku 作者:YYB
还有一些天空贴图,墙壁瓷砖贴图引用自互联网,没有找到作者源头。
测试机器参数
也就是小熊同学自己的电脑了。
| 部件 | 型号 | 性能 |
|---|---|---|
| CPU中央处理器 | AMD RYZEN | 6800HS |
| RAM内存 | 三星M425R1GB4BB0-CQKOD | DDR5 4800MHz 8+16GB(24GB) |
| ROM电脑存储 | 西部数据 WD PC SN735 SDBPNHH-512G-1002 | 512GB PCIE4.0 |
| 电脑主板 | 华硕GA503RM | OEM:ASUS - 1072009 |
以上,测试数据如无特殊说明,均为这里列出的测试数据。由于本项目最主要看的是CPU性能,内存延迟和SSD读取性能,故其他数据暂未详细列出。
| 软件名称 | 版本 |
|---|---|
| POWERBEARRENDER渲染器 | 截至2023年10月版本,内测 |
| BLENDER | 2.81 Windows |
| CINEMA4D | R20 Windows |
碎碎念
感想信
很开心的说,这个项目的初始想法,和最后的编程实现来自于我自己。并没有特别依托学校和老师的资源,孩子总要长大,所以要有动力和勇气自己尝试写一下代码。
不过话是这么说,我依旧要很感谢我在周围所遇到的所有人,我的同学帮助我,在老师来的时候喊我起来,这样让我可以在课堂上开小差看这些喜欢的内容。有时候睡过头了同学也会喊我去上课,让我不用天天写检讨,这是非常nice的时刻。同时我也遇到了很棒的队友和同学,他们愿意与我组队并且做了很多有意义的工作,他们帮助我写了经济效益预期,调查问卷等等内容。如果没有他们的存在,让我去写和做这些调查报告我是极不乐意的。
我也要感想我所遇到打指导老师,虽然我们学校没有计算图形这个方向(毕竟只是一个三类本科民办),但是他们为我开阔了视野。其中有一位祝老师让我从外语系转到了信息系,我要感想她对我的发现和认识,其中我的薛老师为我指点了很多很多在计算机视觉上的内容,并且帮助了我打通了一些基础的OpenCV操作和人工智能的基础姿势,这是我所开始的开端,当时也和老师一起探讨过我们是否应该使用Qt来进行UI界面的编写,不过我比较喜欢C#语言想要减少一点C++的占比所以最后我使用了WPF,哈哈。其中的祁老师为我的人生做了很多的建议,并且在我失落的时候鼓励我,开导我且给了我许多中肯的指南。
我也要感谢先前的人,他们做了非常优秀的工作,且无私的将这些成果公布了出来,让我有机会能借助他们的思路,实现了自己的项目。
(我估计应该没有人会在我的基础上继续工作了吧,毕竟这个就是一个自己写着玩的小工具,所以就不感谢后来者了,嘿嘿。)
尚未完成的部分
就算写道这里还是有很多的东西让我尚未完成,比如说一些更好的算法,体积光照系统,更加先进的降噪,还有我的红黑图的继续下一步的改进和优化。
前途路漫漫,等以后做了更多工作就来这里再写一篇随笔好啦。
因为确实挺感兴趣的
大概算了一下,编写这个项目大概花了10个月的时间,几乎一有空我就会去写它。
管它有什么用途,有什么可以得到的,总要有机会为了自己所喜欢的东西去为之努力一次,这份旅途,它至少不亏啊,我看到了内在的东西和风景,我相信它是值得的。

下图是我在高中时代所做的作品。

发布时间为:2019-07-04 11:36:28
这个视频使用了UE4进行制作和渲染。
而下面这行图则是现在这个项目所输出的画面

发布时间为:2023年10月13日
由自己的渲染器所输出的画面。
时间跨度为4年,谨以这份图像,纪念我所经历过的风景。有人说时间是最好的告别,而让我还在继续研究的原因仅此就是一个:我喜欢。
希望未来的我能继续保持对技术的喜欢,继续下一步~
相关文章:
【随笔】论多线程CPU离线渲染器的实现:A CPU BASED OFFLINE RENDERING ENGINE
前言 小熊挺喜欢玩游戏的,对于游戏画面有所追求,记得高中第一次玩战地的时候,惊叹于画面细腻的表现,并且还能开坦克车,这样的事情深深吸引了我。我是一个画面党,为了追求更好的画质表现我开始研究设置面板…...
多输入多输出 | MATLAB实现CNN-GRU-Attention卷积神经网络-门控循环单元结合SE注意力机制的多输入多输出预测
多输入多输出 | MATLAB实现CNN-GRU-Attention卷积神经网络-门控循环单元结合SE注意力机制的多输入多输出预测 目录 多输入多输出 | MATLAB实现CNN-GRU-Attention卷积神经网络-门控循环单元结合SE注意力机制的多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果…...
Ubuntu:Arduino IDE 开发环境配置【保姆级】
物联网开发学习笔记——目录索引 本章主要介绍在Ubuntu系统搭建Arduino IDE 开发环境,windows系统请移步:Windows:Arduino IDE 开发环境配置【保姆级】 参考官网:Arduino - Home 有关更多详细信息,请参阅 Arduino I…...
Kafka 开启SASL/SCRAM认证 及 ACL授权(三)验证
Kafka 开启SASL/SCRAM认证 及 ACL授权(三)验证。 官网地址:https://kafka.apache.org/ 本文说明如何做client验证ACL是否生效,我们之前开启了无acl信息不允许访问的配置。涉及的client有以下几个场景:shell脚本、python脚本、java应用、flink流。 kafka shell script验证…...
Pycharm 2023 设置远程调试
pycharm 版本 : 2023.2.1 整体流程参考:https://blog.csdn.net/xuanhaolaile/article/details/128293254 首先确定远程服务器上已经安装好 requirements.txt 中所需的依赖包。 1、SSH Configurations 添加远程服务器 2、Python Interpreter 注意&…...
asp.net core在其他程序集获取HttpContext
首先在Program.cs中,注册 builder.Services.AddHttpContextAccessor();Program.cs完整代码: using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Text.Encodings.Web; using System.Text.Unicode; us…...
UWB NI框架嵌入式实现——Qorvo示例
在Qorvo提供的DW3000示例代码中,实现了与Apple的NI框架的互通的示例,本文中针对其示例程序进行简要的分析。测试中使用Qorvo提供的模块,该模块为nRF52833DW3000的架构。 1. Qorvo相关库文件 Qorvo在提供示例时,仅提供了相关的库文…...
Linux OS源的问题记录
场景 安装了一台Linux虚拟机充当服务器,准备搭建一个elk环境,我使用命令安装docker的时候,报错提示 YumRepo Error: All mirror URLs are not using ftp, http[s] or file.Eg. Invalid release/repo/arch combination/ removing mirrorlist…...
数据库:Hive转Presto(五)
此篇将所有代码都补充完了,之前发现有的代码写错了,以这篇为准,以下为完整代码,如果发现我有什么考虑不周的地方,可以评论提建议,感谢。代码是想哪写哪,可能比较繁琐,还需要优化。 …...
SQL中for xml path 的用法
1. 用法 是一种将查询结果转换为 XML 格式的方法。它可以将查询结果中的每一行转换为一个 XML 元素,并且可以指定元素的名称和属性。 2. 应用示例 有一张学生选修课程的表,如下图所示 希望整合成下图所示效果 --建表 if object_id(StudentInfo,u) is…...
【TensorFlow2 之014】在 TF 2.0 中实现 LeNet-5
一、说明 在这篇文章中,我们将展示如何在 TensorFlow 中实现像 \(LeNet-5\) 这样的基础卷积神经网络。LeNet-5 架构由 Yann LeCun 于 1998 年发明,是第一个卷积神经网络。 数据黑客变种rs 深度学习 机器学习 TensorFlow 2020 年 2 月 29 日 | 0 …...
【2023】redis-stream配合spring的data-redis详细使用(包括广播和组接收)
目录 一、简介1、介绍2、对比 二、整合spring的data-redis实现1、使用依赖2、配置类2.1、配置RedisTemplate bean2.2、异常类 3、实体类3.1、User3.2、Book 4、发送消息4.1、RedisStreamUtil工具类4.2、通过延时队列线程池模拟发送消息4.3、通过http主动发送消息 5、dz…...
飞书应用机器人文件上传
背景: 接上一篇 flask_apscheduler实现定时推送飞书消息,当检查出的异常结果比较多的时候,群里会有很多推送消息,一条条检查工作量会比较大,且容易出现遗漏。 现在需要将定时任务执行的结果记录到文件,…...
高版本Mac系统如何打开低版本的Xcode
这里写目录标题 前言解决方案 前言 大家偶尔也碰见过更新Mac系统后经常发现低版本的Xcode用不了的情况吧.基本每年大版本更新之后都可以在各个开发群里碰见问这个问题的. 解决方案 打开访达->应用程序->选中打不开的那个版本的Xcode并且右键显示包内容->Contents-…...
测试H5需要注意的交互测试用例点
H5(HTML5)是一种用于构建网页的标准,可以实现丰富的交互和功能。测试H5交互通常涉及到验证网页在各种情况下的行为,包括用户输入、按钮点击、页面加载等等。以下是一些可能的H5交互测试用例: 页面加载: 验…...
1014蓝桥算法双周赛,学习算法技巧,助力蓝桥杯
家人们,我来免费给大家送福利了!!! 【1014蓝桥算法双周赛 】 背景 蓝桥杯全国软件和信息技术专业人才大赛是由工业和信息化部人才交流中心举办的全国性IT学科赛事。参赛高校超过1200余所,累计参赛人数超过40万人。该…...
C语言之通讯录的实现篇
目录 test.c 主菜单menu 创建通讯录con 初始化通讯录InitContact 增加个人信息AddContact 展示个人信息ShowContact 删除个人信息DelContact 查找个人信息SearchContact 修改个人信息ModifyContact test.c总代码 contact.h 头文件包含 PeoInfo_个人信息的设置声…...
如何降低海康、大华等网络摄像头调用的高延迟问题(二)
目录 1.RTSP介绍 2.解决办法1 3.解决办法2 1.RTSP介绍 RTSP(Real-time Streaming Protocol)是一种用于实时流媒体传输的网络协议。它被设计用于在服务器和客户端之间传输音频、视频以及其他流媒体数据。 RTSP协议允许客户端通过与服务器建立RTSP会话…...
centos清理日志和缓存
今天使用redmine修改密码,修改报错,再去试试创建用户,创建用户的页面直接报错显示不出来。然后看了一下服务器,发现服务器磁盘空间全部占满了。 CentOS系统也会在使用很长一段时间后出现硬盘空间开始不够的情况,而这并…...
排序算法的稳定性
什么是排序算法的稳定性? 排序算法的稳定性: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i] r[j],且 r[i…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...




