1 问题背景
有一个3D游戏对象(再次强调,是3D对象,不是2D的UI喔),如Cube, Plane啥的,需要贴上一张图,图中有部分区域是透明的。比如酱紫: 然后,如果直接贴图片,则透明区域会显示黑色。例如:
2 解决方案
2.1 场景搭建
首先,创建一个3D对象,如Cube。 然后,把图像加入到工程的Assets目录下。
Hierarchy面板选中Cube,然后把Project面板的图片,直接拖到Inspector面板。 发现,Cube显示了图片。但是,透明区域是黑色的。 这有2个问题需要弄清楚。
2.1.1 为什么图片可以直接作为组件存在于Inspector面板
其实图片还是原来的图片,只不过,Unity自动的帮你创建了一个材质(Material),材质的纹理来源是图片。不信请看图片的工程目录下,是不是自动创建了一个Material目录?里面还有一个名字和图片一样的文件?具体说明如下: 所以图片并没有作为组件,你看到的是一个新建的材质。
这意味着,你也可以自己创建材质,然后材质的纹理来源选择为图片,然后把材质赋给Cube。
材质知识补充: 要在 Unity 中绘制某物,必须提供描述其形状的信息以及描述其表面外观的信息。使用网格可描述形状,使用材质可描述表面的外观。材质资源是扩展名为 .mat 的文件
2.1.2 为什么是黑色
如上面图中说的,自动创建的材质,其Shader的Rendering Mode是不透明。所以显示了黑色。
解决办法?下面分2种思路来讨论
2.2 方案1 把Rendering Mode从Opaque改为Fade
几个Rendering Mode的说明如下:
Opaque - 此项为默认设置,适用于没有透明区域的普通固体对象。
Cutout - 用于创建在不透明区域和透明区域之间具有硬边的透明效果。在这种模式下,没有半透明区域,纹理为 100% 不透明或不可见。使用透明度来创建材质的形状时(如树叶或者有孔洞和碎布条的布料),这非常有用。
Transparent - 适用于渲染逼真的透明材质,如透明塑料或玻璃。在此模式下,材质本身将采用透明度值(基于纹理的 Alpha 通道和色调颜色的 Alpha),但与真实透明材质的情况一样,反射和光照高光将保持完全清晰可见。
Fade - 允许透明度值完全淡出对象,包括对象可能具有的任何镜面高光或反射。如果要对淡入或淡出的对象进行动画化,此模式将非常有用。它不适合渲染逼真的透明材质,如透明塑料或玻璃,因为反射和高光也会淡出。
从上面看,选择Fade是最合适的。
效果如下:
2.3 方案2 修改Shader为UI/Unlit/Transparent
效果:
高能预警 : 有咩有发现,方案2比方案1,颜色要真实一些? 方案1,其实颜色有点发白,因为其shader必须选一个Albedo(反射率): 默认白色,换别的颜色,更明显。比如红色:
而方案2,就没有再做什么二次处理。颜色就是纹理本身的颜色。
结论,请选用方案2!
2.4 shader源码分析
从上面可知,Unity有很多内置的Shader,如Standard, Transparent,每种的效果不一样的。 其中UI-Unlit层级下,表示一些 不包含光照的基本的shader
我们可以找到其源码: https://github.com/newchenxf/Unity-Built-in-Shaders/blob/master/DefaultResourcesExtra/UI/UI-Unlit-Transparent.shader 简单说明一下shader语法:
第一行是名字。斜杠代表其层级。 Proterties表示参数。 SubShader:是具体的顶线/片元着色器实现。Unity会扫描所有的SubShader,然后选择第一个能够在目标平台运行的,如果不支持,则使用Fallback语义指定的Unity Shader。 Fallback: SubShader在所有的显卡都不能用,或者没有写,那就用Fallback定义的一个保底方案。
上面没有SubShader,所以去看UI/Default实现: https://github.com/newchenxf/Unity-Built-in-Shaders/blob/master/DefaultResourcesExtra/UI/UI-Default.shader
发现代码非常友好,基本只做纹理采样。 当然了,也乘于一个IN.color。这个是在这里赋值的 只要我们选白色(白色是255, 255, 255),归一化后就是1,相当于乘于1,相当于还是纹理本身的颜色。所以最后的小鬼,纹理啥颜色就是啥颜色。
好了,代码也分析结束咯,可以安心的选用UI/Unlit/Transparent啦
参考
渲染模式 (Rendering Mode)
|