OpenGL学习笔记24-Face culling

Face culling 面选取

试着在心里想象一个3D立方体,数一数你能从任何方向看到的最大面数。如果你的想象力不太有创意,你可能会得到最多3个。你可以从任何位置和/或方向观看一个立方体,但你不能看到超过3个面。为什么我们要浪费时间去画另外3张我们看不见的面呢。如果我们可以以某种方式丢弃它们,我们将节省超过50%的立方体碎片着色器运行!

我们说超过50%而不是50%,是因为从某些角度看,只能看到两个甚至一个面。那样的话,我们可以节省50%以上。

这确实是一个很棒的想法,但我们需要解决一个问题:我们如何知道一个物体的面是否从观察者的角度看不见?如果我们想象一个闭合的形状,它的每个面都有两面。每一面要么面向用户,要么向用户显示背面。如果我们只能渲染面向观众的面呢?

这正是面部剔除所做的。OpenGL检查所有面向观众的面,并在丢弃所有面向观众的面时呈现这些面,节省了我们大量的片段着色器调用。我们需要告诉OpenGL我们使用的哪些面是正面哪些面是背面。通过分析顶点数据的缠绕顺序,OpenGL使用了一个聪明的技巧。

Winding order 缠绕顺序

当我们定义一组三角形顶点时我们用特定的绕圈顺序来定义它们要么顺时针,要么逆时针。每个三角形由3个顶点组成,我们按照从三角形中心看到的缠绕顺序指定这3个顶点。

 

正如你在图片中看到的,我们首先定义顶点1,然后从那里我们可以选择下一个顶点是2还是3。这个选项定义了这个三角形的缠绕顺序。下面的代码说明了这一点:


float vertices[] = {
    // clockwise
    vertices[0], // vertex 1
    vertices[1], // vertex 2
    vertices[2], // vertex 3
    // counter-clockwise
    vertices[0], // vertex 1
    vertices[2], // vertex 3
    vertices[1]  // vertex 2  
};

每个由3个顶点组成的三角形原语包含一个缠绕顺序。OpenGL在呈现原语时使用这些信息来确定三角形是面向前的还是面向后的。默认情况下,定义为逆时针顶点的三角形被处理为面向前方的三角形。

当定义顶点顺序时,将对应的三角形想象成它正对着你,所以指定的每个三角形都应该是逆时针的,就像你正对着那个三角形一样。像这样指定所有顶点很酷的一点是实际的缠绕顺序是在光栅化阶段计算的,所以当顶点着色器已经运行时。然后从观察者的角度来看这些顶点。

此时查看器所面对的所有三角形顶点确实按照我们指定的正确的绕圈顺序排列,但立方体另一侧三角形的顶点现在以一种将其绕圈顺序颠倒的方式呈现。结果是,我们面对的三角形被视为正面的三角形和背面的三角形被视为背面的三角形。下图显示了这种效果:

我们定义两个三角形的顶点数据按照逆时针的顺序(正面和背面三角形为1、2、3)。然而,从观众的方向顺时针呈现三角形如果我们画的顺序1、2和3的查看器的当前的观点。尽管我们以逆时针的顺序指定了后面的三角形,但它现在是以顺时针的顺序呈现的。这正是我们想要剔除(抛弃)不可见的面!

Face culling 面选取

在本章的开始我们说过,如果三角形原语被渲染为面向后的三角形,OpenGL可以丢弃它们。现在我们知道了如何设置顶点的缠绕顺序,我们可以开始使用OpenGL的face culling选项,这个选项在默认情况下是禁用的。

我们在前几章中使用的立方体顶点数据并没有按照逆时针的旋转顺序来定义,所以我更新了顶点数据以反映逆时针的旋转顺序,您可以从这里here.复制它。这是一个很好的实践,尝试并可视化这些顶点确实都是按逆时针顺序为每个三角形定义的。

要启用face culling,我们只需启用OpenGL的GL_CULL_FACE选项:


glEnable(GL_CULL_FACE);  

从这一点开始,所有不是正面的面都将被丢弃(试着在立方体内飞行,看看是否真的丢弃了所有的内面)。目前,如果OpenGL决定先渲染背面,我们可以在渲染片断上节省超过50%的性能(否则深度测试已经将它们丢弃了)。请注意,这只适用于像立方体这样的封闭形状。当我们从上一章中提取草叶时,我们必须再次禁用面部剔除,因为它们的正面和背面应该是可见的。

OpenGL也允许我们改变我们想要剔除的脸的类型。如果我们想要剔除正面而不是背面呢?我们可以用glCullFace定义这个行为:


glCullFace(GL_FRONT);  

glCullFace函数有三种可能的选项:

  • GL_BACK:只选择背面。
  • GL_FRONT:只选择正面。
  • GL_FRONT_AND_BACK:删除正面和背面。

glCullFace的初始值是GL_BACK。我们也可以通过glFrontFace告诉OpenGL我们更喜欢顺时针的脸而不是逆时针的脸:


glFrontFace(GL_CCW);  

默认值是GL_CCW,表示逆时针顺序,另一个选项是GL_CW,(显然)表示顺时针顺序。

作为一个简单的测试,我们可以通过告诉OpenGL,正面现在是由顺时针顺序而不是逆时针顺序来颠倒缠绕顺序:


glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);  

结果是只有背面被渲染:

 

注意,你可以创建相同的效果,通过剔除正面与默认的逆时针旋转顺序:


glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);  

正如你所看到的,面部剔除是提高OpenGL应用程序性能的一个很好的工具;特别是当所有的3D应用程序导出模型与一致的绕线订单(默认CCW)。你必须跟踪哪些对象会从面部剔除中受益,哪些对象根本不应该被剔除。

Exercises

  • Can you re-define the vertex data by specifying each triangle in clockwise order and then render the scene with clockwise triangles set as the front faces: solution
### 回答1: 完美剔除和遮挡剔除都是计算机图形学中的优化技术,目的是在场景中只渲染可见的物体,从而提高渲染效率。 完美剔除是指通过检测物体是否在视野内来剔除不需要渲染的物体。这种剔除方式需要使用一系列算法来检测物体是否可见,包括视锥剔除、反向相交剔除等等。完美剔除的优点是可以剔除不必要的渲染,从而提高帧率和性能,但同时也需要较大的计算开销。 遮挡剔除则是在完美剔除的基础上,通过对物体的相互遮挡关系的检测来进一步提高渲染效率。在遮挡剔除中,通常会使用空间划分树等数据结构来优化遮挡关系的计算。遮挡剔除的优点是可以剔除视线被阻挡的物体,从而降低渲染负载,但是需要在每一帧进行遮挡检测,计算复杂度较高。 总的来说,完美剔除和遮挡剔除都是提高渲染效率的有效方法,但具体应用取决于具体的场景和计算需求。 ### 回答2: Perfect culling - occlusion culling,也叫视野遮挡剔除,是计算机图形学中的一项技术,利用算法判断物体是否在视野或视线范围内,决定哪些物体需要渲染,哪些可以被剔除或隐藏,从而加速计算机图形的处理速度和优化渲染。 完美剔除是指完全的剔除,即仅在无需绘制的情况下进行剔除,从而节省系统资源。通过分析场景中的物体和环境,可以减少未被看到的物体的绘制,从而提高帧率和性能。此外,完美剔除还可以消除隐藏物体对深度测试产生的影响,提高渲染质量。 视野遮挡剔除(Occlusion Culling)是一种先进的完美剔除技术,它基于场景的几何形状,通过计算相机的视线路径对场景中的物体进行剔除。通常,OC会对游戏场景进行预处理,并将相机的视锥体与场景的几何体进行比较,从而确定哪些物体可以被遮挡,从而进行动态的渲染。 综上所述,完美剔除-视野遮挡剔除是一种计算机图形学中高效的技术,可以显着提高渲染效率和性能,并使绘制的图形更加真实和准确。它在游戏开发、虚拟现实等领域有着广泛的应用前景。 ### 回答3: 完美的剔除技术——遮挡剔除 完美的剔除技术通常包括两种类型,一种是静态剔除,另一种是动态剔除。 遮挡剔除是一种静态剔除技术,它的基本原理是在场景渲染前,对场景进行逐像素的遮挡分析,找出被遮挡物体,将其剔除掉,只渲染视图内可见的物体,从而达到提高渲染性能的效果。这种技术可以应用于虚拟现实、游戏开发等领域,尤其是对于大规模场景和复杂场景的渲染,遮挡剔除可以显著降低渲染的开销,提高场景的渲染效率。 具体来讲,遮挡剔除通过采用空间分区、视景体裁剪等技术,将场景以及被渲染物体分为多个区域,然后逐个区域对相邻的物体进行深度比较和遮挡分析,找出被遮挡物体,将其剔除掉。如果采用了合适的剔除策略和算法,遮挡剔除可以大幅减少被渲染对象的数量,从而降低了渲染的开销,提高了渲染效率和帧率。 总的来说,遮挡剔除技术在现代计算机图形学中是非常重要的技术之一,它可以有效地提高场景渲染效率,增加场景的视觉真实感和交互性,是图形学领域中不可或缺的技术之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值