3D引擎中高效拾取(Pick)像素级数据(可见对象, 深度,法线等)
请见Demo:http://www.artvily.com/renderCase?sample=mousePickNormal
很多3D应用中需要获取像素级别的数据用于各种操作,例如需要知道光标选中了哪个显示对象这种常见的应用。
其实合理的引擎渲染器渲染管理机制之下,很容易拿到几乎是任何想拿到的某个可见像素的信息,例如法线,切线,光照或阴影相关数据,三角形信息等等。
上面的示例中演示了获得光标所在位置对应的像素所在的3D物体,以及位深度,世界坐标,法线这几个信息。
原理是通过 GPU 将对应的像素想要的信息,绘制到GPU back buffer, 然后取出这个back buffer中的数据。一般的渲染流程实际绘制存放的是 R,G,B,A四个颜色值GPU中每个值的取值范围是0.0->1.0, 例如在Opengl中当我们通过 readPixels获取到的R,G,B,A的值是0->255的整型。由上可见你要通过片段着色器将你想写入的值,写入到back buffer,你就要想办法将这个值规范到取值范围为0.0->1.0的四个值中去。通过readPixels读取到之后,再换算回来。例如这里要写入0->10000范围内的V值,及确定将他们存放在 R, G两个变量内,那么 R=floor(V/255.0)/255.0, G=fract(v/255.0). fract函数的意思是取得浮点数的小数部分。readPixels拿到数据之后,计算v = (r + g/255.0) * 255.0;
鼠标拾取的过程:
1. 射线检测,通过空间管理,筛选出可能与射线相交的3D对象所在的子空间节点
2. 接上一步的结果,射线检测包围盒,得到可能真正相交的准备进入渲染的一系列物体,这一系列物体一般无需太多
3.进入特定的渲染流程(使用已有的顶点,渲染数据对象等数据,尽可能不创建生成新的逻辑对象),在blend关闭的情况下clear(0.0,0.0,0.0,0.0), 然后渲染, 只需渲染一个像素的屏幕区域。
4.获得像素级别拾取的对象,这个对象就是一定光标碰触的对象。这个过程得到其他数据。
5.若要获取其他数据,只需重复按需求渲染这个选中的对象即可。
合理的引擎的渲染器的渲染管理机制,可以用极低的性能开销,获取有价值的相关信息