Direct3D texture mapping

With texture mapping technology, we can map image data into triangular units. This feature can significantly increase the detail and realism of the painted scene. For example, creating a cube and then mapping a plank texture to each face will The cube becomes a crate. In Direct3D, the texture is represented by the interface IDirect3DTexture9 . The texture is a pixel matrix similar to the surface. Unlike the surface, it can be mapped into triangular units.

Texture coordinates

The texture coordinate system used by Direct3D lock consists of the u axis along the horizontal direction and the v axis along the vertical direction. The texture element identified by the coordinate pair (u, v) is called a texture element. Note that the positive direction of the v axis is vertical. down

In order to be able to handle textures of different scales, Direct3D normalizes texture coordinates so that they are limited to the interval [0,1]. For each 3D triangle unit, we can define a corresponding triangle area in the texture, and then Map the texture in the triangle area to the 3D triangle unit. In order to achieve this mapping, the vertex structure needs to be modified again and a texture coordinate pair is added to it to identify the vertices in the texture.

struct TextureVertex
{
	TextureVertex(){}
	TextureVertex()
	{

	}
	float _x, _y, _z;
	float _nx, _ny, _nz;
	float _u, _v;			//纹理坐标
	static const DWORD FVF;
};
const DWORD TextureVertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1; //D3DFVF_TEX1表示顶点结构中包含了一对纹理坐标

Now each triangle formed by 3 vertex objects has a corresponding texture triangle defined in that texture coordinate system. Although specified, the texture will not be used until rasterization, when the 3D triangle has been transformed to the screen coordinate system . Mapping will take place .

Create and enable textures

Texture data is usually read from an image file on disk and then loaded into an IDirect3DTexture9 object. This can be achieved using the D3DXCreateTextureFromFile function, which can load images in the following formats: BMP, DDS, DIB, JPG, PNG and TGA.

HRESULT D3DXCreateTextureFromFile(
	LPDIRECT3DDEVICE9         pDevice,
	LPCSTR                    pSrcFile,
	LPDIRECT3DTEXTURE9*       ppTexture
);
IDirect3DTexture9* _stonewall;
D3DXCreateTextureFromFile(Device, "stonewall.bmp", &_stonewall);

HRESULT IDirect3DDevice9::SetTexture(
	DWORD Stage,	//纹理层
	IDirect3DBaseTexture9* pTexture
);

//禁用某一纹理层,可将pTexture参数设为0,绘制物体时若不想使用纹理可以这样做
Device->SetTexture(0, 0);
renderObjectWithoutTexture();

//如果场景中的各个三角形所使用的纹理均不相同
Device->SetTexture(0, tex0);
drawTrisUsingTex0();

Device->SetTexture(0, tex1);
drawTrisUsingTex1();

In Direct3D, you can set up to 8 layers of textures , which can be combined to create a more detailed image. This is called multi-texturing .

texture filter

Usually the size of the texture triangle and the screen triangle are not consistent. When the size of the texture triangle and the screen triangle are inconsistent, in order to adapt to the latter, the texture triangle needs to be enlarged or reduced. In both cases, distortion occurs. In order to overcome it to some extent For this type of distortion, Direct uses a technology called texture filtering .

Direct3D provides 3 types of texture filters. The higher the quality of the filter, the greater the computational overhead and the slower the processing speed. The texture filtering method can be set using the SetSamplerState method .

Closest point sampling : The filtering method used by Direct3D by default. This method has the fastest processing speed but the worst effect. The following codes respectively indicate setting the closest point sampling method to the enlargement filter and the reduction filter.

Linear texture filter : This type of filtering can produce pretty good results and is fast with current hardware configurations.

Anisotropic texture filtering : This type of filtering can produce the best results, but the processing speed is also the slowest. When using this filtering, the D3DSAMP_MAXANISOTROPIC level value must be set, which determines the quality of anisotropic filtering. level. The larger the value, the better the image effect. Please call the IDirect3DDevice::GetDeviceCaps function to check the returned D3DCAPS9 structure parameters to obtain the legal value range of the value supported by the hardware.

//设置最近点采样纹理过滤
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);

//设置线性纹理过滤
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

//设置各向异性纹理过滤
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);

//将各向异性过滤的质量水平设置为4
Device->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);

Multi-level progressive texture

The triangles on the screen are usually not the same size as the texture triangles. In order to minimize the impact caused by the size difference between the two, we can create a multi-level progressive texture chain for the texture by creating a series of gradually decreasing resolutions from a certain texture. The texture image and the filter used for the texture at each resolution must be customized in order to retain the more important details. It is very easy to use multi-level progressive textures in Direct3D. If the hardware supports multi-level progressive textures, the D3DXCreateTextureFromFile function will create A multi-level progressive texture chain. In addition, Direct3D will automatically select the first-level texture from the texture chain that best matches the screen triangle. Therefore, since it can be automatically set by Direct3D, and the time and space costs during processing are relatively low, multi-level Progressive textures are widely used.

Multi-level progressive texture filter

The multi-level progressive texture filter is mainly used to control the way Direct3D uses multi-level progressive textures. You can set the multi-level progressive texture filter as follows

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

Filter can take the following values

D3DTEXF_NONE : Disable the multi-level progressive texture filter
D3DTEXF_POINT : By using this filter, Direct3D will select the level of texture whose size is closest to the screen triangle. Once a level of texture is selected, Direct3D will use the specified amplification filter and The reduction filter filters the texture of this level
D3DTEXF_LINEAR : By using this filter, Direct3D will take the two texture levels closest to the screen triangle size, use the specified enlargement filter and reduction filter to filter each level of texture, and then These two levels of textures are then linearly combined to form the final color value.

Addressing mode

In the previous section, we said that texture coordinates must be limited to the interval [0,1]. From a technical point of view, this is problematic because sometimes the coordinates may exceed this range. Direct3D defines 4 methods to handle texture coordinate values ​​exceeding [ 0,1] interval texture mapping mode. They are repeated addressing mode (wrap), border color addressing mode (border color), clamp addressing mode (clamp), and mirror addressing mode (mirror).

//set wrap address mode
if (::GetAsyncKeyState('W') & 0x8000f)
{
	//表示对纹理的u方向或v方向设置纹理寻址模式
	Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
	Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); 
	//D3DTADDRESS_CLAMP、D3DTADDRESS_MIRROR
}

//set border color address mode
if (::GetAsyncKeyState('B') & 0x8000f)
{
	//表示对纹理的u方向或v方向设置纹理寻址模式
	Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
	Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
	Device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0x000000ff);
}

Textured Quad Routine

1. Construct the vertices that make up the object and specify texture coordinates for them.
2. Use the function D3DXCreateTextureFromFile to load a texture for the IDirect3DTexture9 interface.
3. Set the reduction/amplification filter and the multi-level progressive texture filter.
4. Before drawing the object, use the function IDirect3DDevice9::SetTexture to set the texture associated with the object

bool SetUpTextureQuad()
{
	Device->CreateVertexBuffer(6 * sizeof(TextureVertex), D3DUSAGE_WRITEONLY, TextureVertex::FVF, D3DPOOL_MANAGED, &Quad, 0);
	TextureVertex* v;
	Quad->Lock(0, 0, (void**)&v, 0);
	v[0] = TextureVertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f);
	v[1] = TextureVertex(-1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[2] = TextureVertex(1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f);

	v[3] = TextureVertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f);
	v[4] = TextureVertex(1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f);
	v[5] = TextureVertex(1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 3.0f);
	Quad->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, (float)Width / (float)Height, 1.0f, 1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);
	return true;
}

bool DisplayTextureQuad(float timeDelta)
{
	if (Device)
	{
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();
		Device->SetStreamSource(0, Quad, 0, sizeof(TextureVertex));
		Device->SetFVF(TextureVertex::FVF);
		Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);
		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}

Guess you like

Origin blog.csdn.net/SwordArcher/article/details/132803354