自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(71)
  • 收藏
  • 关注

原创 Games101作业7 蒙特卡洛路径追踪

因为蒙特卡洛积分要求对谁积分就要在谁上面进行采样,所以渲染方程进行改写,从对dω积分改为对dA积分,我们只需要知道dω和dA的关系然后替换即可。在下面这种情况下,当光源面积很大时,我们仅需很少的光线就能得到想要的效果,而当光源面积很小时,需要很多的光线才能打到光源,因此为了能尽快的打到光源,我们需要采取合适的pdf,直接对光源进行采样。渲染方程告诉我们的是,我们需要在物体表面的半球上进行积分,才能解出这个渲染方程,但是在半球上进行积分计算机不擅长做这个事情,因此我们采用蒙特卡洛积分解决这个问题。

2023-09-15 10:40:52 184

原创 Games101作业6(BVH的构建和遍历)

当场景中有多个物体时,先找到xyz哪一项加起来的值最大,以最大的坐标进行排序,进行划分,以下图为例,如果X的和最大,即对X进行划分。bounds对象的目的,找到该区域的包围盒,但可以通过方式找到包围盒,这种遍历方式较为耗时建议删除。对BVH的结构的理解,在BVH的非叶子节点中,都有多个物体,所以走到只有叶子节点的时候才会真正的。在recursiveBuild中,有如下代码,bounds对象创建而未使用。在场景中有两个物体时,将两个物体包围起来,再分别进行划分,对于代码。

2023-09-14 15:45:32 189

原创 Games101作业5解读

第一步,找到光线和物体的交点,然后往外走一点,这里为什么是Vector3f shadowPointOrig = (dotProduct(dir, N) < 0)?第一步先与场景的求交,如果光线打到了物体,就继续判断打到的物体的材质,根据不同的材质进行不同的处理,这里重点说下REFLECTION和default。第二步,从shadowPoint中,往光源方向打一根光线,如果没照到物体,或者照到了物体比光远,说明光源可以打到物体,则没阴影。在REFLECTION中,这一段代码有点问题,应该是如下代码。

2023-09-09 15:56:34 213

原创 OpenGL学习笔记(一)

例如这个点,一共4个字节,我需要前两个字节表示坐标,后两个字节表示颜色,VertexBufferLayout就可分配字节,前两个字节为一组,后两个字节为一组,如果要具体的表示坐标与颜色后文会介绍。就像上图,整个大长方形表示我们所有点的内存总和,每个小长方形表示每一个点占的内存,这时OpenGL只是知道了存储这些点需要多少内存,但不知道有多少个点,每个点的每个字节的意义。我们已经知道了顶点的信息,但目前而言,顶点的信息只是一串数,让OpenGL如何解析这些数,就是Shader要做的事情。

2023-04-25 21:55:19 529 1

原创 利用MFC实现一个托盘功能

在BEGIN_MESSAGE_MAP(CMFCApplication2Dlg, CDialogEx) 与END_MESSAGE_MAP()之间添加自定义消息。在BEGIN_MESSAGE_MAP(CMFCApplication2Dlg, CDialogEx) 与END_MESSAGE_MAP()之间添加自定义消息。在CMFCApplication2Dlg::OnInitDialog进行初始化。OnSysCommand的实现。右键点击托盘,弹出如下的图标。

2023-04-20 14:13:22 762 1

原创 https协议

因为HTTP是明文传输,所以会很有可能产生中间人攻击(获取并篡改传输在客户端及服务端的信息并不被人发觉),HTTPS加密应运而生。中间人只需在传私钥时窃取私钥信息,那往后传输的所谓“加密”数据,中间人也都可以将其解密并加密继续传输下去而不被人发现。网站在使用HTTPS前,需要向CA机构申领一份数字证书,数字证书里含有证书持有者信息、公钥信息等。简单的说,就是用一个密钥,可以对一段信息进行加密,也可以使用其本身对这段信息进行解密,这就叫做对称加密。这种方法在效率上有所提升,但安全性与非对称加密方案一样。

2023-02-13 16:55:02 2400

原创 http协议

响应正文允许为空字符串,如果响应正文存在,则响应报头中会有一个Content-Length属性来标识响应正文的长度。其中,前面三部分是一般是HTTP协议自带的,是由HTTP协议自行设置的,而请求正文一般是用户的相关信息或数据,如果用户在请求时没有信息要上传给服务器,此时请求正文就为空字符串。:请求正文允许为空字符串,如果请求正文存在,则在请求报头中会有一个Content-Length属性来标识请求正文的长度。:请求的属性,这些属性都是以key: value的形式按行陈列的。:遇到空行表示请求报头结束。

2023-02-12 19:40:20 246

原创 boost搜索引擎

Boost官网没有对应的搜索引擎,不方便我们查看,本项目帮助我们搜索查阅Boost官方文档。.正排索引和倒排索引 - 搜索引擎具体原理4.编写数据去标签和数据清洗模块Parser2.去标签:html的标签,我们需要去除的标签,一般为成对出对官网的url:**https://www.boost.org/doc/libs/1_81_0/libs/beast/doc/html**/index.html当前路径:data/input/html/**index.html**只要加粗的地方相加就能得到官

2023-01-29 18:13:46 444

原创 图的最短路径

设k是p的一个中间节点,那么从i到j的最短路径p就被分成i到k和k到j的两段最短路径p1,p2。设i是src的一个中间节点,那么从src到j的最短路径p就被分成src到i和i到j的两段最短路径p1,p2。p1是从src到i且中间节点取得的一条最短路径。p2是从i到j且中间节点属于取得的一条最短路径。针对一个带权有向图G,将所有结点分为两组S和Q,S是已经确定最短路径的结点集合,在初始时为空(初始时就可以将源节点s放入,毕竟源节点到自己的代价是0),Q 为其余未确定最短路径的结点集合,

2022-12-26 20:04:51 394

原创 最小生成树

构造最小生成树的方法:Kruskal算法和Prim算法。这两个算法都采用了逐步求解的贪心策略。核心思想:每次迭代时,选出一条具有最小权值,且连接后图不形成回路,加入生成树。Prim与Kruskal算法类似区别在于。若连通图由n个顶点组成,

2022-12-22 18:30:36 645

原创 并查集的实现

在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(union-find set)。1.初始化数组将所有的元素初始化为-1,数组下标对应对象的编号。如果要用下图表示对应的集合关系。在一些应用问题中,需要。

2022-12-22 13:03:59 79

原创 图的遍历(以领接矩阵为例)

重复2过程,一直将出队列首节点,并将该节点指向未访问的节点入队列,并标记成已访问。

2022-12-22 12:09:17 79

原创 图的基本概念,存储结构

是同一条边,比如下图G1和G2为无向图。注意:无向边(x, y)等于有向边和。,顶点对(x,y)称为顶点x和顶点y相关联的一条边,这条边没有特定方向,(x, y)和(y,x)边(弧),和是两条不同的边,比如下图G3和G4为有向图。图是由顶点集合及顶点间的关系组成的一种数据结构:G = (V, E)是一个非空有穷集,称作顶点集,其元素称作顶点或结点.,顶点对称为顶点x到顶点y的一条。是顶点间关系的有穷集合,也叫做边的集合。有向图和无向图:在有向图中,

2022-12-21 18:04:53 122

原创 网络套接字编程(TCP协议)

参数说明:参数说明:服务端监听参数说明:服务端获取连接参数说明:客户端连接服务器参数说明:多线程版本的大小写字母转换服务server.hppclient.hpp效果

2022-12-07 20:58:32 623

原创 网络套接字编程(UDP协议)

其中最常见的服务类型是SOCK_STREAM和SOCK_DGRAM,如果是基于UDP的网络通信,我们采用的就是SOCK_DGRAM,叫做用户数据报服务,如果是基于TCP的网络通信,我们采用的就是SOCK_STREAM,叫做流式套接字,提供的是流式服务。addrlen:调用时传入期望读取的src_addr结构体的长度,返回时代表实际读取到的src_addr结构体的长度,这是一个输入输出型参数。sockfd:对应操作的文件描述符。:数据的高字节内容保存在内存的低地址处,数据的低字节内容保存在内存的高地址处。

2022-11-29 13:59:59 678

原创 POSIX信号量

P操作:申请信号量,进入临界资源前,会申请信号量,x–,如果x为0时,则会堵塞等待。每个执行流要进入临界资源时,要先申请信号量,出临界资源时,要释放信号量。功能:发布信号量,表示资源使用完毕,可以归还资源了。V操作:释放信号量,出临界资源后,会释放信号量,x++pshared:0表示线程间共享,非零表示进程间共享。信号量是一个计数器,用来描述临界资源数量的计数器。功能:等待信号量,会将信号量的值减1。sem: 输出型参数,信号量的标号。value:信号量初始值 即x的值。

2022-11-23 16:34:31 165

原创 linux线程同步

条件等待是线程间同步的一种手段,如果只有一个线程,条件不满足,一直等下去都不会满足,所以必须要有一个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件 变量上的线程。条件不会无缘无故的突然变得满足了,必然会牵扯到共享数据的变化。:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问。:当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。:因为时序问题,而导致程序异常,我们称之为竞态条件。

2022-11-23 11:41:12 110

原创 linux线程互斥

大部分情况,线程使用的数据都是局部变量,变量的地址空间在线程栈空间内,这种情况,变量归属单个。但有时候,很多变量都需要在线程间共享,这样的变量称为共享变量,可以通过数据的共享,完成线程之。如果多个线程同时要求执行临界区的代码,并且临界区没有线程在执行,那么只能允许一个线程进入该临。发起函数调用时,其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互斥量,:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用。多个线程并发的操作共享变量,会带来一些问题。

2022-11-18 19:29:24 280

原创 linux多线程

在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”一切进程至少都有一个执行线程线程在进程内部运行,本质是在进程地址空间内运行在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程 执行流。

2022-11-16 22:04:21 64

原创 system V共享内存

共享内存让不同进程看到同一份资源的方式就是,在物理内存当中申请一块内存空间,然后将这块内存空间分别与各个进程各自的页表之间建立映射,再在虚拟地址空间当中开辟空间并将虚拟地址填充到各自页表的对应位置,使得虚拟地址和物理地址之间建立起对应关系,至此这些进程便看到了同一份物理内存,这块物理内存就叫做共享内存。IPC_CREAT | IPC_EXCL:如果内核中不存在键值与key相等的共享内存,则新建一个共享内存并返回该共享内存的标识码;如果存在这样的共享内存,则直接返回该共享内存的标识码。返回值:成功返回0;

2022-11-05 20:57:40 498

原创 进程间的匿名通信(匿名管道)

1. 父进程与子进程的读写是有一定顺序的,当父进程没写入数据时,子进程会在read处等待,所以,父进程写入后,子进程read才会读取数据。进程间的匿名通信(匿名管道)2. 当父进程关闭写入的文件描述符,子进程read会接收到信号,读到的字符数为0,依据这个判断结束int main(){ int pipefd[2]; pipe(pipefd); pid_t id =fork(); if(id==0) { //子进程 ,进行读 c

2022-10-31 20:37:36 130

原创 Linux动静态库

使用静态库生成可执行程序会占用大量空间,特别是当有多个静态程序同时加载而这些静态程序使用的都是相同的库,这时在内存当中就会存在大量的重复代码。节省磁盘空间,且多个用到相同动态库的程序同时运行时,库文件会通过进程地址空间进行共享,内存当中不会存在重复代码。静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。在/etc/ld.so.conf.d/路径下,添加新文件,写入动态库的路径即可。

2022-10-28 22:10:13 730

原创 C语言中的缓冲区

缓冲区的本质:一段内存假设没有缓冲区,处理数据采取的方案,直接将数据进行刷新,IO次数较多,从而降低整机的效率。因此:我们在进程中,取一段内存作为缓冲区,集中处理数据,减少IO次数,从而达到整机效率的目的以下为证明过程:上面这段代码中执行结果是怎么的?先输出write,,5秒后在输出,printf fprintf fgets原因:缓冲区是语言层提供的,printf fprintf fgets先进入缓冲区,等待刷新,write为系统调用,没有缓冲区,直接刷新,sleep过后,进程退出,刷新缓冲区常规:特

2022-10-24 20:57:06 876 1

原创 Linux的重定向

这行命令中,隐含了一个1,因此要把标准错误的数据进行输出,则需加个2。标准输出的数据就进入到log.txt 中。2>&1及将标准错误重定向到标准输出。OS提供了一定接口,完成重定向。oldfd拷贝给newfd;

2022-10-24 20:37:22 779

原创 linux系统下的文件操作

flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。进程内部有过管理文件指针的数组,当我们增加打开的文件时,就会从头遍历,找到没有使用的下标,分配给新文件。Linux进程默认情况下会有3个缺省打开的文件描述符,分别是标准输入0, 标准输出1, 标准错误2.O_CREAT : 若文件不存在,则创建它。0,1,2对应的物理设备一般是:键盘,显示器,显示器。pathname: 要打开或创建的目标文件。O_WRONLY: 只写打开。O_RDWR : 读,写打开。

2022-10-19 18:57:03 240

原创 C++的IO流

如果一次输入过多,会留在那儿慢慢用,如果输入错了,必须在回车之前修改,如果回车键按下就无法挽回了。,同时C++标准库还提供了cerr用来进行标准错误的输出,以及clog进行日志的输出,从上图可以看出,cout、cerr、clog是ostream类的三个不同的对象,C++标准库提供了4个全局流对象cin、cout、cerr、clog,使用cout进行标准输出,即数据从内存流向控制台(显示器)。对于自定义类型,如果要支持cin和cout的标准输入输出,需要对进行重载。

2022-10-14 10:17:03 239

原创 自定义类型转化为内置类型(C++)

;Date d;if(d) {}上段代码中,d为自定义类型,但在Date内部实现一个 operator bool(),在进行if判断时,d会进行隐式类型转换。这也是下面代码的原理int a , b;在io流中,也重载了一个类似的函数。

2022-10-14 09:47:56 236

原创 特殊类的设计

final关键字,final修饰类,表示该类不能被继承。请设计一个类,不能被拷贝,请设计一个类,只能在堆上创建对象,请设计一个类,只能在栈上创建对象,设计一个类,不能被继承

2022-10-11 14:39:48 43

原创 C++强制类型转换

reinterpret_cast操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换。dynamic_cast用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)static_cast用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可用。上面这种转换的缺陷会造成精度缺失,及转换类型不明确等问题,因此C++新定义了一套转换风格。在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或者返回值类型与。接收返回值类型不一致时,就需要发生类型转化。

2022-10-10 12:27:23 1114

原创 进程替换(理解Xshell的基本原理)

Xshell在执行我们的命令时,会将我们的命令进行解析,在创建一个子进程(fork),再进行子进程的替换(execvp),父进程等待子进程的退出(wait)用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。例如在这样的一个进程替换中,最后一行的printf不会执行。,从新程序的启动例程开始执行。以下几个为常用的进程替换函数。

2022-10-07 20:17:44 217

原创 智能指针(c++)

如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对 象就成野指针了。shared_ptr的原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共 享。在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减1。如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;unique_ptr的实现原理:简单粗暴的防拷贝。

2022-10-06 20:50:02 387

原创 lambda表达式(C++11)

capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量。[&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量。[&]:表示引用传递捕捉所有父作用域中的变量(包括this)

2022-09-28 20:03:52 369

原创 右值引用(C++11)

左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。// 以下的p、b、c、*p都是左值 int * p = new int(0);// 以下几个是对上面左值的左值引用 int * & rp = p;return 0;}

2022-09-21 20:51:01 300

原创 哈希思想的经典应用(位图,哈希切割)

分别计算每个哈希值对应的比特位置存储的是否为零,只要有一个为零,代表该元素一定不在哈希表中,否则可能在哈希表中。所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。在该问题中,我们可以取40亿个比特位,每个比特位表示一个数,如果该数出现则标记为1,未出现则标记为0。给40亿个不重复的无符号整数,没排过序。将每一个log中的IP通过哈希函数映射成一个整数%100,分到100不同的小文件,在进行计数。我们采取类似位图的思想,将一个字符串通过相同的方式映射成一个整数,再将对应的下表,标位1。

2022-09-20 17:37:07 339

原创 哈希表(c++)

最好的情况是:每个哈希桶中刚好挂一个节点,再继续插入元素时,每一次都会发生哈希冲突,因此,在元素个数刚好等于桶的个数时,可以给哈希表增容。如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功。1.桶的个数是一定的,随着元素的不断插入,每个桶中元素的个数不断增多,极端情况下,

2022-09-13 20:28:15 306

原创 fork函数

另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。(查看进程的退出码)最后,父进程派给子进程的任务完成的如何,我们需要知道。子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。当正常返回的时候waitpid返回收集到的子进程的进程ID;

2022-08-25 16:43:09 92

原创 linux进程概念

CPU处理数据的速度远远大于其他设备,根据木桶效应,计算机的效率就受到限制,因此,前人就设计出内存,让内存作为CPU与外设交互的中介,适配外设和CPU速度不均的问题。I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。

2022-08-23 20:47:36 83

原创 RBTree (红黑树)

## 红黑树的概念红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。## 红黑树的性质1. 每个结点不是红色就是黑色 2. 根节点是黑色的 3. 如果一个节点是红色的,则它的两个孩子结点是黑色的 4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点 5. 每个叶子结点都是黑色的...

2022-08-09 14:46:17 308

原创 AVL 树

一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树: 它的左右子树都是AVL树 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结点,其高度可保持在$O(log_2 n)$,搜索时间复杂度O($log_2 n$)。AVL树就是在二叉搜索树的基础上引入了平衡因子,因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步:1. 按照二叉搜索树的方式插入新节点2. 调整节点的平衡因子...

2022-08-09 13:29:38 205

原创 搜索二叉树

情况d在它的右子树中寻找最大的节点,用它的值填补到被删除节点中,再来处理该结点的删除问题–替换法删除。如果我们要删除7,6等叶节点,直接删除即可,但如果我们要删除2,5等非叶节点又应该如何做呢?情况b删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点–直接删除。情况c删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点–直接删除。d.要删除的结点有左、右孩子结点。b.要删除的结点只有左孩子结点。c.要删除的结点只有右孩子结点。a.要删除的结点无孩子结点。......

2022-08-01 16:56:05 118

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除