3D拾取指的是中原六仔平台搭建论坛:haozbbs.com Q1446595067 将鼠标在屏幕上点击的位置匹配到3d游戏场景中的某个图元上,该图元投影到屏幕上的像素恰好就是鼠标点击的像素。3D场景在很多交互情境中有重要作用,使开发者的应用能够将用户的点击对应到场景空间中的物体上。例如:用户可以通过点击选中某个物体或者物体的某一部分进行删除等后续操作。在这个教程中的demo中,我们将渲染几个物体,并且展示如何使用红色标记选中的三角形图元使其突出显示。
为了实现3D拾取,我们将用到第23章阴影贴图教程中介绍的OpenGL特性:帧缓存对象(FBO)。之前我们使用FBO只用作深度缓冲,因为我们感兴趣的是从不同角度来比较像素的深度。而在3D拾取中,我们将既使用深度缓冲又要使用颜色缓冲,来存储渲染的三角形的索引值。
3D拾取背后的技巧很简单,对每一个三角形在程序运行时附加一个索引,并让片段着色器输出每个像素所在三角形的索引值。结果是我们将得到一个颜色缓冲,但是并不包含颜色值,而是像素所在的图元的索引值。当鼠标点击在窗口上,我们将根据鼠标的点击位置来获得这个索引并将这个三角形渲染成红色。由于有深度测试,所以能够保证当片元之间相互覆盖时也可以得到最顶部的片元的索引(离相机最近的)。
上面就是3D拾取的概念和原理了,下面在进入代码之前,我们需要做一些设计上的决策。例如,如何处理多物体的情况?如何处理一个物体多次draw call渲染的情况?我们需要为每个物体设置递增的图元索引使场景中每一个图元都有唯一的索引,还是为每一个物体都重置其索引?
这篇教程的代码采用了一种普遍的方法,可以根据需要进行简化,会为每一个像素渲染三级索引:
第一级是像素所在物体的索引值,场景中的每一个物体都会得到一个唯一的索引;
物体的draw call的索引,这个索引会在开始渲染新物体时重置;
每个draw call中图元的索引值,每次新的draw call开始时该索引会重置。
在我们读取每个像素的索引时实际上我们就将获取到上面的三级索引数据了。之后我们将对特定的图元进行相应的处理。
我们需要渲染场景两次。一次叫做“纹理拾取”,纹理包含图元索引数据。另一次则直接渲染到实际的颜色缓冲。因此,住渲染循环会有一个拾取的阶段和一个渲染阶段。
注:这里的demo中使用的蜘蛛模型来自于Asssimp的资源包。它包含多个VB,可以帮助我们测试这里的例子。
源代码详解
见原文。
原文地址:http://blog.51cto.com/13857087/2137650