APP下载

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

2023-07-26陈翔宇

电脑知识与技术 2023年16期
关键词:着色器高光顶点

陈翔宇

(华东师范大学 计算机科学与技术学院,上海200333)

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 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世界空间的像素值。

2 游戏需求下涉及的算法

当前游戏的逻辑模式已经完成,原人物角色模型见图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值。

3 主要片元函数代码

物体角色模型在导入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 Shader下结果测试

4.1 自发光测试

对应Unity 场景,在Shaderlab 中对人物角色的自发光RGB值进行多次更改后,颜色值呈正常相关变化,主要表现为人物模型保持为纹理原色,但自发光的颜色会受RGB值的影响,测试结果见表1。

表1 自发光测试结果统计

4.2 高光测试

人物角色面部的高光会受到高光颜色值的直接影响,但主要是由高光参数决定面部的光泽效果。在实际应用中,高光参数区域的大小会和高光参数的值成反比,测试结果见表2。

表2 高光测试结果统计

5 U3D下Shader实现后结果

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 两种效果共同附加后人物角色模型

6 结束语

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

猜你喜欢

着色器高光顶点
见证彼此高光
过非等腰锐角三角形顶点和垂心的圆的性质及应用(下)
想做联名爆款?超级飞侠、熊出没、奥特曼等“高光”IP等你来聊
基于UE4 实时射线追踪技术的研究与探讨
基于Unity Shader石油泄漏现象模拟的研究
基于IMx6的opengl图形着色器开发研究
关于顶点染色的一个猜想
释放出来自HDR的高光力量 Optoma奥图码UHZ880
基于Moldflow 的高光无痕电视前壳注射模具设计
基于可编程渲染管线的雷达图像分层模型设计与实现