Direct3D中的纹理映射

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Spring_24/article/details/78189338

一、概要


          为了使渲染的图形看起来更真实,Direct3D提供了在物体表面绘制纹理的功能。一般来说,纹理是表示物体表面细节的一幅或几幅二维图形,也称纹理贴图。借助纹理映射技术,我们可将图像数据映射到三角形单元中,这种功能可以显著地增加所绘制场景的细节和真实感。

二、纹理坐标


           Direct3D所使用的纹理坐标系由沿水平方向的 u 轴和沿垂直方向的 v 轴构成。用坐标对(u , v)标识的纹理元素称为纹理元(texel)。注意,u 轴的正方向是水平向右的,v 轴的正方向是竖直向下的。如下图所示:

          

             还有一点要注意,为了能够处理不同尺度的纹理,Direct3D将纹理坐标做了规范化处理,使之限定在区间[0,1]内。

          虽然我们为一个3D三角形指定了相应的纹理三角形,但直到光栅化时,即该3D三角形已被变换至屏幕坐标系时,纹理映射才会进行。

三、创建并启用纹理


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

         HRESULT  D3DXCreateTextureFromFile(
                LPDIRECT3DDEVICE9   pDevice,
                LPCTSTR   pSrcFile,
                LPDIRECT3DTEXTURE9*   ppTexture
         );

         该函数可以加载下列格式的图像:BMP、DDS、DIB、JPG、PNG和TGA。

         为设置当前纹理,可以使用如下方法:

         HRESULT  IDirect3DDevice9::SetTexture(
            DWORD  Stage,
            IDirect3DBaseTexture9*  pTexture
          );

         在Direct3D中,最多可以设置8层纹理,可以对这些纹理进行组合以创建一副更细致的图像,这称为多重纹理。

         若想禁用某一纹理层,可将pTexture参数设置为0。

         如果场景中的各个三角形所使用的纹理均不同,可以按照如下的套路来做:

         Device->SetTexture(0, tex0);
         drawTrisUsingTex0();

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

四、纹理过滤器


          如前所述,纹理将被映射到屏幕空间中。通常,纹理三角形与屏幕三角形的大小并不一致。当纹理三角形比屏幕三角形小时,为适应后者,纹理三角形必须被放大(magnified)。当纹理三角形比屏幕三角形大时,为适应后者,纹理三角形必须被缩小(minified)。在上述两种情形下,都有畸变发生。为了从某种程度上克服这类畸变,Direct3D采用了一项称为纹理过滤(filtering)的技术。

         当使用纹理渲染物体时,屏幕上的每一个像素必须从物体的多边形表面获得相应的颜色值,这个过程称为纹理过滤

         Direct3D提供了3种类型的纹理过滤器(filter),每种过滤器都提供了一种质量水平(level of quality)。质量越高,运算开销越大。纹理过滤方式可以用方法IDirect3DDevice9->SetSampleState来设置。

        ●最近点采样(nearest point sampling)这是默认使用的过滤方式,该方式处理速度最快,但效果最差。Direct3D计算的纹理元素地址通常是一个浮点值,而非整数的纹理下标值,这时Direct3D会复制最接近的整数地址的纹理元素颜色。如果纹理的大小和屏幕图元的实际大小相近,那么采用最近点采样方法对图像的影响不大。但是,如果大小相差太多,就会降低图像精度从而影响图像质量,出现色块或者闪烁现象。

         下面的代码分别表示将最近点采样方式设置为放大过滤器和缩小过滤器:
          Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
          Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);

       线性纹理过滤(linear filtering)该类型的过滤方式可以产生相当好的结果,而且以目前的硬件配置水平,也可以获得较快的处理速度。线性纹理过滤取得计算得到的浮点地址最接近的上、下、左、右4个纹理元素,对这4个纹理元素进行加权平均,得到最终的颜色值。
     
        下面的代码分别表示将线性纹理过滤设置为放大过滤器和缩小过滤器:
          Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
          Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

       各向异性纹理过滤(anisotropic filtering)该类型的过滤方式可以产生最好的结果,但是处理速度也是最慢的。

        下面的代码分别表示将各向异性纹理过滤设置为放大过滤器和缩小过滤器:
          Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
          Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);

        使用各向异性纹理过滤时,必须对D3DSAMP_MAXANISOTROPIC水平进行设定,该值决定了各向异性过滤的质量水平。该值越大,图像效果越好。
       
       下面的代码将该值设为4:
         Device->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);

       ●多级渐进纹理过滤

         如前所述,屏幕上的三角形通常与纹理三角形大小不一致。为了尽量消除由二者尺寸差异所带来的影响,我们可以为纹理创建一个多级渐进纹理链(chain of mipmap)。方法是:由某一纹理创建一系列分辨率逐渐减小的纹理图像,并且对每种分辨率下的纹理所采用的过滤方式进行定制,以便保留那些较重要的细节。
 
         多级渐进纹理过滤由一组分辨率逐渐降低的纹理图形序列组成,每一级纹理的宽度和高度都是上一级纹理的宽度和高度的一半,Direct3D在纹理映射时自动选择大小最接近的纹理渲染。


          可以对多级渐进纹理进行如下设置:
 
          Device->SetSamplerState(0, D3DSAMP_MIPFILTER, Filter);

          其中,Filter可取以下值。
          ●D3DTEXF_NONE    禁用多级渐进纹理过滤器。
          ●D3DTEXF_POINT   通过使用该过滤器 ,Direct3D将选择尺寸与屏幕三角形最接近的那一级纹理。一旦选择了某一级纹理,Direct3D就会用指定的放大过滤器和缩小过滤器对该级纹理进行过滤。
          ●D3DTEXF_LINEAR  通过使用该过滤器,Direct3D将取与屏幕三角形最接近的两个纹理级,用指定的放大过滤器和缩小过滤器对每级纹理进行过滤,然后再将这两级纹理进行线性组合,从而形成最终的颜色值。

、寻址模式


           在前边我们说过纹理坐标必须限制在区间[0, 1]内。实际上,这是有问题的。因为有时坐标可能超出该范围。Direct3D定义了4种用来处理纹理坐标值超出[0, 1]区间的纹理映射模式。

       重复(wrap)寻址模式
         重复寻址模式在每个整数纹理坐标连接处自动重复纹理,这是默认的寻址模式。例如,矩形的4个顶点的纹理坐标分别定义为(0,0),(0,3),(3,0),(3,3),那么Direct3D就会在 u 方向和 v 方向各复制3遍原始纹理图。

        Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
        Device->SetSamplerState(0, D3DSAMP_ADDRESSV,  D3DTADDRESS_WRAP);

       镜像(mirror)寻址模式
         镜像寻址模式在每个整数纹理坐标连接处自动复制并翻转纹理。例如,矩形的4个顶点的纹理坐标分别定义为(0,0),(0,3),(3,0),(3,3),那么Direct3D就会在 u 方向和 v 方向各复制3遍并依次翻转原始纹理图。
     
        Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
        Device->SetSamplerState(0, D3DSAMP_ADDRESSV,  D3DTADDRESS_MIRROR);

      ●夹取(clamp)寻址模式
         夹取寻址模式将纹理坐标夹取在[0,1]范围中,它只映射一遍纹理,当纹理范围超出[0,1]时将纹理边缘的颜色延伸。

        Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
        Device->SetSamplerState(0, D3DSAMP_ADDRESSV,  D3DTADDRESS_CLAMP);

      ●边界颜色(border color)寻址模式
        当纹理范围超出[0,1]时,Direct3D以边框颜色代替纹理颜色。
      
        Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
        Device->SetSamplerState(0, D3DSAMP_ADDRESSV,  D3DTADDRESS_BORDER);

        同时可以设置边界颜色:

        Device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0xffff0000);

六、示例代码


    (一)寻址模式


          下面的代码演示不同的寻址模式之间的区别:

#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 )
#include <d3dx9math.h>

LPDIRECT3D9             g_pD3D = NULL; 
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; 
LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
LPDIRECT3DTEXTURE9  g_pTexture = NULL;

struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	FLOAT tu,tv;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)

HRESULT InitD3D(HWND hWnd)
{
	// Create the D3D object.
	if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
		return E_FAIL;

	// Set up the structure used to create the D3DDevice
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.EnableAutoDepthStencil = TRUE;
    	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	// Create the D3DDevice
	if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp, &g_pd3dDevice)))
	{
		return E_FAIL;
	}
	return S_OK;
}

HRESULT InitGeometry()
{
	if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,L"earth.jpg",&g_pTexture)))
	{
		return E_FAIL;
	}
	
	CUSTOMVERTEX vertices[] =
    {
		{  -10.0f, -10.0f, 0.0f,  -2,2},
		{  -10.0f, 10.0f, 0.0f, -2,0},
		{  10.0f, 10.0f, 0.0f, 2,0},
		{  10.0f, -10.0f, 0.0f, 2,2},
	};

	// Create the vertex buffer.
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(vertices)/sizeof(vertices[0]) * sizeof(CUSTOMVERTEX),
		0, D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT, &g_pVB, NULL)))
	{
		return E_FAIL;
	}

	// Fill the vertex buffer.
	VOID* pVertices;
	if (FAILED(g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, (void*)vertices, sizeof(vertices));
	g_pVB->Unlock();
	
	WORD indices[] = {0,1,2,0,2,3};

	if( FAILED( g_pd3dDevice->CreateIndexBuffer( sizeof(indices)/sizeof(indices[0]) * sizeof( WORD ),
                                                  0, D3DFMT_INDEX16,
                                                  D3DPOOL_DEFAULT, &g_pIB, NULL ) ) )
	{
		return E_FAIL;
	}

	VOID* pIndices = NULL;
	if(FAILED(g_pIB->Lock(0, sizeof(indices), (void**)&pIndices,0)))
		return E_FAIL;
	memcpy(pIndices,(VOID*)indices, sizeof(indices));
	g_pIB->Unlock();

	return S_OK;
}


VOID SetupMatrices()
{
	D3DXVECTOR3 vEyePt(0.0f, 0.0f, -50);
	D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);

	//D3DXMatrixPerspectiveFovLH()函数中的最远、最近距离为相对于视点的距离(即vEyePt中的距离)
	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1.0f, 1.0f, 200.0f);
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}

VOID Cleanup()
{
	if( g_pTexture != NULL )
        g_pTexture->Release();

	if (g_pVB != NULL)
		g_pVB->Release();

	if (g_pIB != NULL)
		g_pIB->Release();

	if (g_pd3dDevice != NULL)
		g_pd3dDevice->Release();

	if (g_pD3D != NULL)
		g_pD3D->Release();
}

VOID Render()
{
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);

	// Begin the scene
	if (SUCCEEDED(g_pd3dDevice->BeginScene()))
	{
		SetupMatrices();

		g_pd3dDevice->SetTexture( 0, g_pTexture );

		g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
		g_pd3dDevice->SetIndices(g_pIB);

		g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
		g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
		g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

		//左上
		D3DXMATRIX mat;
		D3DXMatrixTranslation(&mat, -11,11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);

		//右上
		D3DXMatrixTranslation(&mat, 11,11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);

		//左下
		D3DXMatrixTranslation(&mat, -11,-11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_BORDERCOLOR, D3DCOLOR_XRGB(255,0,255));
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);

		//右下
		D3DXMatrixTranslation(&mat, 11,-11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);
		g_pd3dDevice->EndScene();
	}

	// Present the backbuffer contents to the display
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}

LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY:
		Cleanup();
		PostQuitMessage(0);
		return 0;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT)
{
	UNREFERENCED_PARAMETER(hInst);

	// Register the window class
	WNDCLASSEX wc =
	{
		sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		L"D3D Tutorial", NULL
	};
	RegisterClassEx(&wc);

	// Create the application's window
	HWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D Tutorial 03: Texture",
		WS_OVERLAPPEDWINDOW, 100, 100, 700, 700,
		NULL, NULL, wc.hInstance, NULL);

	// Initialize Direct3D
	if (SUCCEEDED(InitD3D(hWnd)))
	{
		// Create the scene geometry
		if (SUCCEEDED(InitGeometry()))
		{
			// Show the window
			ShowWindow(hWnd, SW_SHOWDEFAULT);
			UpdateWindow(hWnd);

			// Enter the message loop
			MSG msg;
			ZeroMemory(&msg, sizeof(msg));
			while (msg.message != WM_QUIT)
			{
				if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
				{
					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}
				else
					Render();
			}
		}
	}

	UnregisterClass(L"D3D Tutorial", wc.hInstance);
	return 0;
}


     运行效果如下所示:

   

   

 (二)过滤器


      
         下面的代码演示不同过滤器所生成的图形:

       
#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 )
#include <d3dx9math.h>

LPDIRECT3D9             g_pD3D = NULL; 
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; 
LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;
LPDIRECT3DTEXTURE9  g_pTexture = NULL;

struct CUSTOMVERTEX
{
	FLOAT x, y, z;
	FLOAT tu,tv;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)

HRESULT InitD3D(HWND hWnd)
{
	// Create the D3D object.
	if (NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
		return E_FAIL;

	// Set up the structure used to create the D3DDevice
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.EnableAutoDepthStencil = TRUE;
    	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	// Create the D3DDevice
	if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp, &g_pd3dDevice)))
	{
		return E_FAIL;
	}
	return S_OK;
}

HRESULT InitGeometry()
{
	if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,L"earth.jpg",&g_pTexture)))
	{
		return E_FAIL;
	}
	
	CUSTOMVERTEX vertices[] =
    {
		{  -10.0f, -10.0f, 0.0f,  0,1},
		{  -10.0f, 10.0f, 0.0f, 0,0},
		{  10.0f, 10.0f, 0.0f, 1,0},
		{  10.0f, -10.0f, 0.0f, 1,1},
	};

	// Create the vertex buffer.
	if (FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(vertices)/sizeof(vertices[0]) * sizeof(CUSTOMVERTEX),
		0, D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT, &g_pVB, NULL)))
	{
		return E_FAIL;
	}

	// Fill the vertex buffer.
	VOID* pVertices;
	if (FAILED(g_pVB->Lock(0, sizeof(vertices), (void**)&pVertices, 0)))
		return E_FAIL;
	memcpy(pVertices, (void*)vertices, sizeof(vertices));
	g_pVB->Unlock();
	
	WORD indices[] = {0,1,2,0,2,3};

	if( FAILED( g_pd3dDevice->CreateIndexBuffer( sizeof(indices)/sizeof(indices[0]) * sizeof( WORD ),
                                                  0, D3DFMT_INDEX16,
                                                  D3DPOOL_DEFAULT, &g_pIB, NULL ) ) )
	{
		return E_FAIL;
	}

	VOID* pIndices = NULL;
	if(FAILED(g_pIB->Lock(0, sizeof(indices), (void**)&pIndices,0)))
		return E_FAIL;
	memcpy(pIndices,(VOID*)indices, sizeof(indices));
	g_pIB->Unlock();

	return S_OK;
}


VOID SetupMatrices()
{
	D3DXVECTOR3 vEyePt(0.0f, 0.0f, -50);
	D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);

	//D3DXMatrixPerspectiveFovLH()函数中的最远、最近距离为相对于视点的距离(即vEyePt中的距离)
	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1.0f, 1.0f, 200.0f);
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}

VOID Cleanup()
{
	if( g_pTexture != NULL )
        g_pTexture->Release();

	if (g_pVB != NULL)
		g_pVB->Release();

	if (g_pIB != NULL)
		g_pIB->Release();

	if (g_pd3dDevice != NULL)
		g_pd3dDevice->Release();

	if (g_pD3D != NULL)
		g_pD3D->Release();
}


VOID Render()
{
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);

	// Begin the scene
	if (SUCCEEDED(g_pd3dDevice->BeginScene()))
	{
		SetupMatrices();

		g_pd3dDevice->SetTexture( 0, g_pTexture );

		g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
		g_pd3dDevice->SetIndices(g_pIB);

		g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
		g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
		g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
		g_pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);

		//左上
		D3DXMATRIX mat;
		D3DXMatrixTranslation(&mat, -11,11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);

		//右上
		D3DXMatrixTranslation(&mat, 11,11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);

		//左下
		D3DXMatrixTranslation(&mat, -11,-11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);

		//右下
		D3DXMatrixTranslation(&mat, 11,-11,0);
		g_pd3dDevice->SetTransform(D3DTS_WORLD,&mat);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
		g_pd3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,4,0,2);

		g_pd3dDevice->EndScene();
	}

	// Present the backbuffer contents to the display
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}

LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_DESTROY:
		Cleanup();
		PostQuitMessage(0);
		return 0;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

INT WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, LPWSTR, INT)
{
	UNREFERENCED_PARAMETER(hInst);

	// Register the window class
	WNDCLASSEX wc =
	{
		sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		L"D3D Tutorial", NULL
	};
	RegisterClassEx(&wc);

	// Create the application's window
	HWND hWnd = CreateWindow(L"D3D Tutorial", L"D3D Tutorial 03: Texture",
		WS_OVERLAPPEDWINDOW, 100, 100, 700, 700,
		NULL, NULL, wc.hInstance, NULL);

	// Initialize Direct3D
	if (SUCCEEDED(InitD3D(hWnd)))
	{
		// Create the scene geometry
		if (SUCCEEDED(InitGeometry()))
		{
			// Show the window
			ShowWindow(hWnd, SW_SHOWDEFAULT);
			UpdateWindow(hWnd);

			// Enter the message loop
			MSG msg;
			ZeroMemory(&msg, sizeof(msg));
			while (msg.message != WM_QUIT)
			{
				if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
				{
					TranslateMessage(&msg);
					DispatchMessage(&msg);
				}
				else
					Render();
			}
		}
	}

	UnregisterClass(L"D3D Tutorial", wc.hInstance);
	return 0;
}

     运行效果如下:

 


猜你喜欢

转载自blog.csdn.net/Spring_24/article/details/78189338