塞尔达风之杖技术分析-角色渲染和面部表情.

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

首发于游戏开发启示录

塞尔达风之杖技术分析-角色渲染和面部表情

拳四郎

游戏开发 话题的优秀回答者

简介

《塞尔达传说 风之杖》是一款由任天堂开发的任天堂GameCube平台上的动作冒险游戏,一经发布就广受好评,之后任天堂在WiiU上还发布了HD版本。其别具一格的卡通美术风格现如今看来都不算过时,甚至给最近火的一塌糊涂的《塞尔达传说 荒野之息》带来了很大的影响。

虽说gamebox上的版本马赛克比较重,但是link的表情表现的非常的到位,从简单的眨眼,到各种神情的变化,都特别的到位,比如下面这个他被用木桶投掷到岛上的过场

非常带感。

今天要分析的是游戏中的角色渲染和表情系统,并且在Unity中进行实现。

工具

Unity3D 5.3.5

Maya 2014

模型处理

原始的模型可以从这里下载到。最原始的模型是obj的模型,要放到Unity里的话,首先要将其转化成fbx。

打开Maya,选择导入模型

导入之后的mesh是一个完整的mesh,先把它打撒。选中模型,然后 网格->分离,Mesh就被打散了

看下面数,不到3000

衣服的贴图尺寸180*96,怎么”挤” 进去的?

由于衣服大部分的地方都是大块的纯色,不同于常规的展UV的方法,纹理也是一些很简单的颜色,uv就直接被放到对应的色块上。

在看最重要的面部。

嘴巴部分是专门用了一块mesh来处理,这样只要在材质中切换贴图就能够达到换表情的作用。

嘴巴部分由于是切割的mesh,所以在导入的时候生成法线会出问题

嘴巴部分的的法线和面部的法线不是连续的,这样会导致后面处理光照的时候会很奇怪。

处理方法是用Maya的法线工具

会生成一个合并好的mesh,

这下正常了。再看眼睛,眼睛的表现分为三个部分。眉毛,眼白,眼睛。这里的处理方法不是用面部的网格切一块下来了,而是在眼睛出罩一些片mesh

每一边的眼睛都覆盖了三个mesh片,分别是眉毛,眼白,瞳孔(为了看清楚将它们拉开了一些)。

实际上是往外拉了一点点,防止Z-Fighting

接下来可以导出模型了,文件->导出,选fbx,默认设置。

角色渲染

角色渲染的话就是最简单的卡通渲染,根据direction light的方向和法线的角度得到一个shadow值,和纹理的颜色相乘。

Shader "Custom/celshading"
{Properties{[NoScaleOffset] _MainTex("Texture", 2D) = "white" {}}SubShader{Pass{Tags{ "LightMode" = "ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f{float2 uv : TEXCOORD0; // texture coordinatefloat4 vertex : SV_POSITION; // clip space positionhalf3 worldNormal : TEXCOORD1;};// vertex shaderv2f vert(appdata_base v){v2f o;// transform position to clip space// (multiply with model*view*projection matrix)o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);// just pass the texture coordinateo.uv = v.texcoord;o.worldNormal = UnityObjectToWorldNormal(v.normal);return o;}// texture we will samplesampler2D _MainTex;// pixel shader; returns low precision ("fixed4" type)fixed4 frag(v2f i) : SV_Target{// sample texture and return itfixed4 col = tex2D(_MainTex, i.uv);float shadow = dot(i.worldNormal, normalize(_WorldSpaceLightPos0.xyz));col *= smoothstep(0.0, 0.1, shadow) * 0.4 + 0.6;//fixed4 col = 0;//col.rgb = i.worldNormal*0.5 + 0.5;//col.rgb = _WorldSpaceLightPos0.xyz;return col;}ENDCG}}
}

不加光照

加上之后得到结果

用到了一个内置函数

smoothstep - interpolate smoothly between two input values based on a third

目的是为了让明暗交接的地方不要太锋利,过度的平滑一些。

加上阴影

// shadow caster rendering pass, implemented manually
// using macros from UnityCG.cginc
Pass
{Tags{ "LightMode" = "ShadowCaster" }CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_shadowcaster#include "UnityCG.cginc"struct v2f {
V2F_SHADOW_CASTER;};v2f vert(appdata_base v){v2f o;TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)return o;}float4 frag(v2f i) : SV_Target{SHADOW_CASTER_FRAGMENT(i)}ENDCG
}

面部表情

嘴巴部分最简单,用的和身体一样的shader,要变换嘴型的时候,只需要切换材质的贴图。

眼睛部分会比较复杂。眼睛和眉毛的shader是一样的,就是基本的transparent

记住左右眉毛和左右眼睛得用不同的材质,因为不同的表情左右可能是不对称的。

眉毛和眼睛正常了,但是眼珠不正常,这里需要在shader中给眼珠加一个mask,将当前眼白的部分叠加到眼珠上得到最终的结果。

fixed4 frag(v2f i) : SV_Target
{// sample texture and return itfixed4 col = tex2D(_PupilTex, i.uv);fixed4 mask = tex2D(_EyeMaskTex, i.uv);col *= mask;return col;
}

需要注意的是眼珠的EyeMaskTex 需要和眼白的maintex要同步好,不然就会很囧。

瞳孔的放大缩小

Link眼睛的瞳孔的位置也是可以控制的,用来表现看的方向

同时也是可以放大缩小的,比如说上面的用来表示惊恐的表情

瞳孔的位置处理直接叠加上一个uv偏移就可以了。

_XOffset("X Offset", float) = 0
_YOffset("Y Offset", float) = 0float2 finalUv = i.uv + float2(_XOffset, _YOffset)
fixed4 col = tex2D(_PupilTex, finalUv);

调一个结果

惊悚的表情需要进行UV缩放,注意不是将uv直接乘以scale值,这样会从左下角为中心缩放,我们的目的是从贴图的中心开始缩放,需要一个简单的换算

float2 scaleCenter = float2(0.5f, 0.5f);
float2 finalUv = (i.uv + float2(_XOffset, _YOffset) - scaleCenter) * _Scale + scaleCenter;
fixed4 col = tex2D(_PupilTex, finalUv);

调个简单的结果

还有一个点要注意,瞳孔的纹理的wrap mode 要设置为

不然会出现…

头发不会挡住眼睛

游戏中是这样的就像下面这样

虽然有时候看起来有点奇怪

但是整体表现还是挺好的。

这里使用的方法是利用Stencil buffer来处理,首先标记出被遮挡的部分,然后清掉那一部分的zbuffer,最后绘制出来,下面是具体的实现。

首先单独给头发一个shader,用来写stencil

Stencil
{Ref 1Comp alwaysPass replace
}

其余部分和身体的shader一样,头发绘制过的地方Stencil都变成了1。

眼睛分为三个pass绘制,

第一个pass标记出stencil为1,且ztest fail的部位

Stencil
{Ref 1Comp EqualPass replaceZFail IncrSat
}

ZFail IncrSat表示通过stencil test,Ztest失败之后,将stencil的值+1.所以被头发遮挡住的地方stencil变成了2.下面蓝色部分就是

第二个pass,清掉标记区的Zbuffer

ZTest Greater
ZWrite OnStencil
{Ref 2Comp Equal
}

第三个pass,就是最简单的transparent

Pass
{Tags{ "IgnoreProjector" = "True" "RenderType" = "Transparent" }CGPROGRAM// use "vert" function as the vertex shader#pragma vertex vert// use "frag" function as the pixel (fragment) shader#pragma fragment frag#include "UnityCG.cginc"// vertex shader outputs ("vertex to fragment")struct v2f{float2 uv : TEXCOORD0; // texture coordinatefloat4 vertex : SV_POSITION; // clip space position};// vertex shaderv2f vert(appdata_base v){v2f o;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = v.texcoord;return o;}// texture we will samplesampler2D _MainTex;fixed4 frag(v2f i) : SV_Target{fixed4 col = tex2D(_MainTex, i.uv);return col;}ENDCG
}

最终结果

最后来摆几个Pose

小结

相对于UnityChan中完全用骨骼驱动的表情系统(王者荣耀里面角色展示的部分似乎也是这样处理的)

这套表情系统的特点是

非常节省资源,几乎没有什么消耗(也许贴图还可以再pack一下?)。

和美术风格非常的搭。

面部的所有细节都不会糊掉。

无法使用macanim动画系统,需要自己写一套控制角色表情的脚本。

对于在移动平台上想自己实现一个的表情系统的卡通风格项目可以考虑用这种方案。

参考

Twilight Princess Eyes Breakdown

http://totallysweetredhoodie.blogspot.com/2013/07/animated-facial-textures-in-maya-and_26.html

https://medium.com/@gordonnl/links-expressions-eb7beae2c62c

图文详解Unity3D中Material的Tiling和Offset是怎么回事 - BIT祝威 - 博客园

Unity Shader-渲染队列,ZTest,ZWrite,Early-Z

Unity3D游戏开发从零单排(十) - 进击的Shader续

编辑于 2017-04-03

游戏开发

Unity(游戏引擎)

独立游戏开发

文章被以下专栏收录

游戏开发启示录

进入专栏

推荐阅读

风格化角色渲染实践

拳四郎发表于游戏开发启...

一道技术美术的面试题

王滕昊

Mask的艺术 – 近似PBR的Dota2角色渲染

拳四郎发表于游戏开发启...

如何在unity实现足够快的2d动态光照

伪人

22 条评论

写下你的评论...

  • eoyanglei1 年前

    蛮有趣的

  • 临冬城的夏天1 年前

    用上渐变纹理并且再乘上光照衰减打开实时阴影效果会好跟多

  • 知乎用户1 年前

    干货满满,多谢分享

  • 知乎用户1 年前

    不错,很实用

  • MrRight1 年前

    将来会写一篇coc角色渲染的专栏吗

知乎用户 (作者) 回复MrRight1 年前

Coc都是3渲2的吧?

  • 许巍1 年前

    在will上发布了hd版本,will是啥

知乎用户 (作者) 回复许巍1 年前

哈,是wiiu

  • Libin NS1 年前

    风之杖 HD 是发布在 Wii U 上的。 Wii U 和 Wii 是两代机器。

  • Alex Jiang1 年前

    可以用一张tone图去控制也不错,类似军团要塞的风格

  • 紫阳1 年前

    真良心

  • 张大亮1 年前

    良心干货

  • 张仁杰Allen1 年前

    模型那个下载链接打开是youtube,没找到下载地址在哪

知乎用户 (作者) 回复张仁杰Allen1 年前

已更新链接

  • 翁锟1 年前

    感谢拳四郎的分享,

  • 文浩1 年前

    真材实料的干货!

  • 延澈左1 年前

    有意思

  • HjYm1 年前

    爱你!!!!!!!!!!!!

  • 下划线1 年前

    不知道塞尔达还有这款游戏,以为题主做的模型,表示第一眼看到,笑疯了

  • 王申浩1 年前

    厉害了卧槽,强势干货啊

  • 圞巜1 年前

    用3dsmax打开缺眼睛和嘴巴是为什么呢

  • 知乎用户5 个月前

    都想打赏作者了

塞尔达风之杖技术分析-角色渲染和面部表情相关推荐

  1. 从《缩小帽》分析塞尔达系列的关卡结构

    最近看了一档名叫"Boss Key"的游戏设计节目,主讲人Mark Brown在节目中详细分析了塞尔达系列的地下城关卡结构,其中他运用了一套结构图的分析方法,思路十分清晰.在学习了 ...

  2. 【转】: 塞尔达组在GDC2017演讲的文字翻译:技术的智慧

    大家好,我是堂田卓宏,在<荒野之息>的制作中我担任技术总监的职位.我在2003年加入任天堂,并且作为程序员参与了许多不同游戏的制作.在本次的制作的过程中,我们的程序员团队也需要打破许多游戏 ...

  3. RenderDoc塞尔达荒野之息抓帧分析

    RenderDoc是一种抓帧工具,主要用来分析游戏开发中渲染流程,官网: https://renderdoc.org/ 我是用的版本是RenderDoc_1.14_64.zip 塞尔达荒野之息使用Ce ...

  4. 【转】: 塞尔达组在GDC2017演讲的文字翻译:显示的力量

      塞尔达系列推出新作的时候,美术风格都有明显变化.本作的风格比起写实,笔触轻快变化幅度大是其特征.2011年公开的技术演示中,画面风格要更加写实.最终版则更接近于卡通.5年里到底发生了什么呢? ▲2 ...

  5. 塞尔达 amiibo数据_塞尔达传说:旷野之息Amiibo道具制作_碧海风云

    本文出自微信公众号[碧海风云]之<塞尔达传说:旷野之息Amiibo道具制作_碧海风云> Amiibo介绍 Amiibo是任天堂发行的内置NFC芯片的产品,可以在特定游戏中与Switch机器 ...

  6. 塞尔达传说gba_1986版塞尔达 回顾34年经典系列历代作品 满分最多系列游戏

    塞尔达系列的男主林克已经陪伴我们34年了,小蟹最早是在GB塞尔达梦见岛,当时是日语,也没有资料可查,也是各种试玩到中间,实在过不了.正式玩过中文是GBC塞尔达时空之章和大地之章,这二个版本也是第一次塞 ...

  7. 这家工作室花三年把塞尔达做进RogueLike里面

    近日<轮回深渊>终于在Steam上架,这是ScreamBox这家是十年「老」游戏工作室正式推出的第二款作品. 2011年,郭星与几位朋友凭着对游戏的热爱而创建ScreamBox工作室. 从 ...

  8. 被刷屏的塞尔达来了,附源码!

    渲染系统作为游戏引擎的核心模块,是引擎画面表现力的天花板,直接决定了游戏所能输出给玩家的内容上限.Cocos Creator 3.x 的渲染系统,从架构到设计都是以面向未来.高性能.跨平台为目标,支持 ...

  9. Cocos Creator - 塞尔达的3D渲染风格,能在小游戏跑起来?

    塞尔达的3D渲染风格,能在小游戏跑起来? 渲染系统作为游戏引擎的核心模块,是引擎画面表现力的天花板,直接决定了游戏所能输出给玩家的内容上限.Cocos Creator 3.x 的渲染系统,从架构到设计 ...

最新文章

  1. Linux修改密码是提示“passwd: 鉴定令牌操作错误”问题的处理办法
  2. 将GB28181国标流转成RTSP流
  3. 批量模糊查询_Django之ORM表高级操作、增删改查、F/Q查询等
  4. Python中的向量、矩阵(numpy)
  5. linux安装数据库依赖包,Linux下安装DB2的包依赖
  6. 工作经验--他人经验
  7. tomcat事件处理机制
  8. 显示隐藏-overflow(HTML、CSS)
  9. npm换成国内源 npm换源 npm换淘宝源镜像
  10. python怎么下载numpy?
  11. 基于微信小程序的毕业设计题目(32)求职招聘小程序(含开题报告、任务书、中期报告、答辩PPT、论文模板)
  12. i18n国际语言代码对照表
  13. [Leetcode] 382. Linked List Random Node 解题报告
  14. Nginx使用的php-fpm的三种进程管理方式及优化 pm.start_servers pm.max_children参数说明
  15. 【深度学习实战03】——YOLO tensorflow运行及源码解析
  16. Hulu 圣诞剧集推荐
  17. linux系统装fluent没有界面,Linux上安装ANSYS后的一些坑(未完待续)
  18. 江苏电信欢go重新定义宽带标准
  19. 点清垃圾渗滤液脱色剂的现场应用和数据
  20. PostgreSQL报表统计历史12月度数据,无数据补零

热门文章

  1. 网页制作105个问答
  2. 计算机毕业设计 SSM购物商城管理系统
  3. MacBookPro 存储空间优化
  4. C++第二阶段(跨平台通信)-卢嘉文-专题视频课程
  5. 关于计算两日期之间经过多少天的超巧妙算法(转载)
  6. php 类型 打印机,常见的打印机类型有哪几种
  7. Linux开发速记教程之第一篇
  8. Android 自定义控件属性
  9. typora使用PicGo自动上传图片到chevereto图床服务器
  10. 17.unity粒子特效--Renderer模块、灯光模块、粒子系统组合、二级发射器、粒子间碰撞、粒子拖尾