DirectX9:基础篇 纹理

一.简介

纹理映射是一种为三角形赋予图像数据的技术

在 Direct3D 中一个纹理是通过 IDirect3DTexture9 接口来表示,一个纹理是一个像素矩阵的表面被映射到三角形上

 

二.纹理坐标

Direct3D 使用一个纹理坐标系统,它是由水平方向的 轴(向右为正)和竖直方向 v 轴(向下为正)构成

 

// 纹理坐标系统表示

struct Vertex

{

  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;

 

三.创建纹理

1.D3DXCreateTextureFromFile()

纹理数据可以从存储在磁盘中的图片文件中读取,放入 IDirect3DTexture9 抽象纹理类型

支持的图片格式有: BMP DDS  DIB JPG  PNG  TGA

 

HRESULT D3DXCreateTextureFromFile(

  LPDIRECT3DDEVICE9 pDevice,

  LPCSTR pSrcFile,

  LPDIRECT3DTEXTURE9* ppTexture

);

 

HRESULT IDirect3DDevice9::SetTexture(

  DWORD Stage,

  IDirect3DBaseTexture9* pTexture

);

 

1
2
3
4
5
6
// 创建纹理
IDirect3Dtexture9* _stonewall;
D3DXCreateTextureFromFile(_device, "stonewall.bmp", &_stonewall);
 
// 设置纹理
Device->SetTexture(0, _stonewall);

 

四.过滤器

纹理被映射到屏幕中的三角形上,有可能纹理和三角形不一样大,当出现需要对纹理进行变形的时候,就要用过滤(Filtering)来让变形平滑的技术

Direct3D提供了三种不同的过滤器,每种的品质级别和速度各不相同

 

1.Nearest point sampling

默认的过滤方法,品质最差,速度最快

1
2
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);

 

2.Linear filtering

推荐使用,过滤产生的效果好

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

 

3.Anisotropic filtering

过滤产生的品质最好,处理时间最长

1
2
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);

 

4.Mipmaps过滤器

如果显卡支持Mipmaps,Direct3D会自动选择与三角形最匹配的Mipmap

1
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);  // 不使用 mipmap<br>Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); <br>Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

 

五.寻址模式

纹理坐标必须指定在[0, 1]之间

Direct3D的寻址模式有四种: 环绕纹理寻址模式 边框颜色纹理寻址模式  截取纹理寻址模式 镜像纹理寻址模式

1.环绕纹理寻址模式(wrap address mode)

1
2
3
4
5
if (::GetAsyncKeyState('W') & 0x8000f)
{
    Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);  
}

 

2.边框颜色纹理寻址模式(border color address mode)

1
2
3
4
5
6
if (::GetAsyncKeyState('B') & 0x8000f)
{
    Device>SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
    Device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0x000000ff);
}

 

3.截取纹理寻址模式(clamp address mode)

1
2
3
4
5
if (::GetAsyncKeyState('C') & 0x8000f)
{
    Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
}

 

4.镜像纹理寻址模式(mirror address mode)

1
2
3
4
5
if (::GetAsyncKeyState('M') & 0x8000f)
{
    Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
}

 

六.例子

1.不过滤纹理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "d3dUtility.h"
 
IDirect3DDevice9* Device = 0;
 
const int Width = 640;
const int Height = 480;
 
IDirect3DVertexBuffer9* Quad = 0;
IDirect3DTexture9* Tex = 0;
 
struct Vertex
{
    Vertex(){}
 
    float _x, _y, _z;
    float _nx, _ny, _nz;
    float _u, _v;
 
    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;
    }
 
    static const DWORD FVF;
};
 
const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
 
bool Setup()
{
    Device->CreateVertexBuffer(
        6 * sizeof(Vertex),
        D3DUSAGE_WRITEONLY,
        Vertex::FVF,
        D3DPOOL_MANAGED,
        &Quad,
        0);
 
    Vertex* v;
    Quad->Lock(0, 0, (void**)&v, 0);
 
    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();
 
    // 加载纹理文件
    D3DXCreateTextureFromFile(Device, "a.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,
        (float)Width / (float)Height,
        1.0f,
        1000.0f);
    Device->SetTransform(D3DTS_PROJECTION, &proj);
 
    return true;
}
 
void Cleanup()
{
    d3d::Release<IDirect3DVertexBuffer9*>(Quad);
    d3d::Release<IDirect3DTexture9*>(Tex);
}
 
bool Display(float timeDelta)
{
    if (Device)
    {
 
        Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
        Device->BeginScene();
 
        Device->SetStreamSource(0, Quad, 0, sizeof(Vertex));
        Device->SetFVF(Vertex::FVF);
        Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
 
        Device->EndScene();
        Device->Present(0, 0, 0, 0);
    }
    return true;
}

 

 

2.过滤处理纹理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "d3dUtility.h"
 
//
// Globals
//
 
IDirect3DDevice9* Device = 0;
 
const int Width = 640;
const int Height = 480;
 
IDirect3DVertexBuffer9* Quad = 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(
        6 * sizeof(Vertex),
        D3DUSAGE_WRITEONLY,
        Vertex::FVF,
        D3DPOOL_MANAGED,
        &Quad,
        0);
 
    Vertex* v;
    Quad->Lock(0, 0, (void**)&v, 0);
 
    v[0] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.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, 3.0f, 0.0f);
 
    v[3] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f);
    v[4] = Vertex( 1.0f,  1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f);
    v[5] = Vertex( 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 3.0f);
 
    Quad->Unlock();
 
    //
    // Create the texture and set texture
    //
 
    D3DXCreateTextureFromFile(
        Device,
        "a.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 the projection matrix
    //
 
    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(
        &proj,
        D3DX_PI * 0.5f,
        (float)Width / (float)Height,
        1.0f,
        1000.0f);
    Device->SetTransform(D3DTS_PROJECTION, &proj);
 
    return true;
}
 
void Cleanup()
{
    d3d::Release<IDirect3DVertexBuffer9*>(Quad);
    d3d::Release<IDirect3DTexture9*>(Tex);
}
 
bool Display(float timeDelta)
{
    if (Device)
    {
        //
        // Update the scene
        //
 
        // 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);
        }
 
        //
        // Draw the scene
        //
 
        Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
        Device->BeginScene();
 
        Device->SetStreamSource(0, Quad, 0, sizeof(Vertex));
        Device->SetFVF(Vertex::FVF);
        Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
 
        Device->EndScene();
        Device->Present(0, 0, 0, 0);
 
    }
    return true;
}

 

posted @   言午丶  阅读(1009)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示