人气 553

[综合技术] ShadowGun shader 解析(1) [复制链接]

ylifk 2012-12-5 16:07:35

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
去年的时候就从网上下了这个工程,虽然只有一个场景和一些shader,不过这些已经足够了。像这样公司能将自己项目的一部分放在网上供大家学习真是难能可贵的,对于untiy移动平台的开发人员更是重要的学习资料。
大家可能打开项目之后无从下手,虽然ShadowGun的效果更现在次时代游戏比起来还是有差距的,不过在当时的移动平台上可是赚足了眼球。其实的优化方法值得大家学习。本文希望有一定shader基础的人来阅读,我怕误人子弟,对别人的代码上理解上可能有些偏差。请大家提出宝贵意见,共同学习共同进步。
这个项目我在itouch4上测试过,平均30-40帧,最多3万个三角形。其实30-40帧是不够的,游戏里还要加上动画脚本AI等等,把他们融合在一起才是游戏。对于开发者来说平衡他们之间的关系变得尤为重要。

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

项目下载网站
http://blogs.unity3d.com/2012/03/23/shadowgun-optimizing-for-mobile-sample-level/


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

  1. inline float4 AnimateVertex2(float4 pos, float3 normal, float4 animParams,float4 wind,float2 time)
  2. {
  3. // animParams stored in color
  4. // animParams.x = branch phase
  5. // animParams.y = edge flutter factor
  6. // animParams.z = primary factor
  7. // animParams.w = secondary factor
  8. float fDetailAmp = 0.1f;
  9. float fBranchAmp = 0.3f;
  10. // Phases (object, vertex, branch)
  11. float fObjPhase = dot(_Object2World[3].xyz, 1);
  12. float fBranchPhase = fObjPhase + animParams.x;
  13. float fVtxPhase = dot(pos.xyz, animParams.y + fBranchPhase);
  14. // x is used for edges; y is used for branches
  15. float2 vWavesIn = time  + float2(fVtxPhase, fBranchPhase );
  16. // 1.975, 0.793, 0.375, 0.193 are good frequencies
  17. float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0);
  18. vWaves = SmoothTriangleWave( vWaves );
  19. float2 vWavesSum = vWaves.xz + vWaves.yw;
  20. // Edge (xz) and branch bending (y)
  21. float3 bend = animParams.y * fDetailAmp * normal.xyz;
  22. bend.y = animParams.w * fBranchAmp;
  23. pos.xyz += ((vWavesSum.xyx * bend) + (wind.xyz * vWavesSum.y * animParams.w)) * wind.w;
  24. // Primary bending
  25. // Displace position
  26. pos.xyz += animParams.z * wind.xyz;
  27. return pos;
  28. }
复制代码

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

  1. // Phases (object, vertex, branch)
  2. float fObjPhase = dot(_Object2World[3].xyz, 1);
  3. float fBranchPhase = fObjPhase + animParams.x;
  4. float fDetailAmp = 0.1f;
  5. float fBranchAmp = 0.3f;
复制代码
就是振幅
  1. // x is used for edges; y is used for branches
  2. float2 vWavesIn = time  + float2(fVtxPhase, fBranchPhase );
复制代码
Crysis里叶子的边用了x,叶子当中的茎干用y,shadow gun里旗子本身的摆动用了y,边上的摆动用了x。其实都差不多,就是你有时想不到这么用。
  1. // 1.975, 0.793, 0.375, 0.193 are good frequencies
  2. float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0);
复制代码
是将两个频率映射成4个,不知道大家能否理解,这样就有了4个不同的频率。
vWaves = SmoothTriangleWave( vWaves );
这里用了三角波,就是为了不用sin cos 为了一点效率,很有借鉴,不过还要看实际测试。
float2 vWavesSum = vWaves.xz + vWaves.yw;
将两个频率合并,为了看上去没有规律。
  1. // Edge (xz) and branch bending (y)
  2. float3 bend = animParams.y * fDetailAmp * normal.xyz;
  3. bend.y = animParams.w * fBranchAmp;
  4. pos.xyz += ((vWavesSum.xyx * bend) + (wind.xyz * vWavesSum.y * animParams.w)) * wind.w;
复制代码
这里就是融合的部分,animParams.y叶子的权重从顶点色的绿色获得,fDetailAmp 振幅,normal法线叶子是按法线方向飘动的。下面也是一样的道理。
  1. pos.xyz += animParams.z * wind.xyz;
复制代码
加上风的偏移量,最后就完成了。


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

使用道具 举报

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

QQ|手机版|小黑屋|九艺游戏动画论坛 ( 津ICP备2022000452号-1 )

GMT+8, 2024-4-27 17:20 , Processed in 0.135709 second(s), 23 queries .

Powered by Discuz! X3.4  © 2001-2017 Discuz Team.