Direct3D纹理映射技术

多阶段纹理是在纹理缓存(多阶段可以有0~7个纹理缓存)和顶点多边形之间的决定一个物体的颜色的

单个纹理基本要素有:顶点UV; SetTexture纹理使用和切换; 采样方式SetSamplerState(mag放大min缩小插值,Mip多幅渐进纹理选择算法,纹理寻址)。

如果需要空间纹理包装和多阶层的纹理等,那么就是高级纹理技术了,需要SetTextureStageStateSetRenderState的一些设置和比较多的逻辑,现在先看单个纹理的操作。

 Device->SetTexture(0, Tex);

 Device->SetTexture(0, Tex1);

 Device->SetTexture(0, 0);

D3DTADDRESS_CLAMP

Texture coordinates outside the range [0.0, 1.0] are set to the texture color at 0.0 or 1.0, respectively.

D3DTADDRESS_BORDER

Texture coordinates outside the range [0.0, 1.0] are set to the border color.


一、纹理映射的基本概念

IDirect3DTexture9来表示,纹理是类似于表面的像素矩阵,与表面不同的是它可以被映射到三角形单元中。

1.纹理坐标系是2D纹理图像中的uv坐标系,因为直到三角形顶点光栅化时,三角形已经被映射到屏幕坐标系了,纹理映射才会真正进行,所以uv坐标系类似屏幕坐标系,坐标系原点在图像的左上角,u往右递增,v往下递增,uv大小都在[0,1]的值域范围内。

2.三角形顶点中定义uv坐标,uv坐标系在图像中,但是只有顶点中需要指定uv坐标,图像只需要读取进来即可。

包含纹理坐标的顶点格式:

struct Vertex
{
    Vertex(){}
    Vertex(
        float x, float y, float z,
        float nx, float ny, float nz,
        float u, float v)
    {
        _x  = x;  _y  = y;  _z  = z;
        _nx = nx; _ny = ny; _nz = nz;
        _u  = u;  _v  = v;
    }
    float _x, _y, _z;
    float _nx, _ny, _nz;
    float _u, _v; // texture coordinates

    static const DWORD FVF;
};


3.读取纹理

IDirect3DTexture9*      Tex  = 0;

D3DXCreateTextureFromFile(
        Device,
        "dx5_logo.bmp", //该函数加载的格式,可以是.bmp, .dds, .dib, .jpg, .png和.tga
        &Tex);


4.设置纹理

 Device->SetTexture(0, Tex);

HRESULT SetTexture(
  [in]  DWORD Sampler,// 多层纹理的层级阶段,0-7,层级阶段越多越精致,不启用多层纹理用0
  [in]  IDirect3DBaseTexture9 *pTexture // 纹理
);
不启用纹理时用:

Device->SetTexture(0, 0);

如果在场景中各个三角形使用的纹理不相同,那么setTexture(0,tex0)绘制三角形,再setTexture(0, tex1)绘制下一个三角形。


5.纹理过滤器

通常图像纹理三角形 和屏幕顶点三角形大小不一致,当纹理三角形比顶点三角形小时候,纹理三角形会被放大。当纹理三角形比顶点三角形大时候,纹理三角形会被缩小。

直接贴上去会发生畸形,因此需要纹理过滤器,D3D定义了三种纹理过滤器:

D3DTEXF_POINT,D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC。

D3DTEXF_POINT最快效果比较差,D3DTEXF_LINEAR现在硬件水平也较快效果比较好(推荐使用),D3DTEXF_ANISOTROPIC最慢但效果最好。

D3DTEXF_ANISOTROPIC各向异性纹理过滤时,需要对D3DSAMP_MAXANISOTROPIC水平值进行设定,该值越大效果越好,该值用D3DCAPS9获得合法范围。

实例:

Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

Device->SetSamplerState(0, D3DSAMP_MAXANISOTROPIC, 4); // 4是D3DSAMP_MAXANISOTROPIC的值


6.多级渐进纹理过滤器

DX9中用多级渐进纹理,DX11中已经使用Tessellation技术。多级渐进纹理是创建纹理的时候生成一个纹理链包含256x256,128x128,64x64,32x32,16x16等的系列逐渐减小的图片。将相同的纹理选择恰当的大小到给定大小的光栅化三角形中。

创建:如果硬件支持多级渐进纹理,D3DXCreateTextureFromFile将会创建一个多级渐进纹理链,runtime默认是用D3DTEXF_POINT选择最近的纹理。时间和空间性能都很好,因此多级渐进纹理mip map技术被广泛运用。

多级纹理过滤器主要用于控制D3D使用多级纹理的方式:

Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);// D3DTEXF_POINT是最近的,D3DTEXF_LINEAR是最近的两个线性组合,D3DTEXF_NONE是不使用多级纹理过滤器。


7.纹理坐标超出的寻址模式

如果指定的顶点的坐标超出了纹理坐标[0, 1],那么可以用wrap重复寻址模式,border边界颜色寻址模式,clamp箝位寻址模式,mirror镜像寻址模式。

其中wrap表现好于mirror(都是重复), clamp表现好于border(都是填充颜色).

Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);

Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

// 也可以用D3DTADDRESS_MIRROR模式,D3DTADDRESS_CLAMP,D3DTADDRESS_BORDERCOLOR模式。


二、应用 实例

Device->CreateVertexBuffer(

        6 * sizeof(Vertex),
        D3DUSAGE_WRITEONLY,
        Vertex::FVF,
        D3DPOOL_MANAGED,
        &Quad,
        0);

    Vertex* v;
    Quad->Lock(0, 0, (void**)&v, 0);

    // quad built from two triangles, note texture coordinates:
    v[0] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
    v[1] = Vertex(-1.0f,  1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
    v[2] = Vertex( 1.0f,  1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);

    v[3] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
    v[4] = Vertex( 1.0f,  1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
    v[5] = Vertex( 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);

    Quad->Unlock();

    //
    // Create the texture and set filters.
    //

    D3DXCreateTextureFromFile(
        Device,
        "dx5_logo.bmp",
        &Tex);

    Device->SetTexture(0, Tex);


// 纹理过滤器

    Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

    Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

// 多级渐进纹理过滤器

    Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

    //
    // Don't use lighting for this sample.
    //

    Device->SetRenderState(D3DRS_LIGHTING, false);

// 超出寻址 模式

    // set wrap address mode
        if( ::GetAsyncKeyState('W') & 0x8000f )
        {
            Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
            Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
        }
        // set border color address mode
        if( ::GetAsyncKeyState('B') & 0x8000f )
        {
            Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
            Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
            Device->SetSamplerState(0,  D3DSAMP_BORDERCOLOR, 0x000000ff);
        }

        // set clamp address mode
        if( ::GetAsyncKeyState('C') & 0x8000f )
        {
            Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
            Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
        }

        // set mirror address mode
        if( ::GetAsyncKeyState('M') & 0x8000f )
        {
            Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
            Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
        }   

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值