屏幕空间(SreenSpace)的想象力

在写这篇文章时,我特意去Wiki上搜了一下ScreenSpace, 可能是由于太过直白的缘故,并没有找到标准的定义。 不过他的定义是显而易见的,屏幕空间的所有的信息都是与屏幕上的像素有关的,而不是和场景中的几何有关的信息都叫屏幕空间,这一点其实很像是Pixel和Fragment的区别。pixel是定义在屏幕空间上的,而Fragment是定义在三维空间上的。 举个最简单的例子,我们从相机原点射出一条射线,然后穿过两个不透明物体。这两个交点,在进行光栅化时就是2个Fragment, 但是最终渲染到屏幕上……

一些对辐射度量学的理解

随着硬件性能的提升,PBS/PBR已经越来越成为一种趋势。 Unity内置的standard shader都已经默认使用PBR算法。 而学习PBR过程中,有一门必提的知识是“辐射度量学”。 本来我以为我都学会了,毕竟path tracer都写出来了,并且效果看起来很正常。 但是最近在学习全局光照时,突然对“辐射度量学”突然产生了两个疑惑。 光线在传播过程中,Radiance是如何体现出,能量随着距离增加而衰减的? 回忆在写path tracing时,代码并没有刻意去计算距离对光线能量的衰减。 而从数学公式上看,在计……

深度缓冲和半透明渲染

在场景渲染方式上,一般分为“不透明渲染”和“半透明渲染”。 “不透明渲染”意思是,如果A物体被B物体挡住,那么A物体将完全不可见。 至少有两种方式达到这种效果(假设相机的朝向为Z轴正方向): 由于屏幕上每一个相素都是由场景中某一世界坐标(Fragment)投影得到,在绘制时以Fragment在相机空间内按Z轴从大到小进行绘制, 写入颜色值时直接覆盖FrameBuffer中的颜色值。 物体以任意顺序渲染,但是在渲染某一个Fragment时,会将其在相机空间的Z坐标写入一个叫做深度缓冲区的地方,在……

Mysql的间隙锁

学习Mysql, 总会有一座绕不过去的大山, 那就是锁。理论上,锁的花样再多,也超不出操作系统课上讲的那些范畴,但是Mysql锁让我翻车了。 在Mysql中锁的粒度可分为:表级锁,行级锁,间隙锁 三种。表级锁和行级锁都没什么太难理解的地方。只有间隙锁我无法准确理解其设计意图,而且我试验下来的现象让我觉得很诡异。 那么为什么会有间隙锁这种东西呢,按大部分能查到的资料表示,间隙锁的引入是为了解决在RR隔离级别的幻读问题。 下面来看一个实例,首先创建一个Table: Create Table: ……

更新一些GPU相关知识

在学完并实现路径追踪之后,即使增加了多线程渲染,在SPP=1024的情况下,依然需要30+分钟才能渲染一帧。 为了更快的渲染速度 ,我试图通过使用GPU的CUDA SDK来加速渲染。然而测下来竟然还没我的CPU跑的快,一方面我没有更好的显卡,另一方面我也不太确定是不是我CUDA使用错误所致。再加上就算使用GPU也不可能达到每帧秒级渲染。于是GPU的学习就搁置了。 然而在最近研究Splat地形渲染方案时, 我无意间发现了一个现象。测试地形为4层混合,在所有Texture都不开Mipmapping的情况下, FPS……

2020

写年终总结前,照例翻了一下今年以来的blog, 意外的发现2019去年的年终总结同样拖到很晚。不过今年之所以拖这么晚,大部分原因是今年特别冷。坐到电脑前只顾着瑟瑟发抖了,哪还有心情写年终总结。 翻了一下去年的目标: 《概率论及其应用·卷1》 《具体数学》 《计算机程序设计艺术》 重新温习一下以往学习过的知识,看看能不能再次打破一下这几年形成的思维定式 总的来讲 有部分完成。 《概率论及其应用·卷1》看了一大半,该看正态分布了,不过现在应该差不多忘光了。 《具体数学》……

地形渲染之爬过的坑

目前我们采用TiledMap的菱形模式来编辑地形,然后再导入到Unity, 将TiledMap的每一个菱形以Unity中的Quad为单位来拼出来。 以目前我的知识水平来看,这么做至少有4个问题。 Quad是以正方形为单位拼接的,而我们在TiledMap中每一个菱形是以Quad为单位渲染而成,客户端在使用Quad进行渲染时,为了表现的像个菱形,每两个Quad都会在顶角进行重叠,这需要我们美术出的图四个角Alpha通道都是0,这会增加无用的Overdraw。 为了降低纹理大小,整个地形都是由有限个基础Tile相互叠加来生成……

Lua5.3 GC源码阅读(5)

这篇内容并不是上篇提到的关于弱表实现的分析。而是最近有位同学与我探讨了一些Lua的GC时,发现了两个以前从没注意过的智慧闪光点。 首先是luaC_fullgc的实现. [c] #define keepinvariant(g) ((g)->gcstate <= GCSatomic) static void entersweep (lua_State *L) { global_State *g = G(L); g->gcstate = GCSswpallgc; lua_assert(g->sweepgc == NULL); g->sweepgc = sweeplist(L, &g->allgc, 1); } void luaC_fullgc (lua_State *L, int isemergenc……

实现一个数据库存储队列

大约在在两年前, 我就意识到定点存库的必要性,并在今年应用到实际项目中了。 从历史经验来看,将数据库存储行为收集并合并起来,确实可以极大的降低抽象代码过程中的心智负担。我们在写代码时已经不需要考虑数据库的存储频率,反正最终所有修改过的数据,只会存一次。 从我意识到定点存库的必要性之后,我就一直对当时的抽象不太满意,在最原始的抽象中,刷新数据是需要业务逻辑来完成的。而数据库合并模块本质上只做了去重而已,这也就是说,其实大量定点存储代码实际是散落在业……

再学计算机图形学入门

在网上查资料时,无意间发现了一门课叫《现代计算机图形学入门》。于是事隔将近3年后,我再一次尝试图形学入门。这次学习从8月20号开始,一直到10月11日,约持续了一个半月。 但是这次的学习体验和上次是完全不同的,最直接的感受有3点。 《现代计算机图形学入门》要比《3D游戏编程大师技巧》中的内容现代的多,内容和知识体系都更全面。 现代计算机的性能远超《3D游戏编程大师技巧》著作当时,因此很多为了提高性能的Trick已经没有必要使用。这会使我们花费大量精力在局部细节……