D3D实现BitBlt 截取贴图 UV纹理寻址方式

本文摘自百度空间-天涯狂人的空间http://hi.baidu.com/crazyonline/blog/item/e27312d58eb815cd50da4b03.html

感谢原文作者s

D3D实现BitBlt 截取贴图 UV纹理寻址方式

本人愚钝,一直以为D3D贴图只能按照纹理整张整张滴贴图,不能像Win32的GDI一样,选择纹理的一部分,定位坐标,长宽来贴图。哦,当然,这里我指的是将D3D封装成2D贴图,顶点格式是UV纹理坐标+RHW转化后的屏幕坐标格式。

至于顶点格式RHW,都知道是坐标转换的一个标志而已。但是我一直对于uv纹理寻址方式不是很清楚,什么循环寻址,环绕寻址等等,一直没弄明白。只知道2D贴图时,将UV地址设置为1.0就没什么问题了。完全是知其然,不知其所以然。后来遇到了因为UV的纹理,D3D贴图图像扭曲,变形等问题,后来囫囵吞枣滴解决了,还是不知道为啥。最近终于幡然醒悟,发现:UV其实就是来指定贴图的纹理坐标,这个UV是一个百分比。比如一张图长100,那么U设置为0.5,其实就是把坐标设置在100X0.5=50这个地方。这个和我们常用的BitBlt所用的srcx,srcy,width,height有那么一点点区别,但是完全可以将D3D贴图封装一个BitBlt函数出来,给个示例:

bool CD3D9Texture::BltFast(float fDstX,float fDstY,int nDstWidth,int nDstHeight,
         float fSrcX,float fSrcY,int nSrcWidth,int nSrcHeight,
         int alphaValue/* =BLTCOPY */)
{
D3DTLVERTEX v[4] ;
DWORD dwDiffuse=D3DCOLOR_ARGB(alphaValue,255,255,255);
memset( v , 0 , sizeof( v ));
v[0].x = v[3].x = (float)(fDstX) ;
v[1].x = v[2].x = (float)(fDstX+nDstWidth);
v[0].y = v[1].y = (float)(fDstY);
v[2].y = v[3].y = (float)(fDstY+nDstHeight);
v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 
   v[0].z = v[1].z = v[2].z = v[3].z = 0.5f ;
v[0].diffuse = v[1].diffuse = v[2].diffuse = v[3].diffuse =dwDiffuse;

//设置uv纹理坐标,截取贴图,这里是在确定(u,v)贴图左上坐标(x,y)
v[0].tu = v[3].tu = fSrcX / (float)m_nMemoryWidth;
v[0].tv = v[1].tv = fSrcY / (float)m_nMemoryHeight;

//这里是在确定(u,v)贴图右下坐标(x,y)

v[2].tu = v[1].tu = float(fSrcX+nSrcWidth) / (float)m_nMemoryWidth ;
v[2].tv = v[3].tv = float(fSrcY+nSrcHeight) / (float)m_nMemoryHeight ;

if (m_pTexture==NULL)
{
   return false;
}
if (!m_pD3D9Device)
{
   m_pD3D9Device=CD3D9Device::CreateD3D9Device();
}
assert(m_pD3D9Device);
m_pD3D9Device->SetTexture( 0 , m_pTexture );
m_pD3D9Device->SetFVF( D3DFVF_TLVERTEX );
m_pD3D9Device->DrawPrimitiveUP( D3DPT_TRIANGLEFAN , 2 , (LPVOID)v , sizeof( D3DTLVERTEX ));
return true;
}


函数BltFast是D3D下仿GDI的StretchBlt函数,功能一模一样,不过最后一个地方我多了一个半透明程度参数,然后因为是D3D我没有hdcSrc参数和hdcDest参数而已。

最经典的地方就是下面这里了:纹理载入内存之后,纹理的宽度和长度有可能会发生变化【如果文件长宽不是2的次方】,计算uv的时候必须根据内存大小长宽来计算,否则贴图会扭曲变形。

//设置uv纹理坐标,截取贴图
v[0].tu = v[3].tu = fSrcX / (float)m_nMemoryWidth;
v[0].tv = v[1].tv = fSrcY / (float)m_nMemoryHeight;

v[2].tu = v[1].tu = float(fSrcX+nSrcWidth) / (float)m_nMemoryWidth ;
v[2].tv = v[3].tv = float(fSrcY+nSrcHeight) / (float)m_nMemoryHeight ;

这样,你想怎么截取,想怎么贴图都可以了。而且D3D自带缩放功能,爽歪歪了

posted on 2010-08-09 12:21  resound  阅读(4210)  评论(0编辑  收藏  举报

导航