1 问题背景

有一个3D游戏对象(再次强调,是3D对象,不是2D的UI喔),如Cube, Plane啥的,需要贴上一张图,图中有部分区域是透明的。比如酱紫:

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_unity


然后,如果直接贴图片,则透明区域会显示黑色。例如:

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_02

2 解决方案

2.1 场景搭建

首先,创建一个3D对象,如Cube。
然后,把图像加入到工程的Assets目录下。

Hierarchy面板选中Cube,然后把Project面板的图片,直接拖到Inspector面板。

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_UI_03


发现,Cube显示了图片。但是,透明区域是黑色的。

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_04


这有2个问题需要弄清楚。

2.1.1 为什么图片可以直接作为组件存在于Inspector面板

其实图片还是原来的图片,只不过,Unity自动的帮你创建了一个材质(Material),材质的纹理来源是图片。不信请看图片的工程目录下,是不是自动创建了一个Material目录?里面还有一个名字和图片一样的文件?具体说明如下:

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_05


所以图片并没有作为组件,你看到的是一个新建的材质。

这意味着,你也可以自己创建材质,然后材质的纹理来源选择为图片,然后把材质赋给Cube。

材质知识补充:
要在 Unity 中绘制某物,必须提供描述其形状的信息以及描述其表面外观的信息。使用网格可描述形状,使用材质可描述表面的外观。材质资源是扩展名为 .mat 的文件

2.1.2 为什么是黑色

如上面图中说的,自动创建的材质,其Shader的Rendering Mode是不透明。所以显示了黑色。

解决办法?下面分2种思路来讨论

2.2 方案1 把Rendering Mode从Opaque改为Fade

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_06


几个Rendering Mode的说明如下:

Opaque - 此项为默认设置,适用于没有透明区域的普通固体对象。

Cutout - 用于创建在不透明区域和透明区域之间具有硬边的透明效果。在这种模式下,没有半透明区域,纹理为 100% 不透明或不可见。使用透明度来创建材质的形状时(如树叶或者有孔洞和碎布条的布料),这非常有用。

Transparent - 适用于渲染逼真的透明材质,如透明塑料或玻璃。在此模式下,材质本身将采用透明度值(基于纹理的 Alpha 通道和色调颜色的 Alpha),但与真实透明材质的情况一样,反射和光照高光将保持完全清晰可见。

Fade - 允许透明度值完全淡出对象,包括对象可能具有的任何镜面高光或反射。如果要对淡入或淡出的对象进行动画化,此模式将非常有用。它不适合渲染逼真的透明材质,如透明塑料或玻璃,因为反射和高光也会淡出。

从上面看,选择Fade是最合适的。

效果如下:

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_07

2.3 方案2 修改Shader为UI/Unlit/Transparent

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_3D_08

效果:

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_09

高能预警: 有咩有发现,方案2比方案1,颜色要真实一些? 方案1,其实颜色有点发白,因为其shader必须选一个Albedo(反射率):

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_UI_10


默认白色,换别的颜色,更明显。比如红色:

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_11

而方案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

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_3D_12


简单说明一下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

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_github_13

发现代码非常友好,基本只做纹理采样。

当然了,也乘于一个IN.color。这个是在这里赋值的

unity3D 头发使用透明贴图怎么贴的 unity添加透明贴图_3D_14


只要我们选白色(白色是255, 255, 255),归一化后就是1,相当于乘于1,相当于还是纹理本身的颜色。所以最后的小鬼,纹理啥颜色就是啥颜色。

好了,代码也分析结束咯,可以安心的选用UI/Unlit/Transparent啦

参考

渲染模式 (Rendering Mode)