基于U3D和Shader下模型光束效果的设计与实现

作者: 陈翔宇

基于U3D和Shader下模型光束效果的设计与实现0

摘要:在Unity3D游戏引擎的制作中,不可或缺的是场景的搭建和模型的导入,这些场景模型大多通过3ds Max及Maya等绘图软件制作而成,导入后便不易更改其外观效果,会缺少对三维模型美术方面的追求,同时模型的轮廓特效会有局限性,导致场景及模型不能完美融合,呈现给用户满意的效果。而Shader着色器的出现改善了这一问题。文章通过研究ShaderLab代码的设计以及算法的运用来实现场景中人物角色更逼真的三维效果。

关键词:Unity3D;ShaderLab;三维模型

中图分类号:TP37 文献标识码:A文章编号:1009-3044(2023)16-0112-04

0 引言

Unity是实时3D互动内容创作和运营平台。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助Unity将创意变成现实[1]。Unity平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备,同时支持Windows、Android和Mac等多平台[2]。

Unity3D开发相比于其他游戏引擎,有更多优势特点:1) 支持多种格式导入:整合多种DCC文件格式,包含3dsMax、Maya、Lightwave、Collade等文档,可直接拖拽到Unity中,除原有内容外,还包含Mesh、多UVs、Vertex、Colors、骨骼动画等功能,提升游戏制作的资源应用[3]。2) 逼真的粒子系统:Unity开发的游戏可以达到难以置信的运行速度,在良好硬件设备下,每秒可以运算数百万面以上的多边形。高质量的粒子系统,内置的Shuriken粒子系统,可以控制粒子颜色、大小及粒子运动轨迹,可以快速创建下雨、火焰、灰尘、爆炸、烟花等效果。3) 支持外源制作的各种插件,导入Unity 后方便制作者使用。4) 支持多平台发布:Unity3D游戏开发支持的平台,无疑是当下较为流行的平台,满足绝大部分项目需求。早期的引擎,多以PC和CONSOLE为主[4],同时支持了Windows、XBOX、PS2等平台。U3D便利的多平台发布特性,也是它成为当前性价比最高的引擎的原因之一。5) AssetStore 商店提供了大量的资源,使U3D的生态圈更加稳固[5]。

用户可以制作插件网上售卖,赚取一些利益,也可以购买别人的插件,作为使用或者参考。有时候,购买一些插件,可以让用户快速脱离当前的困境,一个是解决进度问题,一个是解决思路问题,这是之前其他引擎不具备的。

1 Shader 下光束的设计

1.1 Shader 原理

Shader 是运行在GPU 上可编程的图形程序,在Unity中可以使用Cg/HLSL语言编写顶点着色器和片元着色器。顶点着色器和片元着色器被分离为可编程的单元,两者都拥有强大的并行计算能力,擅长于矩阵计算(不高于四阶),片元着色器可以高速查询纹理数据信息,但顶点着色器不行[6]。顶点着色器(Vert) 负责处理顶点坐标转换信息,片元着色器(Frag)负责处理像素颜色数据计算信息,且前者的输出是后者的输入。顶点着色程序从GPU前端模块(寄存器)中提取图元信息(顶点位置、法向量、纹理坐标等),并完成顶点坐标空间转换、法向量空间转换、光照计算等操作,最后将计算好的数据传送到指定寄存器中;然后片元着色程序从中获取需要的数据,通常为纹理坐标、光照信息等,并根据这些信息以及从应用程序传递的纹理信息(如果有)进行每个片元的颜色计算,最后将处理后的数据送光栅操作模块[7]。片元着色程序对每个片元进行独立的颜色计算,最后输出颜色值的就是该片段最终显示的颜色,具体渲染流程见图1。

1.2 Shaderlab 编程开发的结构

ShaderLab开发是Unity内置的一段Shader代码,在Unity 中赋予材质上的Shader 着色器进而实现效果。内部结构偏复杂,详细阐述易于理解。

1) Properties{}:Properties的{}内是定义着色器的相关属性,输入的属性会呈现在Unity平台内Material下的Inspector面板下供调试,定义格式为_Name“( In⁃spector Name”,type)=Value[option}],其中_Name表示属性名,有_NormalMap、_MainTex、_Color、_BumpScale 等。”Inspector Name”代表在Inspector面板下显示的属性名。“Type”则是属性类型(Vector、Float、Range(min,max)、Cube、Rect、2D、Color等);Properties面板见图2。

2) SubShader{},SubShader 是子Shader,可以有多个,运行效果时,从第一个SubShader开始[8],如果第一个SubShader的效果都可以实现,就使用第一个,如果不可以,就会自动运行下一个SubShader,直到最后的Fallback回滚;3) pass块,隶属于SubShader中,一个pass块相当于一个方法,在它内部的CGPROGRAM至ENDCG区域编写Shaderlab代码;4) CGPROGRAM 到ENDCG 部分,这个区域是Shaderlab 代码的核心内容,必须将属性块Properties 里需要的属性值重新定义一遍。区域的主要内容再细分为:①#pragram vertex vert,声明顶点函数,顶点函数名为vert,它的基本作用是完成顶点坐标从模型空间到剪裁空间的转换(从游戏环境转换到视野相机屏幕上)。②#pragram fragment frag,声明片元函数,它的基本作用是返回模型对应的屏幕上每一个像素的颜色值[9]。③struct a2v,从应用程序传递到顶点函数的结构体。④struct v2f,从顶点函数传递给片元函数的结构体。⑤v2f vert(a2v v),即顶点函数,内部书写从模型空间转换到剪裁空间的代码,比如法线、顶点坐标、纹理坐标等。⑥frag(v2f f),即片元函数,内部实现从剪裁空间返回到Unity世界空间的像素值。

2 游戏需求下涉及的算法

当前游戏的逻辑模式已经完成,原人物角色模型见图3。本文的主要需求是运用Shaderlab将场景内游戏角色的服装加上光束的特效以及高光反射的效果,令人物角色在场景中拥有更出色的3D外观表现。

在游戏场景中,为了给人物角色添加特殊的光束效果,本文创新地采用光照融合叠加原理。

1) 漫反射公式:Diffuse=_LightColor0.rgb*max(dot(normalDir,lightDir),0); 其中,直射光_LightColor0表示Unity内置环境光(平行光),其后加上.rgb则代表的是直射光的颜色值。需要在注入“Lighting.cginc”的条件下再调出。

Max(,)函数取最大值,dot(,)函数来进行点乘运算,此处在漫反射公式内则是求|normalDir|*|lightDir|*cos的乘积值。normalDir表示法向量的单位向量,lightDir代表入射光方向的单位向量。

2) 高光反射公式:specular=_LightColor.rgb*pow(max(dot(normalDir,halfDir),0),_Gloss)。

公式内Pow(a,b) 函数计算的是ab 的值,_Gloss表示的是高光参数值,值的大小和高光反射的区域大小成反比。这里的halfDir是由viewDir(观察方向单位向量)和lightDir(入射光方向单位向量)的叠加单位向量。

3) 矩阵转换算法:对于顶点从模型空间下坐标转换到世界空间的坐标,需要用到四维矩阵转换,其代码行为 f.vertex=mul(v.vertex,unity_ObjectToWorld);通过mul函数将模型空间下的模型顶点坐标v.vertex作为行向量,与四维矩阵unity_ObjectToWorld 进行乘积,获得剪裁空间下的模型顶点坐标f.vertex[10]。

4) 透明度alpha值:alpha=min(1,abs(((bottom+top)/2-i.uv.x*tan(_lightAngle))-i.uv.y)/(Length/2)); 这一值是实现人物角色自发光的重点之处,min(,)函数取括号内两数之间最小值,abs()函数取括号内数值的绝对值,tan()函数求_LightAngle(闪光角度)的正切值,随后和i.uv.x(纹理坐标的X分量)一起计算得出透明度alpha值。

3 主要片元函数代码

物体角色模型在导入Unity场景时已配有纹理贴图,对于光束效果来说区分为逐顶点和逐像素的效果追求。在如3dsMax、Maya等三维模型的绘制中,模型是由无数个三角形面组成。一个三角形的面是由三条线和三个顶点拼接而成,逐顶点会取三个顶点间的插值来缓和过渡颜色差。而逐像素则是计算每个像素点的精确值后再绘制在世界空间中,图像上的处理会更精细但相比逐顶点会消耗更多的资源性能。本文中的两个光束效果都是以逐像素为核心,通过改变片元函数中像素值来达到特定的效果。

3.1 人物角色自发光的片元函数代码

属性Properties中已经定义了_MainTex(主贴图),2D类型且默认值为白色,在SubShader的pass块内的CGPROGRAM~ENDCG段进行了Sample2D _MainTex 的再定义。整体Shaderlab的局部片元函数代码如下:

5 U3D 下Shader 实现后结果

5.1 自发光效果

由于对人物角色模型添加了自发光的Shaderlab,可以看到衣服模型自上向下会有呈周期性变化的闪烁光芒效果,模型的纹理原图会作为底层纹理与自发光相互融合产生不错的特效,具体效果见图4。

5.2 高光效果

相比图3的原人物模型,可以发现人物面部色彩更细腻,面部轮廓也有了明显的光泽,整体给用户呈现出了一个更精气神的角色,Unity场景中展示见图5。

5.3 自发光和高光效果融合

同时可以调整场景内的渲染显示质量。在菜单栏下Edit的Project Setting 的Quality 面板进行设置 ,Pixel Light Count像素灯数量取标准值4,Texture Qual⁃ity 纹理质量取Full Res(完整分辨率),Shadow Dis⁃tance阴影距离值取50,超过这个距离阴影将不会被显示。这样可以将渲染的性能开到一个很高的级别,同时也保证了渲染效率的稳定,详细设置可见图6。

将自发光和高光效果共同施加在人物角色模型上,呈现在Unity场景中的效果见图7。

6 结束语

在日常游戏开发中,不仅看重游戏的可玩程度和逻辑性,也越来越重视游戏的场景特效和三维模型特效。Shader着色器的应运而生为此提供了充分的扩展性,本文通过Unity3D和Shader的结合实现了用户想要的效果,通过自发光测试和高光测试也验证了效果的可行性。在今后的开发中,不应止步于此,还可以通过Shaderlab来书写各种各样的渲染特效,与场景搭配融合出令用户惊叹赞绝、美轮美奂的游戏画面。

参考文献:

[1] 加藤政树. Unity游戏设计与实现:南梦宫一线程序员的开发实例[M].罗水东,译.2版.北京:人民邮电出版社,2017.

[2] 刘国柱.Unity3D/2D游戏开发从0到1[M].2版.北京:电子工业出版社,2018.

[3] Bond J G.游戏设计、原型与开发:基于Unity与C#从构思到实现[M].姚待艳,刘思嘉,张一淼,译. 2版.北京:电子工业出版社,2020.

[4] 宣雨松.Unity 3D游戏开发[M].北京:人民邮电出版社,2012:31-40.

[5] Ferrone H.Learning C# by Developing Games with Unity 2020:An Enjoyable and lntuitive Approach to Getting Started with C# Programming and Unity[M].5th ed.北京:清华大学出版社,2022:55-60.

[6] 陈国军,尹鹏,裴利强,等.基于Shader的CSG几何体的实时渲染[J].计算机与数字工程,2022,50(1):190-194.

[7] 罗仁,李子轩.基于OpenGL的三维实时渲染引擎[J].信息与电脑(理论版),2021,33(18):112-115.

[8] Halladay K.Shader开发实战[M].郭华丰,韦静,译.北京:清华大学出版社,2021.

[9] 冯乐乐.Unity Shader入门精要[M].北京:人民邮电出版社,2016.

[10] 唐福幸.Unity Universal RP内置Shader解析[M].北京:清华大学出版社,2021.

【通联编辑:唐一东】

上一篇 点击页面呼出菜单 下一篇