[{"data":1,"prerenderedAt":305},["ShallowReactive",2],{"page-Material-1":3,"page-count-Material":304},[4],{"id":5,"title":6,"body":7,"date":281,"description":13,"extension":282,"meta":283,"navigation":286,"path":298,"seo":299,"stem":300,"tags":301,"__hash__":303},"blogs\u002F_legacy\u002F2018\u002F2018-01-01-ue4-material-deepdive-note.md","深入UE4材质管理",{"type":8,"value":9,"toc":259},"minimark",[10,14,17,21,24,27,32,35,38,42,45,48,51,54,57,61,64,67,70,73,76,80,83,90,93,96,99,102,106,109,114,118,121,126,129,132,135,139,142,146,149,154,157,162,168,171,174,177,182,185,188,193,196,201,204,209,212,216,221,224,229,232,237,240,244,247,250,253,256],[11,12,13],"p",{},"UE4的材质系统使用起来虽然很方便，但是如果不进行有效的管理，很快就会导致项目的体积变得不可控制，材质编译时间也会变成痛苦的折磨。",[11,15,16],{},"本文是EpicJapan UE4 DeepDive系列中材质管理部分的总结，对应UE4版本为4.12~14。部分截图来自4.18。",[18,19,20],"h2",{"id":20},"抽离共通逻辑",[11,22,23],{},"为了减少材质的编译尺寸，首先要做的就是将共通的逻辑都抽出来。",[11,25,26],{},"在材质系统中一共有以下两种做法",[28,29,31],"h3",{"id":30},"material-function","Material Function",[11,33,34],{},"材质函数可以将一些共同的操作逻辑抽取出来，这样在进行材质的编译的时候，就不会产生重复的部分了。",[11,36,37],{},"UE4本身就提供了大量的材质函数来方便进行材质的表现。",[28,39,41],{"id":40},"material-instance","Material Instance",[11,43,44],{},"材质实例通过将通用的材质统合起来，有效的减少材质的数量。",[11,46,47],{},"使用上，如果材质之间就只有贴图或者参数不同的话，就可以构建一个基础的材质，然后将需要变化的材质进行参数化。",[11,49,50],{},"并创建材质实例以应对不同的情况。",[18,52,53],{"id":53},"选项优化",[11,55,56],{},"材质在使用时有的选项需要进行优化，否则就会生成很多不会使用到的部分。导致编译时间变长且无端的占用发布体积。",[28,58,60],{"id":59},"usage","Usage",[11,62,63],{},"材质的选项中有一个Usage的选项，通常会自动勾选上Automatically Set Usage in Editor。",[11,65,66],{},"这个选项会在材质被特定的Usage使用的时候自动打开，针对每一种Usage会生成新的Shader来进行对应。",[11,68,69],{},"但是，Usage被打开后，如果不再在对应的Usage中使用的话，引擎并不会自动的关闭这个Usage，所以需要手动的进行关闭。",[11,71,72],{},"这个选项的作用在极端情况下特别大：使用全部Usage时1837K的材质在仅使用Static Light时却只有97K的。",[11,74,75],{},"因此在使用的时候还是需要进行额外的注意的，如果默认去掉这个选项的话，就可以有效的避免误操作导致的勾选了。当然使用起来就会有些麻烦。",[28,77,79],{"id":78},"shader-permutation-reduction","Shader Permutation Reduction",[11,81,82],{},"在项目设置>渲染中，能够看到",[11,84,85],{},[86,87],"img",{"alt":88,"src":89},"image","\u002Fwp-content\u002Fuploads\u002F2017\u002F12\u002Fimage_thumb.png",[11,91,92],{},"这个也是类似的选项，在没有使用对应的功能的时候去掉就好了。",[11,94,95],{},"这个如果去掉了却在使用对应的功能的话，编辑器内会有屏幕输出提示，可以放心使用。",[18,97,98],{"id":98},"材质实例关系",[11,100,101],{},"材质实例的继承关系会很大的影响到材质的编译过程，部分继承的属性重写是会导致材质实例需要生成新的Shader的。",[28,103,105],{"id":104},"override-properties","Override properties",[11,107,108],{},"材质属性覆盖会导致需要为实例生成新的Shader",[11,110,111],{},[86,112],{"alt":88,"src":113},"\u002Fwp-content\u002Fuploads\u002F2017\u002F12\u002Fimage_thumb-1.png",[28,115,117],{"id":116},"static-switch-parameter","Static Switch Parameter",[11,119,120],{},"开关是需要额外的生成Shader的",[11,122,123],{},[86,124],{"alt":88,"src":125},"\u002Fwp-content\u002Fuploads\u002F2017\u002F12\u002Fimage_thumb-2.png",[11,127,128],{},"当然也包括Static Component Mask Parameter。",[11,130,131],{},"因此在进行材质实例的继承的时候，应当进行规划，首先分支出Switch等需要重新生成Shader的材质实例后，再继承其他的如贴图、颜色这些不会导致重新生成的材质实例的继承。",[11,133,134],{},"同时，由于材质实例不携带Usage属性，所以这个问题上只能一开始就进行分开。",[18,136,138],{"id":137},"tips","Tips",[11,140,141],{},"这个是SE的演讲者给出的一些操作建议。",[28,143,145],{"id":144},"textrue","Textrue",[11,147,148],{},"尽量减少图形的分辨率，在使用单色的Textrue时，使用1x1的图片即可，在需要过渡特效时，使用一个小条就可以了。",[11,150,151],{},[86,152],{"alt":88,"src":153},"\u002Fwp-content\u002Fuploads\u002F2017\u002F12\u002Fimage_thumb-3.png",[11,155,156],{},"而有对称性的图片，可以通过调整Tilling Method来减小尺寸。",[11,158,159],{},[86,160],{"alt":88,"src":161},"\u002Fwp-content\u002Fuploads\u002F2017\u002F12\u002Fimage_thumb-4.png",[11,163,164],{},[165,166,167],"strong",{},"Mipmap",[11,169,170],{},"有一个ComputeMipLevel的节点可以用于将Mipmap进行可视化调节。",[11,172,173],{},"Mipmap虽然可以在贴图的选项中关掉，但是这样会导致原始贴图常驻内存，运行时消耗很大。",[11,175,176],{},"Texture的Uv入口被用于缩放时并不会对应到MipLevel上，使用时需要注意。",[11,178,179],{},[165,180,181],{},"Power",[11,183,184],{},"不要使用Power来进行2.2次方的运算而是直接相乘。也可以直接将同一个数相乘写成一个材质函数，方便使用。",[11,186,187],{},"因为两个的计算几乎无法目视区分，却有着明显的性能消耗。",[11,189,190],{},[165,191,192],{},"vector displacement map",[11,194,195],{},"矢量置换贴图采用BC7压缩可以大幅减小尺寸？",[11,197,198],{},[165,199,200],{},"Maximum Texture Size",[11,202,203],{},"比LOD Bias能够更好的对贴图尺寸进行控制。",[11,205,206],{},[165,207,208],{},"Never Stream",[11,210,211],{},"会一次性载入所有的MipLevel贴图，在使用频率很高的粒子的贴图上可以打开。",[28,213,215],{"id":214},"material","Material",[11,217,218],{},[165,219,220],{},"除0対策",[11,222,223],{},"为了防止0被传到除法运算上，可以考虑加上0.0001，虽然严格意义上应当使用Max或者Min来进行控制，但是Add的效率更高",[11,225,226],{},[165,227,228],{},"Texture参数",[11,230,231],{},"即便两个参数指定的是同一个Texture，也会进行两次采样。",[11,233,234],{},[165,235,236],{},"SamplerType",[11,238,239],{},"SamplerType选择为Alpha时在有的平台实际上用的确实R通道",[28,241,243],{"id":242},"trick","Trick",[11,245,246],{},"DynamicParameter 对于float2、float3、float4，如果实际上需要的参数是一样的话，是可以用float来代替的，会自动的被变为对应的类型。",[11,248,249],{},"ParticleColor 可以在EmissiveColor不需要通过这个参数指定时用于其他用途",[11,251,252],{},"ParticleRandom是GPU粒子独有的节点，值在0~1之间，可以用于添加随机特效",[11,254,255],{},"Static Component Mask Parameter可以为1张贴图提供四种变数",[11,257,258],{},"UV使用Time进行滚动时，可以先滚动再Tilling，这样的话Tilling进行调整时就不会影响UV动画的速度了。",{"title":260,"searchDepth":261,"depth":262,"links":263},"",2,3,[264,268,272,276],{"id":20,"depth":261,"text":20,"children":265},[266,267],{"id":30,"depth":262,"text":31},{"id":40,"depth":262,"text":41},{"id":53,"depth":261,"text":53,"children":269},[270,271],{"id":59,"depth":262,"text":60},{"id":78,"depth":262,"text":79},{"id":98,"depth":261,"text":98,"children":273},[274,275],{"id":104,"depth":262,"text":105},{"id":116,"depth":262,"text":117},{"id":137,"depth":261,"text":138,"children":277},[278,279,280],{"id":144,"depth":262,"text":145},{"id":214,"depth":262,"text":215},{"id":242,"depth":262,"text":243},"2018-01-01","md",{"layout":284,"status":285,"published":286,"author":287,"author_login":289,"author_email":290,"wordpress_id":291,"wordpress_url":292,"date_gmt":293,"excerpt":294},"post","publish",true,{"display_name":288,"login":289,"email":290,"url":260},"风铃","flinkor","flinkor@foxmail.com",2192,"\u002F\u002F?p=2192","2017-12-31 16:02:08 +0000",{"type":8,"value":295},[296],[11,297,13],{},"\u002F2018-01-01-ue4-material-deepdive-note",{"title":6,"description":13},"_legacy\u002F2018\u002F2018-01-01-ue4-material-deepdive-note",[302,215],"UE4","fKGSuTdtw5DEXqYUD_-VBIoQmLlq-aYwVtmxYL8eN0Q",1,1788763179486]