由于需求,要实现stencil picking,也就是利用模板缓冲来拾取。这里有Delta3D中是如何实现的介绍。看了相关的模板测试的相关资料后,发现这个过程也是很简单的,自己想的过程和Delta3D的实现是类似的,虽然没接触过
Delta3D的代码,但是上面所提及的那文章里看到相关的函数的状态设置还是与想法吻合的。
步骤如下:
1,同屏最多只能有255个可点选的渲染物,以为stencil buffer 最多也才8位【0, 255】其中0代表不可选的东西。这样的话就需要动态的给在当前屏幕的每个可渲染物中加上一个id。改id该id 范围是【0,255】,如果一个物体的id 设置为0 的话则该物体不可选中。
2, 设置模板参考值 为 id , SetRenderState(D3DRS_STENCILREF, id);
3,设置模板测试总是成功。 SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
4,设置模板的更新为,D3DSTENCILOP_REPLACE 当模板测试成功则把 模板参考值写入到模板缓冲中。
5,当鼠标点击时,读取当前模板缓冲区的值,该值就是前面我们设置的id。通过id可以找到相应的选中物体。
但是郁闷的是在对上述想法进行验证的时候去碰的了一个问题,如何取得stencil buffer的值?
我是通过GetDepthStencilSurface来获取,代码如下:
IDirect3DSurface9* pStencilSurface;
HRESULT hr = Device->GetDepthStencilSurface(&pStencilSurface);
if ( FAILED(hr) )
{
::MessageBox(NULL, "error", "get surface failed", MB_OK);
return 0;
}
D3DLOCKED_RECT lockedRect;
hr = pStencilSurface->LockRect(&lockedRect, NULL, D3DLOCK_READONLY);
if ( FAILED(hr) )
{
::MessageBox(NULL, "", "LockRect failed", MB_OK);
return 0;
}
但是郁闷的是 LockRect出错,lock不了,网上查了下发现opengl可以但是dx9好像不行 ,如果要lock 后缓冲区需要改变格式。但这样又不符合我要是有stencil的要求了,不知道有没其他途径可以读取到stencil的值,继续找找资料吧~
posted on 2011-09-13 23:43
木华 阅读(457)
评论(0) 编辑 收藏 引用