陈翔宇
(华东师范大学 计算机科学与技术学院,上海200333)
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.1 Shader原理
Shader 是运行在GPU 上可编程的图形程序,在Unity 中可以使用Cg/HLSL 语言编写顶点着色器和片元着色器。顶点着色器和片元着色器被分离为可编程的单元,两者都拥有强大的并行计算能力,擅长于矩阵计算(不高于四阶),片元着色器可以高速查询纹理数据信息,但顶点着色器不行[6]。顶点着色器(Vert)负责处理顶点坐标转换信息,片元着色器(Frag)负责处理像素颜色数据计算信息,且前者的输出是后者的输入。顶点着色程序从GPU 前端模块(寄存器)中提取图元信息(顶点位置、法向量、纹理坐标等),并完成顶点坐标空间转换、法向量空间转换、光照计算等操作,最后将计算好的数据传送到指定寄存器中;
然后片元着色程序从中获取需要的数据,通常为纹理坐标、光照信息等,并根据这些信息以及从应用程序传递的纹理信息(如果有)进行每个片元的颜色计算,最后将处理后的数据送光栅操作模块[7]。片元着色程序对每个片元进行独立的颜色计算,最后输出颜色值的就是该片段最终显示的颜色,具体渲染流程见图1。
图1 Shader渲染流程
1.2 Shaderlab编程开发的结构
ShaderLab 开发是Unity 内置的一段Shader 代码,在Unity 中赋予材质上的Shader 着色器进而实现效果。内部结构偏复杂,详细阐述易于理解。
1) Properties{}:Properties的{}内是定义着色器的相关属性,输入的属性会呈现在Unity平台内Material下的Inspector 面板下供调试,定义格式为_Name(“Inspector 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 Shader下Properties面板
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世界空间的像素值。
当前游戏的逻辑模式已经完成,原人物角色模型见图3。本文的主要需求是运用Shaderlab 将场景内游戏角色的服装加上光束的特效以及高光反射的效果,令人物角色在场景中拥有更出色的3D外观表现。
图3 场景下原人物角色模型
在游戏场景中,为了给人物角色添加特殊的光束效果,本文创新地采用光照融合叠加原理。
1) 漫反射公式:Diffuse=_LightColor0.rgb*max(dot(normalDir,lightDir),0);
其中,直射光_LightColor0 表示Unity 内置环境光(平行光),其后加上.rgb 则代表的是直射光的颜色值。需要在注入“Lighting.cginc”的条件下再调出。Max(,)函数取最大值,dot(,)函数来进行点乘运算,此处在漫反射公式内则是求|normalDir|*|lightDir|*cos<normalDir,LightDir>的乘积值。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值。
物体角色模型在导入Unity场景时已配有纹理贴图,对于光束效果来说区分为逐顶点和逐像素的效果追求。在如3dsMax、Maya等三维模型的绘制中,模型是由无数个三角形面组成。一个三角形的面是由三条线和三个顶点拼接而成,逐顶点会取三个顶点间的插值来缓和过渡颜色差。而逐像素则是计算每个像素点的精确值后再绘制在世界空间中,图像上的处理会更精细但相比逐顶点会消耗更多的资源性能。本文中的两个光束效果都是以逐像素为核心,通过改变片元函数中像素值来达到特定的效果。
3.1 人物角色自发光的片元函数代码
属性Properties中已经定义了_MainTex(主贴图),2D 类型且默认值为白色,在SubShader 的pass 块内的CGPROGRAM~ENDCG段进行了Sample2D _MainTex的再定义。整体Shaderlab的局部片元函数代码如下:
通过(1) 处的Shaderlab 内置tex2D 函数传入参数_MainTex以及剪裁空间下的f.uv参数,再赋给col,获得col 的初始颜色值。(2) 处定义一个float 类型的alpha值,通过min 函数取得每个纹理采样点之间的最小值再赋予alpha。在(3) 处通过返回系数为(1-alpha)的RGB 为(0.5,0.5,0.5)的颜色值和系数为alpha 的纹理颜色值,再与属性Properties 中已定义的_Color(闪光颜色)进行加法叠加,再赋予col,最后再返还给世界空间下的像素值,实现了人物角色自发光的特效。
3.2 人物角色面部高光反射的片元函数代码
经过Shaderlab 代码的初始区域的结构体定义以及顶点函数转换获取到了f.worldnormal(世界空间下法线)、f.worldvertex(世界空间下顶点)、_MainTex(主贴图)等。整体Shaderlab的局部片元函数代码如下:
(1) 将f.worldnormal 通过normalize 函数来单位化获得世界下法线的单位向量(normalDir) 。(2) 将f.worldvertex经过世界空间下入射光方向的函数World-SpaceLightDir 转换来获取世界空间下每个点对应的入射光方向的单位向量(lightDir) 。计算漫反射颜色值见(3)经过dot点乘计算出每个点的世界法线向量和入射光方向的cos余弦值,再和0相比较取最大值,再乘以环境光的颜色值(_LightColor0.rgb) 以及纹理颜色值(texColor) 来得到最终的漫射光颜色值(diffuse) 。(4) 计算视角方向(即摄像机方向),高光反射的重点就在于视角方向。因为人观察事物某个顶点区域从不同的角度会有不同的反射效果。将f.worldvertex 传入世界空间下观察方向函数UnityWorldSpaceViewDir 的转换后再通过normalize 函数单位化后获得世界空间下的单位视角方向向量。(5) 以局部变量halfDir(半融合向量)接受了经过视角方向和入射光方向的叠加后的单位化向量值。(6)随后以normalDir(世界法线单位向量)和halfDir(半融合单位向量)的点乘余弦值和0比较后的最大值作为pow函数的底数,再以_Gloss(高光参数)作为函数的冥次方计算得值,随后将得到的值和环境光颜色以及高光颜色值做乘法融合。这里的颜色值之间的乘法融合相比加法叠加会有更少量化值的影响。(7) 最后,将漫射光颜色值(diffuse) 、高光颜色值(specular)、环境光颜色值(UNITY_LIGHTMODEL_AMBIENT) 与纹理颜色值(texColor)的乘法融合值再相加,最后再返还给世界空间下的像素值,实现了人物角色面部高光反射的特效。
4.1 自发光测试
对应Unity 场景,在Shaderlab 中对人物角色的自发光RGB值进行多次更改后,颜色值呈正常相关变化,主要表现为人物模型保持为纹理原色,但自发光的颜色会受RGB值的影响,测试结果见表1。
表1 自发光测试结果统计
4.2 高光测试
人物角色面部的高光会受到高光颜色值的直接影响,但主要是由高光参数决定面部的光泽效果。在实际应用中,高光参数区域的大小会和高光参数的值成反比,测试结果见表2。
表2 高光测试结果统计
5.1 自发光效果
由于对人物角色模型添加了自发光的Shaderlab,可以看到衣服模型自上向下会有呈周期性变化的闪烁光芒效果,模型的纹理原图会作为底层纹理与自发光相互融合产生不错的特效,具体效果见图4。
图4 场景下附加自发光效果后人物角色模型
5.2 高光效果
相比图3 的原人物模型,可以发现人物面部色彩更细腻,面部轮廓也有了明显的光泽,整体给用户呈现出了一个更精气神的角色,Unity场景中展示见图5。
图5 场景下附加高光效果后人物角色模型
5.3 自发光和高光效果融合
同时可以调整场景内的渲染显示质量。在菜单栏下Edit 的Project Setting 的Quality 面板进行设置 ,Pixel Light Count像素灯数量取标准值4,Texture Quality 纹理质量取Full Res(完整分辨率),Shadow Distance 阴影距离值取50,超过这个距离阴影将不会被显示。这样可以将渲染的性能开到一个很高的级别,同时也保证了渲染效率的稳定,详细设置可见图6。
图6 渲染显示Quality设置
将自发光和高光效果共同施加在人物角色模型上,呈现在Unity场景中的效果见图7。
图7 两种效果共同附加后人物角色模型
在日常游戏开发中,不仅看重游戏的可玩程度和逻辑性,也越来越重视游戏的场景特效和三维模型特效。Shader 着色器的应运而生为此提供了充分的扩展性,本文通过Unity3D 和Shader 的结合实现了用户想要的效果,通过自发光测试和高光测试也验证了效果的可行性。在今后的开发中,不应止步于此,还可以通过Shaderlab来书写各种各样的渲染特效,与场景搭配融合出令用户惊叹赞绝、美轮美奂的游戏画面。
猜你喜欢高光顶点纹理过非等腰锐角三角形顶点和垂心的圆的性质及应用(下)中等数学(2021年9期)2021-11-22想做联名爆款?超级飞侠、熊出没、奥特曼等“高光”IP等你来聊玩具世界(2021年5期)2021-03-08基于BM3D的复杂纹理区域图像去噪软件(2020年3期)2020-04-20使用纹理叠加添加艺术画特效摄影之友(影像视觉)(2018年12期)2019-01-28关于顶点染色的一个猜想山东科学(2018年6期)2018-12-20季后赛高光时刻乔尔·恩比德没有遗憾NBA特刊(2018年10期)2018-06-02TEXTURE ON TEXTURE质地上的纹理Coco薇(2017年8期)2017-08-03释放出来自HDR的高光力量 Optoma奥图码UHZ880家庭影院技术(2017年12期)2017-02-06消除凹凸纹理有妙招!Coco薇(2015年5期)2016-03-29基于Moldflow 的高光无痕电视前壳注射模具设计中国塑料(2014年2期)2014-10-17