Skip to content

Archive

Category: Tech article
2011年,我曾经写过一篇《不争气的geometry shader》,里面比较了在当年的多个平台上跑多种 render to cubemap的方法。经过帧数的对比,得出的结论是geometry shader会造成严重性能问题,甚至还不如渲染6遍的结果。2012年,同样的测试在GTX 580和GTX 680上重新跑了一遍,发现GTX 680上geometry shader终于比渲染6遍更快。 到了2019年,情况又会有什么变化呢?我们再来跑一次。说是2019年,其实我的电脑是2015年配的,Intel i7-4790的CPU,NV GTX 960的GPU。系统是Win10 19H1。但因为GTX 960和D3D 11.4支持在GS之前的stage输出SV_RenderTargetArrayIndex,我们其实不需要GS也能render to cubemap或者render to texture array。所以我们需 ...
最近这几个版本经常出现一些比较大的改进,需要跨多个版本才能实现。所以一直没写改进的文章。现在4.14很快就要发布了,逼自己把渲染部分的重要变化总结一下吧。 Cluster shading成为默认渲染框架 在4.11里,曾经有个实验性质的cluster shading。那时候性能还不如tile based shading,所以也就默认关闭。在4.12中,cluster shading经过了一系列的优化,终于在性能上赶上来了。所以也就能取代tile based shading,成为默认的渲染框架。 对Cluster shading的优化主要集中在cluster如何划分上。经过对不同参数组合的尝试,找到最佳的一组。不过本来的想法是用pixel shader实现shading的部分,而不是compute shader。那样的话就能让不支持compute ...
上一篇总结了SMAA和Clustered shading这两个改进,本篇将讲一下如何支持HDR显示设备,以及一些性能优化。 HDR显示设备 HDR电视已经不是什么新鲜事了,HDR显示器也已经问世。这些HDR显示设备,能达到的最大亮度远超过传统显示器。不过这里存在很大的误解,很多人以为HDR显示器等于在显示器里做tone mapping。然而并不是。HDR显示器并不需要做额外处理,直接拿HDR数据去显示。而tone mapping等,仍然是在程序里做。 传统的后处理流程 原先KlayGE里的post process是这样的。 HDR的渲染结果进入ACES tone mapping,变成LDR的数据,在经过SMAA、gamma矫正和颜色调整后输出到LDR显示设备。 HDR显示设备的重要参数 首先需要提一下HDR显 ...
上一篇总结了VDM、动画导入、双面材质、矢量纹理这几个新功能,本篇将概括地讲一下抗锯齿和渲染框架上的改进 SMAA 原先KlayGE里一直用的FXAA。而FXAA虽然非常快,但有个很大的问题就是会让画面整体变得模糊。而后来出现的SMAA则可以解决这个问题。这里参考的是http://iryoku.com/smaa/。 SMAA和FXAA都是MLAA的一个GPU算法,SMAA注重的是把原算法搬到GPU,FXAA注重的是把原算法的思想简化后在GPU上做的尽量快。所以两者的基本算法还是差不多的,都是通过一个像素和周围像素的信息,恢复出局部几何,确定如何AA。但SMAA的搜索更为彻底,所以不是遇到边就模糊了事。这里可以看一组对比。 这是FXAA的结果。线条不连续,模糊。 这 ...
在这里总结一下在KlayGE 4.11中对渲染的一些改进。 VDM粒子渲染 通过Variance Depth Maps的方法,粒子渲染的速度是以前的近10倍。具体内容在用VDM加速粒子渲染一文中讲解。 动画导入 这部分其实去年就由speakfool完成了雏形,现在终于有时间集成进来了。这个改进分两部分。第一个是在MeshConv工具里,加入了对骨骼动画的导入支持。可以从fbx等格式直接导入骨骼动画。第二部分是在MtlEditor里显示骨骼,作为辅助。 双面材质 原先在导入模型的时候,遇到双面材质,会生成两倍的三角形,一正一反。而现在直接支持了双面材质,遇到这样的材质,在渲染的时候关闭背面剔除,并把normal反一下。有了双面材质,树叶这样的物体就很容易 ...
很多跨平台游戏引擎都有统一shader的需求。比如KlayGE从建立伊始,就强调一份代码跨多个平台,shader代码也不例外。如果需要对不同平台都分别写一遍shader,那样的工作量和可维护性都很糟糕。 既然有这样的需求,就必然会在技术上遇到一个问题,如何把一份代码编译成不同API上的shader。从目前的API上,我们至少需要应对HLSL/GLSL/ESSL,以后还有Vulkan加入战团。这里就打算探讨一下跨平台shader编译的情况,希望对大家有启发意义。 过去 刚有shader高级语言的时候,Cg是几乎唯一的shader语言。后来才在D3D9时代衍生出了HLSL,再往后有了GLSL和ESSL。所以自然而然一开始都会从Cg入手。在KlayGE发展的过程中,这还分为两个阶段。 运行中 ...
(这个功能本来应该是KlayGE 4.10就有的,但因为时间原因,拖过了发布时间。所以变成4.11里第一个实现的功能。) 粒子系统在游戏引擎里用得非常普遍。而粒子系统的渲染本身,却是一个不怎么快的过程。因为大量粒子会叠在屏幕上,给填充很大的压力。 加速的方向 既然是填充率的瓶颈,那显而易见的加速方法就是缩小分辨率。常见的做法是把粒子渲染到一个半分辨率的纹理上,在根据depth的分布混合到全分辨率。在KlayGE里,shadowing是就是用这个方法加速的。如果插值后的depth更接近于point采样的depth,就填充point采样的颜色,否则填充linear采样的颜色。这么做的话,大约能达到原先4倍的速度。GPU Gems 3的High-Speed, Off-Screen Parti ...
上一篇讲了tone mapping的改进。作为引擎的一个长期议题,优化是不可缺少的。本篇就讲讲在4.10中引入的新优化。 CPU端 在profiler里看到的占据CPU耗用第一名的一直是驱动。原先一直没在意这个,前一阵自己看了一下,发现前几位的好几个都是在SceneManager里,而且都和渲染队列相关。具体情况是,在每一帧确定渲染队列的时候,会执行一遍这样的步骤: 扫描一遍场景里的所有SceneObject,根据它的Renderable的类型建立一个从Renderable到SceneObject列表的unordered_map,每个物体作为那个Renderable的instance 把unordered_map中的Renderable建立一个队列 渲染这个队列 销毁unordered_map 所以其实这里的unordered_map只是 ...
上一篇讲了新的材质系统。本篇将讲tone mapping的改进。 Tone mapping的进化 KlayGE早在2006年的时候就引入了HDR的流水线。和当年的其他引擎一样,HDR的内容经过渲染,需要通过tone mapping转成LDR之后送去显示。这时候,tone mapping的质量就可以决定最后的画面细节度和对比度。 在KlayGE的发展过程中,tone mapping这个看似简单的步骤经历了多次进化。 Reinhard 早期的普遍做法是一篇叫做Photographic Tone Reproduction for Digital Images的论文,大家就用作者的名字称它为Reinhard tone mapping。这是个经验公式,把HDR到LDR的变换简单的描述了出来。 float3 ReinhardToneMapping(float3 color, float adapted_lum) { con ...
好久没写这样的系列了,上一次总结渲染的改进,还是4.5的时候。最近,又对KlayGE的渲染做了一些系统性的修改,所以在这里总结一下。 材质系统 原先的材质系统里,diffuse颜色和specular颜色是分开的。要放到GBuffer里的时候,specular颜色就剩下亮度,之后跟光的亮度操作后,从diffuse的颜色恢复出specular颜色。这只是一个情非得已的hack,因为G-Buffer里只有4个通道可供使用,放不下diffuse和specular颜色。 2015年的Physics and Math of Shading里,详细分析了导体、绝缘体、半导体的diffuse和specular分布,得到的结论是,只需要有个albedo的颜色(3通道)以及一个metalness(1通道),就已经足够。因为导体的diffuse是0,绝缘体的s ...