• 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

    );

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

    四.过滤器

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

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

    1.Nearest point sampling

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

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

    2.Linear filtering

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

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

    3.Anisotropic filtering

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

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

    4.Mipmaps过滤器

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

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

    五.寻址模式

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

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

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

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

    2.边框颜色纹理寻址模式(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);
    }
    

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

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

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

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

    六.例子

    1.不过滤纹理

    #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.过滤处理纹理

    #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;
    }
    
  • 相关阅读:
    OpenStack开发基础-oslo.config
    对象的封装
    Oracle动态显示日志
    Marching squares &amp; Marching cubes
    Keil5.15使用GCC编译器链接.a库文件
    数据结构习题之树
    HDU 5358(2015多校联合训练赛第六场1006) First One (区间合并+常数优化)
    使用URL在线语音合成
    企业怎样高速搭建大数据处理系统
    http://blog.sina.com.cn/s/blog_7caae74b0100zl17.html
  • 原文地址:https://www.cnblogs.com/k5bg/p/11126843.html
Copyright © 2020-2023  润新知