• 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自带缩放功能,爽歪歪了

  • 相关阅读:
    OpenCV程序在生产环境中运行
    C#调用C++导出(dllexport)方法
    IIS7.5 GZip配置
    wcf学习笔记--初识wcf
    Greenplum installation guide
    Cloudera 5.8.2 Installation guide
    WPF DataGrid 合并单元格
    wpf DataGrid CheckBox列全选
    WPF button 圆角制作
    WPF passwordbox 圆角制作
  • 原文地址:https://www.cnblogs.com/resound/p/1795640.html
Copyright © 2020-2023  润新知