自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 LuaJIT源码分析(三)字符串

由于每次新建字符串时都需要计算一次hash,这个函数调用会比较频繁,因此它是一个稀疏的hash函数,内部实现使用了lookup3 hash算法,只会取字符串中的常数个字节进行计算,所以函数的运行是一个常数的时间。lua的字符串是内化不可变的,也就是lua字符串变量存放的不是字符串的拷贝,而是字符串的引用。tab字段保存了所有字符串,它是个链表数组,每个新建的字符串先根据hash算法计算出自身的hash值,再根据当前StrInternState的mask,得到数组的索引,如果已经有元素,就插入到链表的头部。

2024-05-02 16:36:15 904

原创 Unity DOTS中的baking(五)prefabs

LoadedPrefabs则是一对一的HashMap,它保存了当前已经加载完成的prefab信息,包含引用计数,prefab对应的Entity。的Entity,这与前面恰好相反,它表示所有需要取消加载prefab的Entity。可以看到,这里保存了prefab对应的guid,后续是通过guid来进行prefab加载的。发起加载请求,该方法返回一个表示prefab当前加载状态的Entity,如果prefab加载完成,Entity上会添加一个。它负责prefab引用计数的管理,加载和卸载prefab的操作。

2024-04-24 00:47:08 932

原创 LuaJIT源码分析(二)数据类型

nil和bool类型是值类型,无需gc管理,而light userdata的定义就是外部管理的对象,只是将指针传给了lua,所以也不受lua的gc管理。的实现也比较巧妙,它不是直接去判断TValue是否为一个非NaN的double,而是尝试取出它的itype,如果itype比最后一个定义的LJ_TISNUM都还要小(注意itype的定义都是取反过的),那么说明它必定不是一个合法定义的TValue类型,也就只能是个double了。换句话说,只要满足这个条件,剩下的51位尾数,完全可以用来编码其他的数据。

2024-04-01 23:14:22 973

原创 Unity DOTS中的baking(四)blob assets

举个通俗的例子,假如第一次分配了12字节的struct内存,而第二次要分配的struct,总共64字节,但它是8字节对齐的,那么这里就不会紧挨着从12字节的位置继续分配,而是计算8字节对齐的整数倍,也就是16字节处,开始分配这个struct。allocIndex和offset表示本次分配的结果,allocIndex表示分配的内存在第0号chunk上,offset表示分配的内存首地址相对于chunk的首地址偏移量,这里为0。直到此时此刻才会被填充。那如果需要分配的内存,超过一个chunk的大小,要怎么办呢?

2024-03-26 22:48:30 955

原创 LuaJIT源码分析(一)搭建调试环境

浏览这个脚本,可以发现LuaJIT的编译分为三个部分,首先是build出一个minilua,它是lua原生代码的一个子集,用来判断当前平台是32位还是64位,并执行lua脚本并生成平台相关的指令;最后编译lua的各种lib,然后生成最终的LuaJIT。另外,脚本在编译结束时,会执行一些清理工作,把中间生成的代码,以及编译产生的obj都会删除掉。然后,我们在src同级目录下新建一个目录,用来存放vs工程,在vs中新建一个empty console C++工程,然后把src目录的头文件和源文件都添加进去。

2024-03-03 14:22:09 1219

原创 Games 103 作业四

先要找到水面与方块相交的区域,然后计算出它们的low_h,这里计算相交可以使用Unity内置的Bounds.IntersectRay,每个水面格子从底部发射一条射线,然后判断是否和方块的包围盒相交,相交的距离就是low_h。第二步,当玩家按下r键时,需要在水面随机落下一个水滴,那么该位置的水面高度需要增加,为了避免水面溢出,还需要把该位置附近的水面高度减小,这样保证整体的水量不变。首先第一步,在update函数的开头,加载水面mesh的高度,然后在update的结束时,把计算后的高度更新到mesh中。

2024-02-24 15:52:26 389

原创 xlua源码分析(六) C#与lua的交互总结

我们分析了xlua对struct类型所做的优化,本节我们系统性地梳理一下xlua中C#与lua的交互。所谓C#与lua的交互,其实主要就分为两部分,第一是往lua层中传数据,第二则是从lua层中取数据。

2024-02-21 23:54:17 855

原创 Unity DOTS中的baking(三)过滤baking的输出

从代码中可以猜测出,这里的变化指的是conversation world和shadow world之间的diff,conversation world就是baker和baking system运行的地方,而shadow world则是上一次baking环节输出的拷贝,Unity使用这个shadow world,与当前baking的输出进行对比,只把不同的components和entities拷贝到main world,然后再更新shadow world为当前的conversation world。

2024-02-03 21:34:47 1728

原创 xlua源码分析(五) struct类型优化

而数据传输的逻辑,稍微不太相同,tolua是使用lua函数进行数据传输,例如Vector3,tolua可以通过一个get函数直接返回3个float*给C#层,也可以通过一个new函数直接使用x,y,z三个参数构造出一个lua层的struct,pack和unpack的逻辑都放在了lua层里。函数是在C层实现的,那其实很简单了,就是把userdata作为要访问内存的首地址,加上偏移量offset,执行memcpy即可,如果是get,就是从userdata拷贝到value,再push到lua栈;

2024-01-15 21:03:01 1141

原创 STL tuple源码分析

STL还提供了两个便捷的函数创建tuple,一个是make_tuple,一个是tie,两者的区别在于返回的tuple类型有差异,一个返回参数类型为值类型的tuple(除非传入的参数是reference_wrapper),一个返回的是引用类型的tuple。如果tuple的元素个数不止一个,那结果直接就是true,而只有一个元素时,需要进行一系列的判断,首先两个tuple的类型不能相同,然后,传入的tuple参数不能直接构造tuple的参数类型,也不能直接convert到tuple的参数类型。

2024-01-14 13:17:38 873

原创 Unity DOTS中的baking(二)Baker的触发

这个事情是必要的,比如我们给当前挂有MyAuthoring脚本的GameObject建立一个父节点,如果父节点的transform发生变化,或者层级关系发生了变化,那么子节点的world transform必然也发生了变化,理应就要再次触发baking。,可以看到这里会再去获取一下记录的GameObject身上最新的component,如果和之前记录的component instance id不同,说明component经历了从无到有或者从有到无的过程,它已经不是之前的那个对象了,此时就会返回false。

2024-01-03 23:55:15 1112

原创 xlua源码分析(四) lua访问C#的值类型

与tolua相比,两者都实现了无gc的值类型传递。而tolua的值类型,默认会在lua层实现一份类似的代码,lua层在调用时,完全是走的lua层的逻辑,不会涉及拷贝数据到C#层的逻辑,只有作为函数调用参数和返回值时,才涉及到数据的拷贝。这样做的好处,就是避免了在函数调用过程的频繁的数据拷贝开销,不方便的地方就是需要在lua层自己实现一遍C#的值类型,而使用wrap则只需要自动生成代码即可,没有额外的开发负担。比如这里,把一个C#对象push到lua层,意味着lua层需要知道对象的类型id,也就是C#层的。

2023-12-25 23:37:53 503

原创 Unity DOTS中的baking(一) Baker简介

baking是DOTS ECS工作流的一环,大概的意思就是将原先Editor下的GameObject数据,全部转换为Entity数据的过程。baking是一个不可逆的过程,原先的GameObject在运行时不复存在,都会变成Entity。baking只会在Editor环境下运行,而且只会对SubScene中包含的GameObject进行烘焙。

2023-12-10 22:08:34 291

原创 Games 103 作业三

模拟很不稳定,房子直接飞了。作业中为了避免这一情况,使用了拉普拉斯平滑。作业三的内容主要就是实现一下FVM。我们按照文档中的步骤,第一步就是去独立地更新mesh的速度和位置,在初始化每个顶点的受力时,需要考虑到重力的影响。下面再看一下附加题部分,其实就是根据PPT的第35页,换一种方法计算P。接下来要考虑mesh的碰撞处理。在作业给的场景中,就只有一个简单的floor。其实这个时候房子已经可以跳动起来了,只是。那么问题就只剩计算这三个偏导数。的函数(注意,这里PPT给的公式有误)根据PPT的第25页,有。

2023-12-06 21:20:22 112

原创 STL pair源码分析

不难发现,只要传入pair的两个类型任意一个的默认构造函数是explicit的,那么pair的这个默认构造函数就是explicit的,这一点也很好理解。首先是一开始template的声明,这里加了一个enable_if_t<bool, T>,它用来进行编译检查,即只有第一个模板参数推导出来结果为true时,后面的T才生效,也就是说,如果检查失败,就不存在对应的T,这里的template声明就是非法,编译期间就会报错。有点令人意外的是p2,它传入的参数明明是int&,但pair的参数类型却是int。

2023-11-25 15:57:49 440

原创 xlua源码分析(三)C#访问lua的映射

XLuaTestInvokeLuaICalcBridge是继承自ICalc接口的类,它负责实现ICalc的功能,也就是我们一开始提到的一个PropertyChanged的event +=和-=操作,一个Add方法,一个Multi属性,以及下标操作符。代码逻辑很简单,就是准备调用环境,然后把C#的参数push到lua层,然后pcall调用,然后从lua栈中取出返回的结果,由于lua是弱类型的,无法事先知道返回值的类型,所以这里只能使用通用的GetObject函数对lua的返回值进行类型转换。

2023-11-18 11:52:31 1173

原创 xlua源码分析(二)lua Call C#的无wrap实现

从命名中也可看出,field对应的是C#的字段和方法,getter对应的是C#的get属性,setter对应的是set属性,meta就是对外设置的metatable了。和tolua一样,xlua也会把C#对象当作userdata来处理,每个要push到lua层的C#类型都有唯一的type_id,对应到不同的metatable,用来定义userdata的行为。并且,除了值类型和枚举类型之外,所有push到lua层的C#对象,都会在C#层缓存,这一点也是和tolua一样的,甚至缓存的数据结构也大差不差。

2023-11-04 11:16:36 1447

原创 Games 103 作业二

难度相对于作业一来说要简单一些,在文档中基本把步骤都写清楚了。这里的f就是重力和弹簧间的弹力。然后我们按照文档的步骤一步一步地来。注意0号顶点和20号顶点是不参与更新的,它们相当于就是定死了位置。作业中是固定的32次迭代次数,这里的break判断就可以省略掉;然后我们再看下PBD的实现。迭代完别忘记更新下V,这里要使用+=,因为一开始算。如果你觉得我的文章有帮助,欢迎关注我的微信公众号。第二步就是计算梯度。这里的梯度就是PPT里的。作业文档中给了近似求解的方法,我们就不用算。

2023-10-28 14:13:18 173

原创 xlua源码分析(一) C# Call lua的实现

与tolua一样,lua函数被C#引用时,都会存放到registry表中缓存,同时C#获取到该函数的reference之后,会生成一个负责生成具体委托的包装类对象,这里就是DelegateBridge,它是以弱引用的形式存放在delegate_bridges里的,这里使用弱引用,因为delegate_bridges只负责查询,真正引用它的是具体的委托。另外,xlua的DoString是有返回值的,返回类型是object数组,也就是C#可以执行任意的lua代码,并且直接获取到lua代码的返回值。

2023-10-21 13:45:04 255

原创 Step 1 搭建一个简单的渲染框架

另外,由于GPU指令的执行对CPU来说是异步的,因此还需要一个ID3D12Fence用于同步。在渲染结束之后,同样我们要把当前back buffer的状态切回渲染前的,如果是多缓冲要切到下一个可用的back buffer,执行掉中间产生的所有渲染指令,显示到屏幕上。初始化过程中我们需要创建若干back buffer和一个depth buffer,这两个buffer的创建方式有区别,但它们本质上都属于资源,因此给它们各自一个类,然后共同继承D3D12Resource这个类,这个类包含一些对资源的通用操作。

2023-10-14 17:04:31 208

原创 tolua源码分析(十一)代码生成

接下来调用的是GenRegisterFuncItems函数,这个函数就是扫描类的导出方法,过滤掉类的重载操作符方法,这部分需要特殊处理。第一部分就是普通导出类的注册过程,第二部分是对所有用到的委托类型增加导出函数,这个与上文类似,就是方便lua层直接构造委托,最后一个部分是preload,实际上是一个延迟加载逻辑,这里面的导出类,不会在Bind的时候就注册,而是在lua层调用require的时候,才会注册进来。接下来就是遍历这个BindType类型的list,对每个type生成对应的wrap文件。

2023-09-17 19:17:01 158

原创 ComPtr源码分析

可以看到,使用ComPtr之后,我们无需对A类指针p进行计数管理,ComPtr会帮我们维护好p的引用计数。当p1和p2离开作用域时,会对p的引用计数减一,当为0时触发真正的release,这里就是打印一句log。对于参数为右值引用的构造函数,根据语义,需要把传入ComPtr的原始指针进行转移。可以看到InternalRelease函数会将持有的原始指针置为空,并调用原始指针的Release函数返回当前的引用计数。这里B类型继承A类型,那么B类型的指针就可以安全地转换为A类型的指针,编译就能顺利通过了。

2023-09-10 14:20:56 123

原创 Games 103 作业一

首先,我们需要对兔子mesh中的所有顶点进行遍历,找到与墙平面发生碰撞的所有顶点,检查任意顶点是否与墙平面发生碰撞也很简单,就是计算点到平面的距离,若为负值即发生碰撞,也就是PPT中的。方法了,它的原理就是让每个顶点先分别自由地计算各自的速度和位置,然后再根据刚体的约束,对顶点进行调整,得到每个顶点最终的速度和位置。下一步,我们计算发生碰撞的点的平均值,作为。场景中有个兔子的刚体,我们要模拟的就是给兔子一个初始的速度,让其在重力的影响下,与两堵墙发生碰撞的效果。之后,就可以根据它计算出当前的冲量。

2023-08-19 12:44:07 124

原创 tolua源码分析(十)struct

向lua层传递struct,就是将C#的struct拆分成若干基本类型,依次push到lua栈,然后调用lua层对应struct的new函数,创建lua层的struct;这么做的原因是在lua层使用struct的方法时,不需要跑到C#层去调用C#的接口,对于struct来说,它往往只是一个保存数据的结构,包含的方法都比较简单,lua层去实现完全可以胜任。函数,所以这里的push实际上是把C#的Rect的每个数据成员都拆出来,作为基本类型挨个push到lua层,然后调用lua层的。

2023-07-30 15:07:27 169 1

原创 tolua源码分析(九)反射

由上文可知,typeof(Vector3)返回的是C#的Type类型,代表C#的Vector3,那么调用MakeArrayType得到的就是Vector3[]的Type类型。这里lua代码第2行也调用了全局的typeof,而这里传入的不是string,Vector3我们之前提到过是lua层自己实现的一个table,对于table类型来说,如果type缓存中不存在,则调用的是C#的。由于这里反射的函数是静态无参并且没有返回值的,因此lua层并不需要提供额外的参数给C#,也不需要从C#层获取返回值信息。

2023-07-08 16:19:00 295

原创 tolua源码分析(八)lua扩展继承C#类

之所以对所有的vptr table都设置同样一个这样的metatable,其原因是它们的逻辑是完全相同的,唯一不同就是各自绑定的userdata不同,因此只需要在metatable的元方法中,把vptr table绑定的userdata传进去就行了,没必要为每个vptr table都设置一个单独的metatable。当然,如果访问的是子类没有重写过的父类方法,则这里的判断都不会命中,会进而获取userdata的metatable,也就是前面我们所说过的class table,进行递归查找。

2023-06-17 15:55:41 300

原创 tolua源码分析(七)带out参数的C#函数

之前我们提到过,把C#层的Ray push到lua层是不会产生gc的,那么反过来,从lua层取出C#的Ray是如何做到没有gc的呢?可以看出,一个C#的Ray其实被拆成了6个float,传到了lua层,然后lua层重新组装一遍,成为lua层的Ray。这个函数会把C#层定义的所有Layer传递给lua,在lua层新建一个Layer table,key为name,value为layer的值,这个值是一个int,所以最后一个参数的类型也是number。上,在lua层真正用到时,才会触发注册流程。

2023-06-10 15:29:55 303

原创 SRP中的光照

平行光源传入的是向量,用float4来表示,最后一位分量w是0,而点光源传入的是位置,用float4表示的话最后一位分量w是1。最后是聚光灯,它更复杂一些,既需要方向信息,也需要位置信息。除此之外,它还有个能被照亮的最大角度,超出该角度范围里的物体是不会被照亮的,这个衰减是过渡的,我们假设聚光灯方向与聚光灯到物体的方向夹角为。对于平行光来说,它的光照方向取决于它的local z轴的方向,因此我们只要取出这个向量即可,由于Unity的向量是列向量,所以矩阵的第2列(下标从0开始)就是这个local z轴。

2023-06-03 13:49:25 183

原创 tolua源码分析(六) C#委托使用lua函数的机制实现

这个最常见的用法要数UI了,例如C#的UI Button上有个ActionClick的委托,它会在Button被玩家按下的时候触发,而触发后具体执行的逻辑我们希望在lua层实现,因此我们就需要在lua层,往这个C#委托上绑定函数。两个方法,可以看出带有self的方法,就是把构造时传入的self,当作函数的一个参数压入lua栈,给lua层调用,这就支持了lua层带有self语法糖的函数,这样的函数也可以绑定到C#的委托上。的调用,它接受一个listener的参数,这个listener是从C#层传入的,它是。

2023-05-27 13:03:51 621

原创 tolua源码分析(五)lua使用C#的enum

本节我们主要探讨在lua中如何使用C#的enum。

2023-05-20 13:14:19 382

原创 SRP中的shader

跟绘制的物体还有关系,因此它需要每次绘制时都要更新一次。在Unity中使用SRP时,我们需要使用HLSL来编写shader。HLSL语法与GLSL类似,在使用HLSL的地方我们需要用。最后,我们希望在SRP中使用gpu instancing的方式来绘制这些gameobjects。接下来,我们希望这些gameobject拥有不同的颜色,显然颜色这个是跟随材质变化的,因此我们要把它放到。如果你觉得我的文章有帮助,欢迎关注我的微信公众号。另外,这两个矩阵的更新频率实际上是不同的,然后还要在shader中引入。

2023-05-14 15:56:43 367

原创 tolua源码分析(四)lua调用C#函数机制的实现

上一节我们讨论了C#是如何访问lua变量的,这次我们将研究lua是如何访问到C#函数的。

2023-04-09 15:51:10 482

原创 tolua源码分析(三)C#访问lua变量的机制实现

上一节我们讨论了C#是如何获取并调用到lua定义的函数,这一节我们更进一步,来看看如何让C#可以访问lua定义的变量的。

2023-03-25 15:06:27 244

原创 Unity的SRP

Unity从2018开始添加了对可编程渲染管线的支持,使得我们可以从头开始设计自定义的管线。我们先从设计一个最小的可编程渲染管线开始,一步一步了解Unity的SRP。

2023-03-11 13:33:38 607

原创 tolua源码分析(二) C#调用lua函数的机制实现

本节我们来深入理解tolua是如何实现C#调用lua函数的。

2023-03-04 16:19:36 578

原创 tolua源码分析(一) tolua的初始化流程

tolua是一个Unity静态绑定lua代码的解决方案,本文是源码分析系列的第一篇,主要围绕tolua初始化流程相关的代码进行分析。

2023-02-18 16:50:40 546

原创 用Unity实现FXAA

FXAA是现代的常用抗锯齿手段之一,这次我们来在Unity中从零开始实现它。

2022-12-04 14:25:14 780

原创 用Unity实现景深效果

景深也是一种非常常见的后处理手段,它用来模拟相机拍摄画面的效果。今天我们讨论如何在Unity中实现它。

2022-09-17 23:04:29 3366 1

原创 用Unity实现Bloom

Bloom是一种常见的后处理效果,用来给发光的物体增加光晕。接下来让我们看看如何在Unity中实现它。

2022-08-29 00:47:25 1561

原创 用Unity实现displacement

除了使用normal mapping和parallax mapping以外,我们可以利用tessellation,来真正地增加物体表面细节的丰富程度。

2022-08-08 22:45:04 1098

空空如也

空空如也

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

TA关注的人

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