半透明的物体一般不会写Depth,就会导致模型的内部和背面也被画出来,模型就会看起来像一个透视图。解决这个的方法是在第一个Pass中只写入Depth,不渲染任何像素,然后在第二个Pass中把RenderState设为DepthLEqual,这样就可以用DepthTest过滤掉我们不希望渲染出来的内部和背部了。
我在UE4.24中尝试用这个思路解决头发的半透明渲染乱序的问题,但是发现诸多问题。
第一个Pass中只写入Depth,最开始我用的方法是关闭模型选项Render In Main Pass,仅写入CustomDepth
问题1:mobile RenderInMainPass和CustomDepth冲突
表现:模型勾选Custom Depth则RenderInMainPass失效(无论是否启用模型都会渲染)
官方解决:
The Unreal Engine Issues and Bug Trackerissues.unrealengine.com
我参照官方Bug页面解决了这个显示问题,不过后来我发现CustomDepth并不对正常的深度测试有效,半透明还是会乱序,不过CustomDepth可以通过在半透明材质中去手动抠出来实现深度测试,其中也有问题,具体可以参考我的另一篇文章UE4 CustomDepth mobile es3.1不起效问题 - 知乎 (zhihu.com)。这里暂时搁置这个Bug。下面还是讨论正常的Depth写入。
问题2:Render in Depth pass模型选项无效
预期:关闭RenderInMainPass的情况下勾选Render in Depth pass渲染深度
实际:关闭RenderInMainPass,即使勾选Render in Depth pass仍然不渲染深度,无论PC还是Mobile ES3.1都无效(测试工具:RenderDoc)
类似问题:
Render only depthanswers.unrealengine.com
Render to Scene Depth Buffer Onlyanswers.unrealengine.com
经实测发现即使勾上Render In Depth,也不会渲染深度~
解决方案:
对于StaticMesh而言,找到其GetViewRelevance函数(其它每种Mesh都有对应的GetViewRelevance函数这里不列举了)
EngineSourceRuntimeEnginePrivateStaticMeshRender.cpp FStaticMeshSceneProxy::GetViewRelevance(...)
...
Result.bRenderInMainPass = ShouldRenderInMainPass();
在此处添加一行代码:
+ -> Result.bRenderInDepthPass = ShouldRenderInDepthPass(); (这就是为什么开启了Render In Depth Pass选项却没有渲染深度的原因,估计是程序员漏写了~ )
...
ok, build ue4 project , 问题解决。
我们再来测试一下,关闭Opaque模型的RendeInMainPass并且打开RendeInDepth:
这里有点奇怪的是这么一整后头发变成黑色了,猜测一下原因应该是因为写入了头发深度,由于深度测试这里本该渲染头发,而我们又关闭了头发的MainPass渲染,所以就没有任何颜色写入,就是黑色了。
打开Buffer可视化看一下SceneDepth:
已经成功渲染到了SceneDepth。这样我们再叠加一层半透明上去,头发Alpha乱序完美解决:
总结:
这个问题应该是引擎bug,并且一直到我所使用的UE4.24版本并没有解决
欢迎大家来我的主页坐客:
哔哩哔哩 ( ゜- ゜)つロ 乾杯~ Bilibilispace.bilibili.com
欢迎大家加入UE4游戏开发爱好者交流群:1101298523