基于像素的模型精确点取

    游戏引擎中,用鼠标点取模型是一个必需的功能,实现方法也有多种。主要可以分为两类:分别在CPU上和GPU上实现。在CPU上的实现比较简单,可以使用摄像机到鼠标位置组成的射线和模型的包围盒求交。如果需要更加精确的点取,可以进一步和模型的三角形求交,但是这样可能性能不高,因为需要和每一个三角形进行相交计算(或许有更好的方法,只是笔者没有研究过)。另外无法得到绝对精确的结果,因为有的模型是镂空的材质(例如树叶)。第二个方法在GPU上实现,这也是笔者在此详述的方法。下面以D3D 9.0的实现为例(OpenGL中大同小异,此外OpenGL API中提供了点取的功能),介绍实现步骤,大致如下:

    一、准备工作

    初始化时使用IDirect3DDevice9::CreateRenderTarget创建一个和后台颜色缓冲区一样大小,一样的抗锯齿等级且颜色格式是D3DFMT_A8R8G8B8的IDirect3DSurface9接口,创建一个1x1的表面,创建一个位于系统内存的1x1的纹理。

    二、每一祯中

    1、渲染正常的场景。

    2、求出和射线相交的所有的模型。

    3、将渲染目标切换成初始化时创建的表面,后台深度模板表面不变。

    4、关闭深度写入,关闭抗锯齿,负向偏移深度,分别渲染相交的模型。对于每一个模型,赋予其一个独一无二的索引DWORD,即颜色(D3D中的颜色使用DWORD表示,在内存中的排列顺序是A8R8G8B8,正好和我们初始化时创建的表面格式一致。注意,这不是巧合,后面我们要用到)。例如第一个模型的颜色是0x00000001,第二个是0x00000001,以此类推。如果使用浮点类型传递给Shader时,分别是float4(0,0,1/255,0),float4(0,0,2/255,0),等等。每个模型的所有像素输出都是其被赋予的颜色值。为了提升效率,只用清除和渲染鼠标附近的几个像素。

    5、使用StretchRect函数将鼠标位置的像素拷贝到1x1的表面。

    6、使用IDirect3DDevice9::GetRenderTargetData将1x1的表面拷贝到1x1的纹理中。

    7、使用IDirect3DTexture9接口的锁定函数,读取1x1的纹理中的数据,转换成DWORD,作为模型的索引值。

    注意,CPU和GPU是异步工作的,也就是说在这一帧中CPU向GPU发送的渲染命令,很可能在下一帧或者下下一帧的时间才能看到,所以步骤6和7需要移到3和4步之间执行。这里的顺序只是为了理解上的方便。

    如果有描述不详或者读者有更好的方法,希望不吝赐教。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值