为什么 OpenGL 不从部分位于查看体积之外的几何着色器中剪裁图元?

发布于 2024-11-27 18:58:29 字数 572 浏览 3 评论 0原文

http://www.opengl.org/wiki/Rendering_Pipeline_Overview 说“位于在几何着色器运行之后和片段光栅化之前,观察体内部和外部之间的边界被分成几个基元”。我读过的有关 OpenGL 的其他内容也以同样的方式描述了裁剪过程。但是,通过将片段着色器中的 gl_FragDepth 设置为比生成它的三角形上的点的实际深度更接近相机的值(以便片段通过深度测试,而如果我复制固定的片段则会失败)管道功能),我发现即使它部分重叠远视平面,也会为整个原始三角形生成片段。另一方面,如果所有顶点都在平面后面,则整个三角形都会被剪裁,并且不会将任何片段发送到片段着色器(我想从技术上讲,您会说它是被剔除,而不是剪裁)。

这是怎么回事?我的几何着色器是否会替换某些默认功能?是否需要设置标志/提示或需要写入的其他内置变量,以便渲染管道的下一步知道如何进行部分裁剪?

我在 NVIDIA GeForce 9400M 上使用 GLSL 版本 1.2 和 GL_EXT_geometry_shader4 扩展。

http://www.opengl.org/wiki/Rendering_Pipeline_Overview says that "primitives that lie on the boundary between the inside of the viewing volume and the outside are split into several primitives" after the geometry shader is run and before fragments are rasterized. Everything else I've ever read about OpenGL has also described the clipping process the same way. However, by setting gl_FragDepth in the fragment shader to values that are closer to the camera than the actual depth of the point on the triangle that generated it (so that the fragment passes the depth test when it would have failed if I were copying fixed-pipeline functionality), I'm finding that fragments are being generated for the entire original triangle even if it partially overlaps the far viewing plane. On the other hand, if all of the vertices are behind the plane, the whole triangle is clipped and no fragments are sent to the fragment shader (I suppose more technically you would say it is culled, not clipped).

What is going on here? Does my geometry shader replace some default functionality? Are there flags/hints I need to set or additional built-in variables that I need to write to in order for the next step of the rendering pipeline to know how to do partial clipping?

I'm using GLSL version 1.2 with the GL_EXT_geometry_shader4 extension on an NVIDIA GeForce 9400M.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无妨# 2024-12-04 18:58:29

这听起来像是一个驱动程序错误。如果您可以看到本应位于查看区域之外的片段的结果(即:如果关闭深度写入会导致片段完全消失),那么这违反了规范的行为。

诚然,这是一个极端的案例,我怀疑有人会对此采取任何行动。

大多数图形硬件都会尽力避免实际剪切三角形。剪切三角形意味着可能从单个三角形生成 3 个以上的三角形。这往往会阻塞管道(无论如何预细分)。因此,除非三角形是微不足道的可拒绝的(即:在剪辑框之外)或非常大,否则现代 GPU 就会忽略它。他们让片段剔除硬件来处理它。

在这种情况下,因为您的片段着色器是深度写入着色器,所以它认为在片段着色器完成之前它无法拒绝这些片段。


注意:我意识到,如果您打开深度钳制,则会完全关闭近剪裁和远剪裁。这可能就是你想要的。从片段着色器写入的深度值被固定到当前的glDepthRange。

深度钳位是 OpenGL 3.2 的一项功能,但 NVIDIA 通过 NV_深度_钳位对其提供了近十年的支持。如果您的驱动程序是最新的,即使您没有获得 3.2 兼容性上下文,您也应该能够使用 ARB_depth_clamp。

That sounds like a driver bug. If you can see results for fragments that should have been outside the viewing region (ie: if turning off your depth writes causes the fragments to disappear entirely), then that's against the spec's behavior.

Granted, it's such a corner case that I doubt anyone's going to do anything about it.

Most graphics hardware tries as hard as possible to avoid actually clipping triangles. Clipping triangles means potentially generating 3+ triangles from a single triangle. That tends to choke the pipeline (pre-tessellation at any rate). Therefore, unless the triangle is trivially rejectable (ie: outside the clip box) or incredibly large, modern GPUs just ignore it. They let the fragment culling hardware take care of it.

In this case, because your fragment shader is a depth-writing shader, it believes that it can't reject those fragments until your fragment shader has finished.


Note: I realized that if you turn on depth clamping, that turns off near and far clipping entirely. Which may be what you want. Depth values written from the fragment shader are clamped to the current glDepthRange.

Depth clamping is an OpenGL 3.2 feature, but NVIDIA has supported it for near on a decade with NV_depth_clamp. And if your drivers are recent, you should be able to use ARB_depth_clamp even if you don't get a 3.2 compatibility context.

万水千山粽是情ミ 2024-12-04 18:58:29

如果我理解正确的话,你会想知道你的三角形没有被远平面剪裁。
Afaik OpenGL 只是在顶点组装后对 4 个边界平面进行剪辑。远近剪切在片段着色器之后完成(根据规范)。即,当您极度放大并且多边形与近平面碰撞时,它们会渲染到该点并且不会整体弹出。
而且我认为规范根本没有注意到分割图元(即使硬件可能在屏幕空间中忽略片段深度),它只是注意到整个跳过图元(在没有顶点位于视锥体中的情况下)。
另外,依赖 wiki 来获取精确的单词规则始终是一个坏主意。

PS: http: //fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/ 解释了实际的边框和近距和远距剪裁非常好。

If I understood you correctly, you wonder that your triangles aren't clipped against the far plane.
Afaik OpenGL just clips against the 4 border planes after the vertex assembly. The far and near clipping gets done (by spec afaik) after the fragment shader. Ie when you zoom in extremely and polygons collide with the near plane they get rendered to that point and don't pop away as a whole.
And I don't think that the specs note splitting primitives at all (even when the hw might do that in screenspace ignoring fragdepth), it just notes skipping primitives as a whole (in the case that none vertex lies in the view frustum).
Also relying on a wiki for word-exact rules is always a bad idea.

PS: http://fgiesen.wordpress.com/2011/07/05/a-trip-through-the-graphics-pipeline-2011-part-5/ explains the actual border and near&far clipping very good.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文