GL_DEPTH_TEST 和透明纹理的渲染故障
从一个角度看,我的灌木看起来像这样:
从另一个角度来看,它们看起来像这样:
我的理论是,当从第一个角度看灌木时,灌木后面的所有块都已经画好了,所以当绘制灌木时,它只是将它们绘制在上面。
然而,从另一个角度来看,它基本上是先尝试绘制灌木,然后当它去绘制灌木后面的块时,它会检查深度缓冲区并发现有东西已经挡住了块的视图,因此它不会不渲染它,导致海军蓝色方块(我的透明颜色)。
我真的不知道如何解决这个问题。禁用深度测试会导致各种其他错误。有没有某种方法可以将顶点或多边形标记为具有透明度,以便它知道它仍然需要渲染后面的内容?
找到了这个。这是唯一的解决方案吗?分离我的透明和不透明块,然后在几乎每一帧的 CPU 上手动对它们进行排序,因为玩家可以四处移动?必须有一种方法将其委托给 GPU...
From one angle my shrubs look like this:
From the other, they look like this:
My theory is that when looking at the shrubs from the first angle, all the blocks behind the shrub have already been drawn, so when it comes to draw the shrub, it just draws them overtop.
From the other angle, however, it's basically trying to draw the shrub first, and then when it goes to draw the block behind the shrub, it checks the depth buffer and sees that there's something already blocking the view of the block, so it doesn't render it, causing the navy blue squares (my clear color).
I really have no idea how to fix this issue though. Disabling the depth test causes all kinds of other errors. Is there some way to flag the vertex or polygon as having transparency so that it knows it still needs to render what's behind?
Found this. Is this the only solution? To separate my transparent and opaque blocks, and then manually sort them on the CPU pretty much every single frame because the player can move around? There has to be a way to delegate this to the GPU...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
该链接(以及 CPU 上的排序)用于 alpha 混合。如果您只需要 Alpha 测试(而不是混合),那么您不需要对任何内容进行排序。只需启用 alpha 测试,同时保持深度测试启用,一切都会渲染得很好。
请参阅此处:http://www.opengl.org/wiki/Transparency_Sorting
您需要需要 alpha 测试的“Alpha 测试”,而不是需要排序的“标准半透明”。
That link (and sorting on CPU) is for alpha blending. If you need only Alpha Testing (not Blending), then you don't need to sort anything. Just enable alpha test, keeping depth test enabled, and everything will be rendered fine.
See here: http://www.opengl.org/wiki/Transparency_Sorting
You need "Alpha test" that requires alpha testing, not "Standard translucent" that requires sorting.
解决方案#1:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
对象(烟/玻璃/草):从最远的多边形到最近的多边形渲染透明场景,禁用深度缓冲区写入 (glDepthMask( GL_FALSE)
)。如果所有透明对象都是凸面且不相交,则可以对对象而不是多边形进行排序。glBlendFunc(GL_SRC_ALPHA, GL_ONE)
和glBlend(GL_ONE, GL_ONE)
(火、“魔法”粒子系统、发光):使用深度缓冲区写入以任意顺序渲染透明场景(glDepthMask(GL_FALSE)
) 已禁用。解决方案#2:
使用深度剥离(谷歌搜索)。特别是当透明物体彼此相交时。不适用于需要解决方案 #1 的粒子系统和草地。
插入排序非常适合已排序或部分排序的数据。
我认为您可以使用具有通道(例如,alpha)的纹理在几何着色器中生成草多边形(以正确的顺序),该通道标记有草和没有草的区域。需要 OpenGL 4,并且您可能必须对要提供给着色器以生成草块的多边形执行某种更高级别的排序。
如果单个灌木在所有方向上完全对称,则可以在顶点着色器中旋转(+- 90/180/270 度)以保持正确的多边形顺序。
还有一种合并排序算法,可以很好地并行化,并且可以使用 GDGPU 方法或 OpenCL/CUDA 在 GPU 上执行。
然而,使用类似的东西来渲染 5 个草丛大致相当于尝试用榴弹发射器杀死一只蟑螂 - 这样做很有趣,但效率不高。
我建议忘记“将其卸载到 GPU”,直到您真正遇到性能问题。使用分析器并始终在优化之前进行测量,否则您将浪费大量开发时间进行不必要的优化。
Solution #1:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
objects (smoke/glass/grass): Render transparent scene from furthest polygon to nearest polygon with depth buffer write disabled (glDepthMask(GL_FALSE)
). If all transparent objects are convex and do not intersect, you can sort objects instead of polygons.glBlendFunc(GL_SRC_ALPHA, GL_ONE)
andglBlend(GL_ONE, GL_ONE)
(fire, "magic" particle systems, glow): Render transparent scene in any order with depth buffer write (glDepthMask(GL_FALSE)
) disabled.Solution #2:
Use depth-peeling (google it). Especially if transparent objects intersect each other. Not suitable for particle systems and grass, which require Solution #1.
Insertion sort works great for already sorted or partially sorted data.
I think you can generate grass polygons (in correct order) in geometry shader using texture that has a channel (say, alpha), that marks areas with and without grass. Requires OpenGL 4, and you probably will have to perform some kind of higher-level sorting for polygons you'll feed to shader to generate grass patches.
Individual shrubs can be rotated in vertex shader (by +- 90/180/270 degrees) to maintain correct polygon ordering if they're perfectly symmetrical in all directions.
And there's merge sort algorithm that parallelizes well and can be performed on GPU, using either GDGPU approach or OpenCL/CUDA.
However, using something like that to render 5 shrubs of grass is roughly equivalent to trying to kill a cockroach with grenade launcher - fun thing to do, but not exactly efficient.
I suggest to forget about "offloading it to GPU" until you actually run into performance problem. Use profilers and always measure before optimizing, otherwise you'll waste large amount of development time doing unnecessary optimizations.
如果您使用的是 WebGL 或 OpenGL ES 2.0 (iPhone/Android),则没有 alpha 测试。相反,您不需要绘制透明像素。这样它们就不会影响深度缓冲区,因为没有写入像素。为此,您需要丢弃片段着色器中透明的像素。您可以对其进行硬编码
,也可以模拟旧式 alpha 测试,您可以在其中设置 alpha 值
If you're in WebGL or OpenGL ES 2.0 (iPhone/Android) there is no alpha testing. Instead you need to not draw transparent pixels. That way they won't affect the depth buffer since no pixel was written. To do that you need to discard pixels that are transparent in your fragment shader. You could hard code it
or you could simulate the old style alpha testing where you can set the alpha value