程序化地形生成-2-性能优化
性能优化的需求 自从实现了程序化地形生成的那个ShaderToy上的Demo之后,我对它的性能表现一直不太满意,随随便便跑一下我的GPU就直接拉到100%了,电脑风扇呼呼的。做了很多次大大小小的优化,最后发现瓶颈还是在对地形的光线步进计算上,不把这个问题解决掉的话这个场景的性能怎么样都无法达到令我满意的程度。 于是我一直在寻找类似的场景,寻找有什么光线步进的方法能够满足我的要求:首先它必须是要针对实时随机生成的地形,也就是说不能是针对高度图或者其他预处理过的地形数据;其次它需要快,至少能够在我这台笔记本上(3070ti显卡)能够保持50%以下的占用率;最后就是这个光线步进算法需要有一定的精度,但是要求不会很高。 最后我在ShaderToy上找到了一个非常棒的例子,来自Dave_Hoskins。 Dave的Demo也是做了地形的渲染,他的场景比我复杂很多,但是这个更为复杂的场景在我的电脑上运行的时候,它的GPU占用率(分辨率768X432)只有35%左右,远低于我的demo让我大为震撼。 于是我开始研究它的光线步进的逻辑,如下: 12345678910111213141516171...
程序化地形生成-2
距离上一篇将程序化地形生成的教程也已经过去了一段时间了。前段时间一直有其他事情需要忙,现在终于有时间继续之前未完成的工作了。 丰富地形 上一篇教程我们已经创建出了绵延的山脉,如下图所示: 看起来似乎是有那么点意思了,但是这样的山脉效果还是太单调了。 接下来我们就计划丰富一下这个场景。 增加绿植 我们场景中的山光秃秃的,很像是沙漠,也很像火星上的地貌。 我想给场景增加一些层次,一些生机,因此我打算将山的一部分渲染为绿植部分。 那么如何确定哪些部分是绿植,哪些部分是裸露的山体呢?根据地形表面的法线可以做一个简单的判定:法线的y分量越大,也就是面向上的分量越大,表明这个面更平,因此有绿植是更合适的;反正则表明这个面更加陡峭,更适合作为山体表现。 1234567891011121314vec3 dirt_color = vec3(0.8549, 0.5255, 0.3098);vec3 grass_color = vec3(0.3137, 0.5412, 0.0157);// ..if(rd.y < 0.05 && rayMarchingTerrain(ro, r...
景深的简单实现
关于景深 景深是一个常在摄像领域出现的词,它一般指的是沿着摄像机或其他成像器的拍摄方向上,能够取得清晰图像的成像所测定的被摄物体前后距离范围。用大白话就是说,拥有浅景深的成像器拍摄出来的效果,是只有焦点附近的图像是清晰的,其他地方的图像都是模糊的;而拥有大景深则可以在离焦点很远的地方也能有清晰的图像。 有了景深效果的图像可以有重点的突出核心想要表达的内容,不仅仅在摄影摄像的领域有非常多的应用,在游戏领域内也是应用广泛,可以表现出很独特的风格化美术效果(如八方旅人的浅景深效果)。 下面我来介绍一种基础的景深效果实现,这个方法也在最近接入了KongEngine 渲染散景 浅景深的主要应用是通过调整不同焦距上物体的成像清晰程度来突出渲染画面的重点。清晰的部分我们已经掌握了,就是正常的将场景渲染出来,那不清晰的部分(或者叫做散景)也有不少的实现方式,一般是通过模糊算法来实现。 模糊的算法有很多种,比如box blur,gaussian blur等等,效果最好的是扩张模糊(dilate blur),这也是我们会采取的方法。 扩张模糊(dilate blur) 扩张模糊它的主要方式,是在...
延迟渲染实现
想要在Kong引擎里面实现的场景慢慢复杂了起来,光源和模型的数量从原先的十以内的数量增长到几十甚至几百的数量级,是时候接入延迟渲染的方法了。 延迟渲染 延迟渲染(Defer Rendering),或者延迟着色法(Defer Shading),是区别于正向渲染(Forward Shading)的一种计算场景光照的方式。 正向渲染方法就是遍历场景中的每一个模型,计算一个模型的光照表现后再继续下一个模型的计算,根据深度测试的结果更新屏幕上最终像素显示的颜色。这种方法是很容易让人理解并实现的。但是当场景中的光照和模型数量变多的时候,模型重叠的区域会进行不必要的光照计算(被挡住的模型像素区域最终会被前面的模型遮挡,但是这篇被挡住的区域还是被计算了光照),而光照计算一般来说是渲染消耗的大头,这部分时间就被浪费了。 而延迟渲染的想法则是将光照计算分成两部分。第一个部分叫做几何处理阶段(Geometry Pass),它先将光照计算所需要的模型信息(顶点位置、法线、颜色、材质属性等等)先渲染到多张贴图上(消耗低),经由深度检测保留最终在屏幕上显示的模型部分的这些信息。 第二部分叫做光照处理阶...
基于单次散射的天空大气渲染方法
最近KongEngine实现了IBL(Image Based Lighting),可以将HDR环境贴图映射作为3D场景的环境。 在实现了IBL之后我又产生了一个想法,能否实现类似UE中的大气环境的渲染效果呢?我尝试去寻找答案,发现如果要完全复刻UE中的效果确实需要一定的功夫的,但是最基础的天空大气渲染并没有想象中那么复杂,于是我便花了点时间在KongEngine中实现了这个功能。 我打算将这个方法的基础思想和实现在此简单记录一下。 单次散射模型 星球的大气层是一种参与性介质,和在真空环境不同,光在大气层中传播的时候会因为大气中的微小颗粒(水、灰尘等等)发生散射(折射、反射)和吸收等情况。因此我们看向空中的一个点的时候,这个点的颜色是光经过多次散射得到的结果。 光到达我们眼睛之前经过多少次反射和折射是不一定的,在实时渲染的需求下计算太多次光的变化显然也是不显示的。最简单的方法,是使用单次散射模型:我们假定光在进入我们眼睛之前,有且只发生了一次散射。光一般在第一次散射的时候,还会有最多的能量剩余,后面的多次散射能力相对少,对最后效果的呈现也影响不大,因此这种模型可以在保证性能的情...
级联阴影贴图实现
阴影贴图的局限 阴影贴图(shadow map)是3D场景中实现阴影效果的基础手段,它通过预先将光线方向的场景深度存储到贴图中,在渲染的时候取每个场景中的点到光源的距离和深度贴图作比较,来判定该点是否在阴影当中。 但是在较大的场景中,使用阴影贴图会有几个明显的不足: 阴影贴图只能覆盖部分场景,在渲染较大的场景的时候(如大世界),远处的场景基本上无法被阴影贴图所覆盖。 贴图的分辨率是有限的,太大的分辨率会对性能造成非常大的影响。但是在覆盖较大场景的时候,贴图分辨率不足会导致阴影模糊,效果不佳。 阴影贴图的实现一开始其实并没有考虑玩家相机的视椎体,也就是说在玩家没有看的地方也会渲染阴影贴图,这对渲染资源来说显然是个浪费。 KongEngine计划在后面接入大地形的渲染,借此机会接入了级联阴影贴图的能力。 实现方法参考了LearnOpenGL的教程。 级联阴影贴图的实现 级联阴影贴图的基本概念包括如下几点: 将玩家的视椎体划分为几段,每一段视椎体构建一张阴影贴图覆盖,这个阴影贴图完美贴合从光源方向投射到这段视椎体中心点的正交投影。 和模型LOD的理念类似,离相机近的阴影贴图需要采...
程序化地形生成-1
ShaderToy是一个很有趣的网站,它上面有着非常多的渲染案例分享,最近一段时间我也是沉迷了。在看了不少大佬的作品之后,不禁手痒。前一段时间看了Inigo大佬的一个教程案例,想着把这个效果自己来实现一次,因此就有了今天的这篇文章。 我最终的成品也放到了shadertoy上面,有兴趣的同学可以一起讨论参考一下。看起来还不错对吧,虽然还有不少地方需要完善,但这个demo已经实现了我心中的大部分效果,包括无限的基于噪音的地形生成、地形阴影、雾气、云等等。 那么下面,就让我来一步步说明这个demo的实现过程吧。 基础知识 在ST上渲染地形 对ShaderToy上运行的Shader代码,对应着可编程渲染管线的片段着色器(或者叫像素着色器)。片段着色器主要是是图形光栅化后的像素信息,所以渲染3D场景需要进行一些额外的步骤。 ShaderToy的程序一般是这样的: 1234void mainImage(out vec4 fragColor, in vec2 fragCoord){ ...} fragColor是输出,代表这这个像素的最终颜色;fragCoord是输入,代...
个人博客启动
晚上好。 还是打算在个人的github.io继续更新自己的技术博客了。原网站本来是打算用于和朋友一起写点东西上去的,结果现在倒是变成了只有我自己的碎碎念,着实不太好。 最近一段时间会尽快的将我的部分文章搬运过来,一些琐碎的文章暂时就不管了。








