为什么Unity材质无法正确呈现半透明效果?

4
我有一个Unity材质,其反射率基于精灵表。 精灵具有半透明性,并且格式化为RGBA 32位。 现在,透明度在精灵中呈现,但在材质中没有呈现。 如何在不使反射率的不透明部分变得透明的情况下实现这一点?
我尝试将渲染模式设置为透明,消失和无光/透明。 结果看起来像这样:

Structures are assigned opaque but acts semi transparent

Structure is assigned to be opaque but acts semi transparent

我尝试了不透明度,但它破坏了质感。我尝试了切割,但半透明度会消失或变成完全不透明(取决于切割)。这没有代码。
我期望输出使材料的半透明部分半透明,不透明部分不透明。实际输出要么完全不透明,要么完全“半透明”,这非常烦人。
编辑
所以我推迟了工作并添加了子网格。因此,它非常接近解决问题。

enter image description here

它仍然出现那个故障。


请尝试使用 Fade - derHugo
@derHugo 嗯,是的,我已经尝试过了,不起作用。 - Kino Bacaltos
反馈:问题是为了 Stack Overflow 上的未来读者编写的。"我只用一只手打字,请修复" 这样的问题既需要编辑又需要点踩。通常,有经验的读者会将此视为内容破坏的形式。 - halfer
我不知道一旦准则改变,我们需要更改所有的帖子。这篇帖子是一年前发布的。 - Kino Bacaltos
2个回答

21
好消息和坏消息。好消息是,这个问题并不罕见,甚至不仅仅限于Unity。坏消息是,它之所以不罕见或不与Unity独有,是因为这是一个普遍存在的问题,没有完美的解决方案。但我们可能能够为您找到一个解决方法,所以让我们一起来解决这个问题。
在3D图形中存在一个根本性问题:你按什么顺序绘制物体?如果你在现实生活中画一幅普通的图片,显而易见的答案是你按照离观察者的距离远近来绘制物体。这个方法一段时间内效果还不错,但是对于那些不干净地“在前面”的物体怎么办呢?请考虑以下图片:

A photograph of a basket containing fruit

那个篮子里的水果是在碗前面还是后面?有点两者都不是,对吧?而且即使你能将物体分成前面和后面,如何处理相交的物体呢?这时就需要用到Z缓冲器:

A simple 3D scene containing several meshes above a greyscale representation of the Z-Buffer of that scene

Z-Buffer是一个简单的想法:在绘制对象的像素时,还要绘制这些像素的深度,也就是它们距离相机的远近。当你在场景中绘制一个新对象时,你会检查底层像素的深度,并将其与新像素的深度进行比较。如果新像素更接近,你就覆盖旧像素。如果旧像素更接近,你就不做任何处理。Z Buffer通常是一个单通道(即灰度)图像,从未直接显示。除了深度排序外,它还可以用于各种后期处理效果,如雾或环境光遮蔽。
现在,深度缓冲区的一个关键组成部分是它只能存储每个像素一个值。大多数情况下,这很好;毕竟,如果你只是想对一堆对象进行排序,你真正关心的只是最前面对象的深度。任何在最前面对象后面的东西都将被渲染为不可见,这就是你需要知道或关心的全部。
也就是说,除非你最前面的对象是透明的。

Four images illustrating various intersecting transparent planes

问题在于渲染器不知道如何处理绘制在透明对象后面的对象。为了避免这种情况,聪明的渲染器(包括Unity)会按照以下步骤进行:
1. 以任意顺序绘制所有不透明对象。 2. 按照与摄像机的距离对所有透明对象进行排序。 3. 从最远到最近绘制所有透明对象。
这样,遇到奇怪的深度排序问题的可能性就被最小化了。但在某些情况下,这仍然会出现问题。当您的对象使用透明材质时,实际上99%的对象是固体的,这一点是完全无关紧要的。就Unity而言,整个对象都是透明的,因此它根据其相对于场景中其他透明对象的深度进行绘制。如果您有大量透明对象,并且网格相交,那么您将立即遇到问题。
那么,如何解决这些问题呢?您有几个选择。
首先,也是最重要的一点,您可以将透明材质限制在明确透明的区域。我认为渲染顺序首先基于材质,因此具有多个不透明材质和单个透明材质的网格可能会正常工作,不过这只是我的猜测。
其次,如果您有其他选择,请使用它们。 "Cutout"模式之所以似乎是二进制掩码而不是真正的透明度,是因为它确实如此。由于它不是真正的透明,您不会遇到通常会遇到的深度排序问题。这是一种权衡。
第三,尽量避免使用透明材料的大型相交对象。大水体在这方面往往会引起问题。仔细考虑你所要处理的内容。
最后,如果你确实需要多个大型相交透明物体,请考虑将它们分成多个部分。
我知道这些答案都不是真正令人满意的,但关键是要认识到这不是一个 bug,而是媒介的限制。如果你非常想解决这个问题,可以尝试挖掘自定义渲染管线,但请记住,如果这样做,你将付出更多的性能代价。
祝好运。

游戏中有许多大水体。一个网格是否可以有两个纹理?(基于UV和资源)我的意思是这样的。一个被认为是不透明的四边形在一个材质中有一个不透明的纹理。然后还有另一个四边形,它是透明的,在另一个材质中有一个透明的纹理。这可能吗? - Kino Bacaltos
1
我相信是这样的。实际上,每个网格可以有多个“子网格”,它们基本上是共享一个材质的三角形列表。在3D建模程序中,这些可能被称为“材质槽”或类似的东西。 - VPellen
绘制调用会延迟运行时间多少? - Kino Bacaltos

0

你说你尝试了透明着色器模式,但是,你尝试过在材质颜色中更改 Alpha 通道值吗? 第二张图片似乎 RGBA 中的 Alpha 值为 0,请尝试更改它。


什么意思?我的精灵制作器可以保存精灵和其阿尔法通道。 - Kino Bacaltos
读完最后一个回答,我只能想到我低估了你的问题。哈哈.. 但是我在人形模型中遇到了类似的问题,通过将纹理的Alpha通道设置为255来解决了这些问题,我认为如果你尝试类似的方法,可能会有所帮助..但我不确定是否适用于你的情况。很抱歉浪费了你的时间。 - Marcos Defina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接