对象指针信息编码:除了坐标外,我们还可以存储其他信息,如物体对应的实体或者网格之类的指针。这类信息的特点是这个物体的信息都是一致的,也就是说相对于Shader中同一次DP或者DIP call是一个常量,在Shader中标识uniform,所以我将作为一个全局变量,在CPU中通过ID3DXEFFECT::SetFloat进行设置,再在Pixel Shader中加入到顶点的颜色信息中。Shader中的主要代码如下:
uniform float pobj;
…
float4 PS_main (float4 mColor:COLOR):COLOR
{
return float4(mColor.rgb,);
}
而在C++的程序中,可以对指针进行赋值,
long pobj=(long)this;
float fobj=(float)pobj;
effect->SetFloat("pobj",fobj);
信息的解析与检索:信息解码的主要在CPU上完成,因为只需要解析点中的点,基本流程是用GetRenderTargetData拷回表面的一个SystemMemeory副本,然后锁定该副本表面,将拾取的点的各个通道值转换成float*在读出来,数组的0123位依次是颜色的RGBA值。解码的主要代码如下:
PickResult finalret;
pPickSurface->LockRect(&lockbits,&rect,D3DLOCK_READONLY);
pPickSurface->UnlockRect();
float* bits=(float*)(lockbits.pBits);
finalret.position.x=bits[0];
finalret.position.y=bits[1];
finalret.position.z=bits[2];
float fobj=bits[3];
long pobj=(long)fobj;
finalret.pObject=(GRuntimeMesh*)pobj;
return finalret;
D3DFMT_A32B32G32R32F 128位浮点纹理:在RTT产生的纹理图中,我们不仅加入了坐标信息,而且加入了指针信息。通过指针传递我们可以记录关于物体的各种信息。但是指针对纹理存贮的精度要求很高,不能存在丝毫误差。在32位的系统中,一个指针占4字节,在C++程序中,我们采用long类型进行传递,而传入Shader时我们采用了float类型。而对于绘制时所用的纹理,我们必须保证A通道有8×4,也就是32位,所以我们采用了D3DFMT_A32B32G32R32F格式,即32Bit IEEE Float格式的纹理。
GetRenderTargetData and LockRect:对于pick所得的纹理,我们可以简单地直接LockRect纹理最高精度表面的(x,y)texel检索值,然而如果我们直接Lock的话,会可能让CPU等待GPU完成当前的绘制操作再进行Lock操作,为了提高并发性,可以采取readonly标识和GetRenderTargetData()函数把RenderTarget表面拷回到SystemMemory的一个表面再检索。GetRenderTargetData()能够把GPU上RenderTarget的一个表面直接完整拷贝到内存,再用带D3DLOCK_READONLY和D3DLOCK_DONOTWAIT等标识Lock指定要Pick的象素。 |