DirectX9:基础篇 纹理
一.简介
纹理映射是一种为三角形赋予图像数据的技术
在 Direct3D 中一个纹理是通过 IDirect3DTexture9 接口来表示,一个纹理是一个像素矩阵的表面被映射到三角形上
二.纹理坐标
Direct3D 使用一个纹理坐标系统,它是由水平方向的 u 轴(向右为正)和竖直方向 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 ; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)