查看: 4523|回复: 5
打印 上一主题 下一主题

[Shaders] ShadowGun shader 解析(1)

[复制链接]

1557

主题

1

听众

1万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
454
精华
31

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2013-10-11 17:23:57 |只看该作者 |倒序浏览
去年的时候就从网上下了这个工程,虽然只有一个场景和一些shader,不过这些已经足够了。像这样公司能将自己项目的一部分放在网上供大家学习真是难能可贵的,对于untiy移动平台的开发人员更是重要的学习资料。
大家可能打开项目之后无从下手,虽然ShadowGun的效果更现在次时代游戏比起来还是有差距的,不过在当时的移动平台上可是赚足了眼球。其实的优化方法值得大家学习。本文希望有一定shader基础的人来阅读,我怕误人子弟,对别人的代码上理解上可能有些偏差。请大家提出宝贵意见,共同学习共同进步。
这个项目我在itouch4上测试过,平均30-40帧,最多3万个三角形。


大家看到上面这张图了么,这是shadowgun游戏里的第一个场景,我要更大家讲的就是,人物的材质,地面的材质,雕像的材质,体积光的材质等等这些。本文不是教程,不会由浅入深为大家讲解,所以会把一些有趣的shader先展示给大家,我认为对大家更有帮助。
1.红旗飘飘


我先来讲讲这个彩旗飘飘的效果,我们的美术想要这个效果,我就研究了一下。发觉很有意思。Shader里关键的代码在这里

[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em]2

[backcolor=rgb(250, 250, 250) !important][size=1em]3

[size=1em]4

[backcolor=rgb(250, 250, 250) !important][size=1em]5

[size=1em]6

[backcolor=rgb(250, 250, 250) !important][size=1em]7

[size=1em]8

[backcolor=rgb(250, 250, 250) !important][size=1em]9

[size=1em]10

[backcolor=rgb(250, 250, 250) !important][size=1em]11

[size=1em]12

[backcolor=rgb(250, 250, 250) !important][size=1em]13

[size=1em]14

[backcolor=rgb(250, 250, 250) !important][size=1em]15

[size=1em]16

[backcolor=rgb(250, 250, 250) !important][size=1em]17

[size=1em]18

[backcolor=rgb(250, 250, 250) !important][size=1em]19

[size=1em]20

[backcolor=rgb(250, 250, 250) !important][size=1em]21

[size=1em]22

[backcolor=rgb(250, 250, 250) !important][size=1em]23

[size=1em]24

[backcolor=rgb(250, 250, 250) !important][size=1em]25

[size=1em]26

[backcolor=rgb(250, 250, 250) !important][size=1em]27

[size=1em]28

[backcolor=rgb(250, 250, 250) !important][size=1em]29

[size=1em]30

[backcolor=rgb(250, 250, 250) !important][size=1em]31

[size=1em]32

[backcolor=rgb(250, 250, 250) !important][size=1em]33

[size=1em]34

[backcolor=rgb(250, 250, 250) !important][size=1em]35

[size=1em]36

[backcolor=rgb(250, 250, 250) !important][size=1em]37

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]inline float4 AnimateVertex2(float4 pos, float3 normal, float4 animParams,float4 wind,float2 time)
[size=1em]{  
[backcolor=rgb(250, 250, 250) !important][size=1em]    // animParams stored in color
[size=1em]    // animParams.x = branch phase
[backcolor=rgb(250, 250, 250) !important][size=1em]    // animParams.y = edge flutter factor
[size=1em]    // animParams.z = primary factor
[backcolor=rgb(250, 250, 250) !important][size=1em]    // animParams.w = secondary factor
[size=1em]      
[backcolor=rgb(250, 250, 250) !important][size=1em]    float fDetailAmp = 0.1f;
[size=1em]    float fBranchAmp = 0.3f;
[backcolor=rgb(250, 250, 250) !important][size=1em]           
[size=1em]    // Phases (object, vertex, branch)
[backcolor=rgb(250, 250, 250) !important][size=1em]    float fObjPhase = dot(_Object2World[3].xyz, 1);
[size=1em]    float fBranchPhase = fObjPhase + animParams.x;
[backcolor=rgb(250, 250, 250) !important][size=1em]           
[size=1em]    float fVtxPhase = dot(pos.xyz, animParams.y + fBranchPhase);
[backcolor=rgb(250, 250, 250) !important][size=1em]           
[size=1em]    // x is used for edges; y is used for branches
[backcolor=rgb(250, 250, 250) !important][size=1em]    float2 vWavesIn = time  + float2(fVtxPhase, fBranchPhase );
[size=1em]           
[backcolor=rgb(250, 250, 250) !important][size=1em]    // 1.975, 0.793, 0.375, 0.193 are good frequencies
[size=1em]    float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0);
[backcolor=rgb(250, 250, 250) !important][size=1em]           
[size=1em]    vWaves = SmoothTriangleWave( vWaves );
[backcolor=rgb(250, 250, 250) !important][size=1em]    float2 vWavesSum = vWaves.xz + vWaves.yw;
[size=1em]      
[backcolor=rgb(250, 250, 250) !important][size=1em]    // Edge (xz) and branch bending (y)
[size=1em]    float3 bend = animParams.y * fDetailAmp * normal.xyz;
[backcolor=rgb(250, 250, 250) !important][size=1em]    bend.y = animParams.w * fBranchAmp;
[size=1em]    pos.xyz += ((vWavesSum.xyx * bend) + (wind.xyz * vWavesSum.y * animParams.w)) * wind.w;
[backcolor=rgb(250, 250, 250) !important][size=1em]      
[size=1em]    // Primary bending
[backcolor=rgb(250, 250, 250) !important][size=1em]    // Displace position
[size=1em]    pos.xyz += animParams.z * wind.xyz;
[backcolor=rgb(250, 250, 250) !important][size=1em]           
[size=1em]    return pos;
[backcolor=rgb(250, 250, 250) !important][size=1em]}




大家打开TerrainEngine.cginc文件.../Unity\Editor\Data\CGIncludes这个目录下面,里面有个AnimateVertex函数,大家就可以知道这函数从哪里来的。这还没完,如果有人看过GPU GEMS 3 里面有一篇Chapter 16. Vegetation Procedural Animation and Shading in Crysiscrysis的植被特效。建议大家看看,不要以为是老技术,其实技术没有新旧,只是看能不能为我所用。Crysis中的这个方法,用VS来完成摆动动画,节约了很多资源。可以腾出更多的性能空间。尤其是手持设备更应该注意的问题。
没想到shadowgun改都没改就拿过来用了,连注释都一样,如果不知道出处根本就不知道是什么。当然shadowgun的牛人是理解的,因为权重是写在模型顶点颜色上的,不知道这个怎么做的出效果。不过下面这段代码在这个效果里其实没什么用,因为_Object2World[3].xyz000,本来是用来做向位移的。为了做风吹过以后的层次感。

[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em]2

[backcolor=rgb(250, 250, 250) !important][size=1em]3

[size=1em]4

[backcolor=rgb(250, 250, 250) !important][size=1em]5

[size=1em]6

[backcolor=rgb(250, 250, 250) !important][size=1em]7

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]// Phases (object, vertex, branch)
[size=1em]    float fObjPhase = dot(_Object2World[3].xyz, 1);
[backcolor=rgb(250, 250, 250) !important][size=1em]    float fBranchPhase = fObjPhase + animParams.x;
[size=1em]      
[backcolor=rgb(250, 250, 250) !important][size=1em]      
[size=1em]  float fDetailAmp = 0.1f;
[backcolor=rgb(250, 250, 250) !important][size=1em]    float fBranchAmp = 0.3f;




就是振幅.

[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em]2

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]// x is used for edges; y is used for branches
[size=1em]    float2 vWavesIn = time  + float2(fVtxPhase, fBranchPhase );




Crysis里叶子的边用了x,叶子当中的茎干用yshadow gun里旗子本身的摆动用了y,边上的摆动用了x。其实都差不多,就是你有时想不到这么用。

[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em]2

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]// 1.975, 0.793, 0.375, 0.193 are good frequencies
[size=1em]float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0);




是将两个频率映射成4个,不知道大家能否理解,这样就有了4个不同的频率。

[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]vWaves = SmoothTriangleWave( vWaves );




这里用了三角波,就是为了不用sin cos 为了一点效率,很有借鉴,不过还要看实际测试。

[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]float2 vWavesSum = vWaves.xz + vWaves.yw;




将两个频率合并,为了看上去没有规律。

[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em]2

[backcolor=rgb(250, 250, 250) !important][size=1em]3

[size=1em]4

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]// Edge (xz) and branch bending (y)
[size=1em]    float3 bend = animParams.y * fDetailAmp * normal.xyz;
[backcolor=rgb(250, 250, 250) !important][size=1em]    bend.y = animParams.w * fBranchAmp;
[size=1em]    pos.xyz += ((vWavesSum.xyx * bend) + (wind.xyz * vWavesSum.y * animParams.w)) * wind.w;






这里就是融合的部分,animParams.y叶子的权重从顶点色的绿色获得,fDetailAmp 振幅,normal法线叶子是按法线方向飘动的。下面也是一样的道理。
[url=]复制代码[/url]
[backcolor=rgb(250, 250, 250) !important][size=1em]1

[size=1em][backcolor=rgb(250, 250, 250) !important][size=1em]pos.xyz += animParams.z * wind.xyz;




加上风的偏移量,最后就完成了。

总结:
建议大家可以参考gpugems3上的文章,看更多的材料可以帮大家更好的理解,这个方法,我认为也是不错的。植被,简单的布料,旗帜,都可以用。虽然简单但很有效,完全用gpu计算,用于大量使用的话更有效的。


  • [url=][/url]
  • 图片:图片2.png

    [url=][/url]




分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏1 支持支持0 反对反对0
回复

使用道具 举报

nts    

3

主题

1

听众

743

积分

初级设计师

Rank: 3Rank: 3

纳金币
7
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2013-10-13 11:18:56 |只看该作者
希望楼主提供原文章地址
回复

使用道具 举报

0

主题

1

听众

1174

积分

助理设计师

Rank: 4

纳金币
92
精华
0
板凳
发表于 2014-5-7 04:14:43 |只看该作者
感謝分享!
回复

使用道具 举报

1

主题

5

听众

2200

积分

中级设计师

Rank: 5Rank: 5

纳金币
7
精华
0

活跃会员

地板
发表于 2014-5-7 09:20:46 |只看该作者
感谢分享!
回复

使用道具 举报

0

主题

2

听众

4092

积分

中级设计师

Rank: 5Rank: 5

纳金币
530
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

5#
发表于 2014-5-14 09:58:35 |只看该作者
thank you thanks sharing
回复

使用道具 举报

0

主题

1

听众

929

积分

初级设计师

Rank: 3Rank: 3

纳金币
142
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

6#
发表于 2014-5-14 13:24:56 |只看该作者
ShadowGun shader 解析
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-11 10:39 , Processed in 0.108759 second(s), 32 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部