纹理

借助纹理映射技术,我们可以将图像数据映射到三角形图元中。在Direct3D中,纹理用接口IDirect3DTexture9来表示。

1.纹理坐标

Direct3D使用的纹理坐标,由沿水平方向的u轴和沿垂直方向的v轴构成。用坐标对(u,v)标示的纹理元素称为纹理元。为了能处理不同尺寸的纹理,Direct3D将纹理坐标做了规范处理,使之限定在区间[0,1]内。纹理的FVF标记:D3DFVF_TEX1.

2.创建并启用纹理

纹理数据通常从磁盘的图像文件读入,然后再加载到IDirect3DTexture9对象中。使用的函数如下:

HRESULT D3DXCreateTextureFromFile(
  LPDIRECT3DDEVICE9 pDevice, //创建纹理的设备
  LPCTSTR pSrcFile,   //要加载的文件
  LPDIRECT3DTEXTURE9 * ppTexture //要创建的纹理
);
设置为当前纹理,用如下函数:
HRESULT IDirect3DDevice9::SetTexture(
  DWORD Sampler,  //第几层纹理,最多8层,(0-7).
  IDirect3DBaseTexture9 * pTexture //要设置的纹理
);
若禁用某一层纹理,将pTexture置为0。Device->SetTexture(0,0);
3.纹理过滤器

有时纹理三角形为了适应屏幕三角形,会进行相应的放大或缩小。这样会产生纹理畸变,为了克服这种畸变,Direct3D采用了纹理过滤技术。

Direct3D提供了3种类型的纹理过滤器,纹理过滤方式可用Device->SetSamplerState方法。

3.1最近点采样

3.2线性纹理过滤

3.3各向异性纹理过滤

4.多级渐进纹理

由某一纹理创建一系列分辨率逐渐减小的纹理图像,并对每种分辨率下的纹理所采用的过滤方式进行定制,保留那些重要的细节。这一系列的纹理图像称为多级渐进纹理链。

4.1多级渐进纹理过滤器

Device->SetSamplerState(0,D3DSAMP_MIPFILTER,Fliter)

Fliter取值:

D3DTEXF_NONE,禁用多级渐进纹理过滤器

D3DTEXF_POINT,Direct3D将选择尺寸与屏幕三角形最接近的那一级纹理。一旦选择了某一级纹理,Direct3D就会用指定的放大过滤器和缩小过滤器对该级纹理进行过滤。

D3DTEXF_LINEAR, Direct3D将选择尺寸与屏幕三角形最接近的两个纹理。用指定的过滤器对每级纹理进行过滤。然后将这两级纹理进行线性组合,形成最终的颜色。

4.2使用多级渐进纹理

如果硬件支持多级渐进纹理,D3DXCreateTextureFromFile函数将创建一个多级渐进纹理链。Direct3D还将自动选择与屏幕三角形最接近的那一级纹理。

5.寻址模式

纹理坐标必须限制在[0,1]。从技术上讲是有问题的,因为坐标有可能超出这个范围。Direct3D定义了4种用来处理纹理坐标超出[0,1]范围的纹理映射模式。分别是:重复寻址模式,边界颜色寻址模式,箝位寻址模式,镜像寻址模式。

同样用SetSamplerState设定。

#include "d3dUtility.h"

IDirect3DDevice9* Device = 0;  //设备
 
const int Width  = 640;
const int Height = 480;

IDirect3DVertexBuffer9* vb = 0; 
IDirect3DTexture9 * tex=0;  //纹理

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;

    static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

//
// Framework Functions
//
bool Setup()
{
    Device->CreateVertexBuffer(               //创建顶点缓存
        12 * sizeof(Vertex), // size in bytes
        D3DUSAGE_WRITEONLY, // flags
        Vertex::FVF,        // vertex format
        D3DPOOL_MANAGED,    // managed memory pool
        &vb,          // return create vertex buffer
        0);                 // not used - set to 0

    Vertex* vertices;
    vb->Lock(0, 0, (void**)&vertices, 0);        //获取指向顶点缓存内容的指针

    vertices[0] = Vertex(-1.0f, -1.0f,1.25f,0.0f,0.0f,-1.0f,0.0f,5.0f);
    vertices[1] = Vertex( -1.0f, 1.0f,1.25f,0.0f,0.0f,-1.0f,0.0f,0.0f);
    vertices[2] = Vertex( 1.0f, 1.0f,  1.25f,0.0f,0.0f,-1.0f,5.0f,0.0f);

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

    vb->Unlock();

    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);  //多级渐进纹理过滤器,选择与屏幕尺寸最接近的那一级纹理

    Device->SetRenderState(D3DRS_LIGHTING, false);  //设置光照不可用

    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(   //投影矩阵
            &proj,
            D3DX_PI * 0.5f, // 90 - degree
            (float)Width / (float)Height,
            1.0f,
            1000.0f);
    Device->SetTransform(D3DTS_PROJECTION, &proj); //投影
    return true;
}
void Cleanup()
{
    d3d::Release<IDirect3DVertexBuffer9*>(vb);
}

bool Display(float timeDelta)
{
    if( Device )
    {
        Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
        Device->BeginScene();

        Device->SetStreamSource(0, vb, 0, sizeof(Vertex));
        Device->SetFVF(Vertex::FVF);
        Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2); //画出顶点缓存中的三角形图元
        Device->SetFVF(Vertex::FVF); 

        Device->EndScene();
        Device->Present(0, 0, 0, 0);
    }
    return true;
}


//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {
    case WM_DESTROY:
        ::PostQuitMessage(0);
        break;
        
    case WM_KEYDOWN:
        if( wParam == VK_ESCAPE )
            ::DestroyWindow(hwnd);
        break;
    }
    return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
                   HINSTANCE prevInstance, 
                   PSTR cmdLine,
                   int showCmd)
{
    if(!d3d::InitD3D(hinstance,
        Width, Height, true, D3DDEVTYPE_HAL, &Device))
    {
        ::MessageBox(0, "InitD3D() - FAILED", 0, 0);
        return 0;
    }
        
    if(!Setup())
    {
        ::MessageBox(0, "Setup() - FAILED", 0, 0);
        return 0;
    }

    d3d::EnterMsgLoop( Display );

    Cleanup();

    Device->Release();

    return 0;
}
Main.cpp
原文地址:https://www.cnblogs.com/hometown/p/3656710.html