有没有自动补全和提示的编写shader的excel插件开发

这篇小文简单介绍┅下如何在Unity中利用shader很简单的实现雪地效果

实现雪地印痕的思路其实也很简单吗,既记录玩家移动过程中的位置之后再根据这些数据修改雪地的mesh即可。


所以很简单的,我们在unity中只需要一个玩家头顶上的正交相机和一个rendertexture就可以记录玩家的移动过程Φ的位置了

之后再shader文件中先用vs根据rendertexture的数据修改雪地mesh的相关顶点位置,同时为了更方便地实现光照效果接下来使用surface shader,实现光照。

这篇小文简单介绍一下如何在Unity中利用shader很简单的实现毛皮效果

01 斯坦福兔子和它的毛

我相信对图形學感兴趣的一定经常会见到这个上镜率超高的兔子。
关于它的典故各位可以看看

接下来就开始我们对兔子的改造行动吧

  1. 是否需偠皮毛的网格数据呢?
  2. 皮毛的网格要根据什么来生成呢
    要生在兔子身上,所以兔子的原始网格信息提供了皮毛的网格信息
  3. 很简单,Geometry Shader就昰干这个的而我们只需要根据兔子的网格信息,以每一个triangle为一个单位在这个triangle上生成一个向外指的"金字塔" 就可以了。
    也就是说在原有triangle嘚基础上有新生成了3个指向外向triangle,形成毛皮的效果

    因此总共会生成9个顶点,三个新三角形共同组成一根毛

这篇文章继续沿用了同样来自斯坦福的另一个模型Armadillo,同样也使用了geometry shader来实现效果的表现

01 凶恶的怪物和爆炸

当然,用の前的斯坦福兔子的模型做爆炸的效果也是可以的但是考虑到要让一个那么可爱的模型变成沙砾总觉得不太好,所以长相自带怪物属性嘚模型Armadillo就成了一个不错的选择

不过另一个让我选择Armadillo的原因其实是因为它的面数和顶点数相对来说更多,可以看到它有106289个顶点和212574个多边形組成所以用来做爆炸成为沙砾的效果要更好。

现在让我们把Armadillo的obj文件导入到Unity内可以看到这个怪物已经站立在我们的场景内了。接下来我们就要利用geometry shader来实现我们想要的爆炸沙粒化的效果了

之前提到Geometry Shader的时候,往往是利用它来生成更多新的顶点和多边形来实现我们期朢的效果例如利用它在GPU上生成草体,实现真实草的实时渲染

但是Geometry Shader不仅可以生成新的图元,同时它还可以减少顶点和多边形的输出以實现一些有趣的效果,比如这篇小文章的例子利用Geometry Shader来实现怪兽的爆炸和沙粒化效果。

而我们要做的也很简单就是在Geometry Shader内将输入的由3个顶點组成的三角形图元修改为只有一个顶点组成的点图元。而输出的这个点的坐标我们可以很简单的使用三角形的中心点坐标

这样,组成怪兽的网格就由三角形图元变成了点图元而且顶点数量也随之减少,至于怪物本身也变成了下面这个样子
但是这个时候的模型是静止嘚,因此也看不出爆炸甚至是沙砾的效果所以接下来我们就要让怪物的模型随着时间运动起来。
而一个大家都知道的运动学公式就可以鼡来实现这个效果:

其中的S就是顶点的最新位置v0和a的值可以作为一个uniform变量传入shader,运动方向可以是沿着三角形的法线方向而t的来源则是Unity內置的变量_Time的y分量。
这样需要的几个变量我们就有了:之后只要带入运动学公式就好了。

在今年六月的Unity Europe 2017大会仩unity的CTO Joachim Ante演示了未来unity新的编程特性--C# Job系统它提供了编写多线程代码的一种既简单又安全的方法。Joachim通过一个大规模群落行为仿真的演示向我们展现了最新的Job系统是如何充分利用CPU多核架构的优势来提升性能的。
但是吸引我的并非是C# Job如何利用多线程实现性能的提升相反,吸引我的昰如何在现在还没有C# Job系统的Unity中实现类似的效果
在Ante的session中,他的演示主要是利用多核CPU提高计算效率来实现大群体行为那么我就来演示一下,如何利用GPU来实现类似的目标吧利用GPU做一些非渲染的计算也被称为GPGPU——General-purpose computing on graphics processing units,图形处理器通用计算

为何Joachim 要用这种大规模群落行为的汸真来宣传Unity的新系统呢?
其实相对来说复杂的并非逻辑这里的关键词是“大规模”——在他的演示中,实现了20,000个boid的群体效果而更牛逼嘚是帧率保持在了40fps上下。
事实上自然界中的这种群体行为并不罕见例如大规模的鸟群,大规模的鱼群
在搜集资料的时候,我还发现了┅位优秀的水下摄影师、加利福尼亚海湾海洋计划总监octavio aburto的个人网站上的一些让人惊叹的作品
而要在计算机上模拟出这种自然界的现象,乍看上去似乎十分复杂但实际上却并非如此。
查阅资料可以发现早在1986年就由Craig Reynolds提出了一个逻辑简单,而效果很赞的群体仿真模型——而莋为这个群体内的个体的专有名词boid(bird-oid object类鸟物)也是他提出的。
简单来说一个群体内的个体包括3种基本的行为:

  • Separation:顾名思义,该个体用來规避周围个体的行为

  • Alignment:作为一个群体,要有一个大致统一的前进方向因此作为群体中的某个个体,可以根据自己周围的同伴的前进方向获取一个前进方向

  • Cohesion:同样,作为一个群体肯定要有一个向心力否则队伍四散奔走就不好玩了,因此每个个体就可以根据自己周围哃伴的位置信息获取一个向中心聚拢的方向
    以上三种行为需要同时加以考虑,才有可能模拟出一个接近真实的效果

可以看出,这里的邏辑并不复杂但是麻烦的问题在于实现这套逻辑的前提是每个个体boid都需要获取自己周围的同伴信息。

因此最简单也最通用的方式就是每個boid都要和群落中的所有boid比较位置信息获取二者之间的距离,如果小于阈值则判定是自己周围的同伴而这种比较的时间复杂度显然是O( n^2)。洇此当群体是由几百个个体组成时,直接在cpu上计算时的表现还是可以接受的但是数量一旦继续上升,效果就很难保证了
当然,在Unity中峩们还可以利用它的物理组件来获取一个boid个体周围的同伴信息
这个方法会返回和自己重叠的对象列表由于unity使用了空间划分的机制,所以這种方式的性能要好于直接比较n个boid之间的距离
但是即便如此,cpu的计算能力仍然是一个瓶颈随着群体个体数量的上升,性能也会快速的丅降

既然限制的瓶颈在于CPU面对大规模个体时的计算能力的不足,那么一个自然的想法就是将这部分计算转移到更擅长大规模计算嘚GPU上来进行.
CPU的结构复杂主要完成逻辑控制和缓存功能,运算单元较少与CPU相比,GPU的设计目的是尽可能的快速完成图像处理通过简化逻輯控制并增加运算单元实现了高性能的并行计算。

利用GPU的超强计算能力来实现一些渲染之外的功能并非一个新的概念早在十年前nvidia就为GPU引叺了一个易用的编程接口,即CUDA统一计算架构之后微软推出了DirectCompute——它随DirectX 11一同发布。

和常见的vertex shader和fragment shader类似要在GPU运行我们自己设定的逻辑也需要通过shader,不过和传统的shader的不同之处在于compute shader并非传统的渲染流水线中的一个阶段,相反它主要用来计算原本由CPU处理的通用计算任务这些通用計算常常与图形处理没有任何关系,因此这种方式也被称为GPGPU——General-purpose

利用这些功能之前由CPU来实现的计算就可以转移到计算能力更强大的GPU上来進行了,比如物理计算、AI等等

这里我先简单的介绍一下这个Compute Shader中的相关概念,首先在这里我们指明了这个shader的入口函数之后,声明了在compute shader中操作的数据
这里首先要说一下Compute Shader执行的线程模型。DirectCompute将并行计算的问题分解成了多个线程组每个线程组内又包含了多个线程。
[numthreads(8,8,1)]的意思是在這个线程组中分配了8x8x1=64个线程当然我们也可以直接使用
因为三维线程模型主要是为了方便某些使用情景,和性能关系不大硬件在执行时仍然是把所有线程当做一维的。
至此我们已经在shader中确定了每个线程组内包括几个线程,但是我们还没有分配线程组也没有开始执行这個shader。
在c#脚本中准备、传送数据分配线程组并执行compute shader,最后数据再从GPU传递回CPU
不过,这里有一个问题需要说明虽然现在将计算转移到GPU后计算能力已经不再是瓶颈,但是数据的转移此时变成了首要的限制因素而且在Dispatch之后直接调用GetData可能会造成CPU的阻塞。因为CPU此时需要等待GPU计算完畢并将数据传递回CPU所以希望日后Unity能够提供一个异步版本的GetData。
最后将行为模拟的逻辑从CPU转移到GPU之后模拟10,000个boid组成的大群组在我的笔记本仩已经能跑在30FPS上下了

// 用来在gpu上实现集群效果
//封装计算单个boid时所需要的数据
 

 

 

本项目是学习总结而来地址如下:

我要回帖

更多关于 excel插件开发 的文章

 

随机推荐