怎么才能设置材质为只写深度,不写颜色

我想做一个角色的半透明效果,需要在多个角色互相遮挡时能够在遮挡部分将多个角色正确的显示出来,制作思路是由远到近(ue4会对半透明角色自动排序)对每一个角色进行两次渲染,两次都设置为半透明模式,第一次只写深度不写颜色,第二次正常判断深度后计算半透明颜色。
现在问题出来了,第一次的渲染使用半透明材质无法写深度,如果第一次使用opaque材质的话则能写深度但是会修改掉颜色(不能保持当前背景的颜色)。
我怎么才能设置材质为只写深度,不写颜色的效果呢?或者有没有什么更好的实现半透明互相遮挡时还能正确渲染的方法?

Hi ttaw,

关于半透明的乱序问题,你可以使用Translucency Sort Priority:

多个角色如果不能穿插,只是前后遮挡,你可以动态的改变这个值来试试。(修改这个值也要考虑跟场景其他半透互动的问题)
如果想要自定义深度信息,可以留意上图的Render CustomDepth Pass,勾选后会产生一个单独的CustomDepth Buffer。如果是半透明材质记得在材质的属性上勾选 Allow Custom Depth Writes。

不过先画深度 再画颜色还是无法解决排序问题,游戏内用的比较多的还有OIT排序(https://developer.nvidia.com/content/transparency-or-translucency-rendering)你可以看看是否符合你的需求。

谢谢答复。关于oit排序,我想问一下ue4里边直接支持您说的oit排序吗?是不是需要自己做那几个rendertarget?

其实我要的半透明不是oit里那种,我想要的是一个角色只考虑离视点最近那一层表面的颜色(半透明),该角色的其他层不考虑;但是如果是另外一个被前一个角色遮挡的角色B,我还是只考虑B的最近层半透明,B里更远的层不考虑。
现在要实现这种效果的困难就是:怎么让半透明材质能写入深度,其他就没有问题了。我试过调整OpacityMaskClipValue为0,但是还是没有写入深度值。

OIT目前需要自己做,UE4还没有现成的功能。

Render CustomDepth Pass就是让材质写入深度的方法。
场景里角色的Rendering下的Render CustomDepth Pass勾选。(如果是动态加载可以在蓝图或者代码中启用。)
角色的半透材质属性勾选Allow Custom Depth Write。
然后你在编辑器中的Buffer Visualization中选择 Custom Buffer就能预览结果。

但是customdepth pass是一个单独的pass,在绘制半透明角色的时候,customdepth里边只包含经过所有半透明角色的最小深度值,这样的最终深度值,我拿着没法进行我要做的渲染。我需要在绘制半透明角色A的时候只使用角色A的深度(不使用B的深度),绘制半透明角色B的时候只使用角色B的深度。而不是在绘制A和B的时候使用A和B的总体最小深度。

但是customdepth pass是一个单独的pass,在绘制半透明角色的时候,customdepth里边只包含经过所有半透明角色的最小深度值,这样的最终深度值,我拿着没法进行我要做的渲染。我需要在绘制半透明角色A的时候只使用角色A的深度(不使用B的深度),绘制半透明角色B的时候只使用角色B的深度。而不是在绘制A和B的时候使用A和B的总体最小深度。

你可以使用材质节点:SceneTexture中的Scene Depth通道的数据获取场景中其他物体的深度。
Custom depth给你了半透明物体额外写深度的一种方式。
不管你用任何方法,结合你前面所说,你需要保证某个物体的半透信息,其实主要涉及的还是排序,只不过你不需要把所有半透明都按深度排序,但是你依然需要比较深度值,选择合适的深度,这个过程就是一种排序比较。
不过目前为止,我依旧不能完全明白你的目标到底是什么,也许你可以上传截图,把问题描述的更清晰一些。另外请告知我你的实现途径,是c++代码,是蓝图?还是纯材质?目前你的进展到了那里,你的需求的明确目标等等。
信息越详细,越方便继续讨论这个问题。

抱歉,没有描述清楚我的问题。下面我详细的描述一下:

1.我的实现途径是蓝图+材质,使用的是角色蓝图和角色的skeletonmesh里的材质。
2.我使用的原始模型(非透明,贴在这里仅仅是让你能大概了解这个模型)是下面这样的:
正面:
pic1

侧面:
pic2

背面:
pic3

使用的半透明材质的单个模型是下面这样的:

pic4

可以看到这样的方法(方法1)实现的模型的腰部有多层透明面(衣服和腰部都能看到),这不是我想要的。我想要的是下面这样的(方法2)(腰部被衣服遮挡了):

pic5

方法1的实现细节是:直接使用半透明材质渲染。
方法2的实现细节是:对角色开启customdepth通道,使用半透明材质时判断customdepth剔除掉模型不可见的部分(比如腰部被衣服遮挡了,被剔除),只渲染深度值小于或等于customdepth的部分。
到目前为止,方法2的效果就是我想要的正确结果,但这是在只有一个角色的情况下。当有两个透明角色互相遮挡时就不对了,此时方法2的结果是这样的:

pic6见下面的评论

可以看到,在两个角色遮挡的部分,近处角色被正确半透明了,但是远处角色被遮挡了,不能看到远处角色。这仍然不是我想要的。我想要的是遮挡部分能看到远处角色,因为近处角色是半透明的,理应看到远处角色。我想要的最终结果是下面这样的:

pic7见下面的评论

可以看到,远处角色的腰部衣服虽然被近处角色遮挡了,但是仍然能看见。这就是我想要的最终结果(方法3)。
方法3的实现细节是:对两个角色使用当前的相机角度先分别进行一次rtt,渲染出两个角色的两张深度信息贴图,然后在半透明pass中判断这两个贴图深度和模型深度的大小关系,只渲染近处的面。
也就是说,方法1不是我要的,方法2仅仅在无多角色遮挡时是我要的,方法3的效果则不管有没有遮挡都是我想要的。但是方法3有一个问题,就是对于每个半透明角色,我需要对其渲染一次rtt深度贴图,我测试时每个贴图需要约2ms的时间,感觉效率有点低。于是我想使用方法4。
方法4:在ue4的半透明渲染通道对每个模型进行两次渲染(每个模型的skeletonmesh都复制成两个skeletonmesh,并分别设置不同的材质mat1和mat2),第一次只使用mat1渲染深度,第二次使用这个深度和mat2渲染半透明模型的近表面部分。也就是说在两个半透明模型A和B时,先将AB根据距离视点的远近由远到近排序,然后渲染远处模型A的深度(不改颜色),再进行半透明渲染A(此时剔除掉A中不可见的部分,比如A的腰部被A的衣服遮挡,需要剔除A的腰部),再渲染近处模型B的深度(不改颜色),再半透明渲染B(同样剔除B中的不可见部分)。由于每个模型的两次渲染有先后关系,两个模型之间也有先后关系,所以A和B的深度渲染需要在ue4的半透明通道中进行,所以材质需要为半透明材质,但是我不知道怎么在ue4中对半透明材质写入深度值,所以方法4暂时没法实现。

ps:方法4使用customdepth通道是不行的,因为customdepth是ue4的一个单独通道,时间在半透明渲染通道之前,所以半透明渲染时,我只能得到A和B的总体深度值,而方法4需要分别使用A和B的单独深度值。

图片6和7如下:
pic6

pic7

我补充了一下问题,还有几张图片,您再帮我看看,谢谢。

这样的话你总归是需要一个“分层”操作来区分一个区域内是自身半透还是不同物体半透的叠加。由于不管是CustomDepth还是CustomStencial都是全局唯一的Buffer且里面的值会被覆盖,所以你需要至少两个同时存在的CustomeDepth(或者是一个Stencil buffer但是提供值的累计而非覆盖),但是目前引擎不提供这样的功能。这就可能需要你额外写一些代码来完成渲染流程的调整,这涉及到了修改引擎代码。

好的,谢谢您的耐心解答:)

再提供给你一个变通方法,你可以看看是否能满足你的需求。

这里为了简化制作步骤并且避免一些引擎某方面的限制,可以使用Dithered Alpha的原理来完成类似的功能。效果如上图。实现方法如下:

优点:避免了半透明排序,半透明混合的效率问题。
缺点:不是基于Blend,仔细观察有Screen Door效应。

好的,多谢。我仔细研究研究