【Unity渲染】 您所在的位置:网站首页 maya贴图后可以看见里边的面 【Unity渲染】

【Unity渲染】

2023-03-11 14:41| 来源: 网络整理| 查看: 265

草的渲染是游戏渲染中的一大麻烦。我目前从知乎和Github上见过的草的做法大概有这么四种:

面片

最传统的一种做法,用一片方形的网格贴一张草的贴图插在地上就行,原神里也可以看到用面片表现的小黄花。缺点很明显,俯视的时候穿帮很严重

CPU生成网格

其实就是想办法用代码绘制点线面拼出一棵(或者一大片)草。相比于3d软件中建模再导入,用代码画的草在体现摇摆动画的时候可能会方便些,不像建模出来的草想摇摆的话可能还得k个形态键啥的。

不过这方案我自己还没实现过,也没法瞎猜性能是高还是低。github上有个这项目可以参考:https://github.com/ECHibiki/WindSway-HDRP

VIsualEffectGraph

这方案也是在Github上偶然看到的,而且它好像还上架unity商店了,如果是用HDRP来做游戏的话可以直接用:

https://github.com/SirMishMash/Unity-StylizedGrass

VEG粒子我也还没开始学,并不能看懂它的原理。。

几何着色器

这个方案就是这篇专栏主要讲的内容了。

主要参考资料:

https://zhuanlan.zhihu.com/p/119307479

https://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/09%20Geometry%20Shader/

原理

当你入门了基础的Unity Shader后,你就可以根据输入的模型网格和贴图等信息将一个模型渲染成各种各样的外观。需要的时候也可以在顶点着色器中将顶点位置进行偏移,实现外廓描边之类的效果。但仅仅使用顶点和片元着色器的话,最终呈现的模型仍然会受限于输入的模型结构,一个三角形再怎么位移扭曲也还是个三角形。

但在顶点和片元着色器之间其实还可以加入一个着色器,叫做几何着色器。在几何着色器中我们可以根据顶点着色器的输入来绘制新的网格再交给片元着色器上色,从而实现把一个点渲染成一个立方体这种效果。

一些游戏中的曲面细分其实就是由几何着色器来实现的效果。相比于直接在建模阶段增加面数,由显卡来进行细分可以减轻CPU处理顶点的负荷,也能减少CPU和GPU交互的信息量。对于草的渲染这种优势就尤为明显。本文中要实现的效果,就是将网格的每一个顶点都渲染成一根草。

准备工作:生成顶点

首先新建一个对象添加MeshFilter和MeshRenderer组件,再添加一个用于生成顶点的脚本。

在脚本中我们需要new一个Mesh对象添加给MeshFilter组件,然后用脚本给这个Mesh添加顶点。

Unity的Mesh对象中,顶点的信息全部是由各个不同的数组来存储的。首先mesh.vertices是必不可少的,它存储的是顶点的位置。如果有需求的话,可以用mesh.SetNormals来设置顶点法线、用mesh.SetColors来设置顶点色等等,这些信息全部依照在数组中的索引位置一一对应。另外还需要用mesh.SetIndices来给顶点设置索引值,将MeshTopology设置为点模式,submesh设置为0。

最后,在GeneratePoint函数头上加上一句[ContextMenu("随便写个名字")],这样回到Unity的Inspector面板右键点击脚本,就会发现多出了个选项,可以直接在编辑模式下运行这个函数:

输入合适的顶点数运行后,就可以看到场景中出现了很多紫色的点,这些就是因为缺失材质而呈现紫色的顶点。

写一个最基础的几何着色器

新建一个Unlit着色器,来对它进行一些修改:

在unlit着色器中,我们会将appdata结构体中的物体空间顶点坐标在顶点着色器中转换为裁切空间坐标(SV_POSITION)并填入v2f结构体,从而提供给片元着色器进行绘制。而要使用几何着色器的话,一般会将v2f拆分成v2g和g2f两个结构体,顶点着色器直接将物体空间坐标填入v2g传给几何着色器,几何着色器生成新的顶点后再转换到裁切空间传给片元着色器绘制。

在这个例子中,我打算将每一个顶点向法线和切线方向展开成一个三角形面片,因此在appdata和v2g中传入了法线和切线信息。

接下来就是编写几何着色器的函数了:

这里用的顶点和片元着色器比unlit还要简单,没啥需要说的,重点就是中间插入的几何着色器了。首先在几何着色器头上要设定一个最大顶点数,这里想画三角形所以是3,之后画草的时候则需要设成11。

然后需要注意几何着色器的输入值。第一个输入的值必须是一个数组,这里输入的只是一个点,因此数组长度设为1。如果想要输入线或者三角形,则需要将前面的point改为line或triangle,数组长度也要改为2或3以接收多个顶点。

第二个输入值必须带有inout前缀,这个三角形流对象用于从几何着色器中接收顶点来绘制三角形。在后半段代码中可以看到,我根据输入的顶点法线和切线计算出了三个顶点坐标,将其依次装填进g2f结构体并调用TriangleStream.append函数。这样就实现了把一个顶点变成一个三角形来绘制。

将这个shader赋给之前创建的一大片顶点,就可以看到这样的效果:

你知道为啥三维软件中的xyz轴是这种颜色么——因为这样可以对应红绿蓝三原色

你也可以试试将其添加到球体和胶囊体之类的网格上,进一步感受它的作用。

到这里为止,根据点来绘制面片所需的API就已经全部展示完毕,因此后文就不再贴代码,只写理论。毕竟种草的完整代码比这要乱不少,贴出来也很难组织语言。。

画一棵草

要画一根草,首先要对草的形状心里有数。目前比较常见的草的建模方法是这样:

使用11个顶点围出9个三角形,就可以拼出一根在近处看也不会有明显棱角的草。为了梳理绘制思路,这里给每个顶点标上了序号。

要绘制这样一根草,无非就是算出每一个顶点的位置和其它需要的信息来组成结构体,然后调用TriangleStream.append即可。然而这时候如果你考虑得比较细心的话你也许会想到:仅仅按顺序填入11个顶点真的足够么?

因为你想,虽然顶点只有11个,但要围出的三角形却有9个。每个三角形都需要指定3个顶点来进行绘制,那岂不是要按照1-2-3,2-3-4,3-4-5……这样的顺序才能完整地画出所有三角形?

如果考虑到了这一点,那么你在第3层,但OpenGL的设计者在第5层。在我之前列的第二篇参考资料中可以查到关于triangle strip的用法,对于连续的三角形,几何着色器会自动将新增的顶点与之前的边连成新的三角形。所以现在只需要绘制一根草的需求下,直接按照上面标出的顺序将顶点依次填入就能轻松地画出一根草了。

附:绘制顺序很重要

无论是用C#脚本来生成三角形还是用几何着色器来画三角形,Unity中都要遵循一个原则:组成三角形的三个点要依次以逆时针顺序输入三角形流,绘制出的三角形才是正面朝向我们的,否则面朝向会反过来。

这次我们绘制的草是双面的,因此暂时不用考虑这个问题,但如果想绘制单面的图形,就必须要严格遵照顺序绘制了。

另外,由triangle strip机制生成的面会与相连的前一个面保持朝向一致而不收逆时针顺序影响,因此绘制连续的三角形时只需要考虑第一个三角形的顺序,不必多虑。

未完待续……



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有