⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textureapplication.cpp

📁 real-time(实时渲染技术DirectX)6-12
💻 CPP
字号:
/***************************************************************
* TextureApplication.cpp                                       *
*                                                              *
* This file contains the implementation of the                 *
* CTextureApplication class.								   *
* To compile correctly, this file must be linked with:         *
* kernel32.lib                                                 *
* user32.lib                                                   *
* d3dx8dt.lib                                                  *
* d3d8.lib                                                     *
* gdi32.lib                                                    *
* advapi32.lib                                                 *
*                                                              *
***************************************************************/

#include "TextureApplication.h"

#define D3DFVF_TEXTUREVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)

struct TEXTURE_VERTEX
{
	float x, y, z;
	float u, v;
};

CTextureApplication::CTextureApplication()
{
	//Initialize everything
	m_pVertexBuffer   = NULL;
	m_pCheckerTexture = NULL;
	m_pMipMapTexture  = NULL;
	m_pImageTexture   = NULL;
}

CTextureApplication::~CTextureApplication()
{
	DestroyGeometry();
}

BOOL CTextureApplication::PostInitialize()
{
	if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_HAL, 
					  D3DCREATE_HARDWARE_VERTEXPROCESSING)))
		return FALSE;

	SetupDevice();

	if (!CreateGeometry())
		return FALSE;
	
	//All of our textures are in managed memory, so no need to 
	//initialize them more than once.
	if (!CreateCustomTextures())
		return FALSE;

	if (FAILED(D3DXCreateTextureFromFile(m_pD3DDevice, 
		                                 "..\\media\\light.bmp", 
										 &m_pImageTexture)))
		return FALSE;

	return TRUE;
}

void CTextureApplication::SetupDevice()
{
	D3DXMatrixIdentity(&m_ViewMatrix);
	m_pD3DDevice->SetTransform(D3DTS_VIEW, &m_ViewMatrix);

	RECT WindowRect;
	GetClientRect(m_hWnd, &WindowRect);
	D3DXMatrixPerspectiveFovLH(&m_ProjectionMatrix,
					D3DX_PI / 4,
					(float)(WindowRect.right - WindowRect.left) / 
					(float)(WindowRect.bottom - WindowRect.top),
				    1.0f, 100.0f);
	m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &m_ProjectionMatrix);

	m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

	//This tells the device to use the texture matrix on 2D coordinates
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 
		                               D3DTTFF_COUNT2);

	m_pD3DDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
}

BOOL CTextureApplication::PreReset()
{
	DestroyGeometry();
	return TRUE;
}

BOOL CTextureApplication::PostReset()
{
	SetupDevice();
	return CreateGeometry();
}

BOOL CTextureApplication::PreTerminate()
{
	DestroyGeometry();

	//Make sure a texture is not in use
	m_pD3DDevice->SetTexture(0, NULL);

	if (m_pCheckerTexture)
		m_pCheckerTexture->Release();

	if (m_pMipMapTexture)
		m_pMipMapTexture->Release();

	if (m_pImageTexture)
		m_pImageTexture->Release();

	return TRUE;
}

BOOL CTextureApplication::CreateGeometry()
{
	//Same old drill...  Create, lock, fill unlock.
	if (FAILED(m_pD3DDevice->CreateVertexBuffer(4 * sizeof(TEXTURE_VERTEX),
										        D3DUSAGE_WRITEONLY,
										        D3DFVF_TEXTUREVERTEX,
										        D3DPOOL_DEFAULT,
										        &m_pVertexBuffer)))
		return FALSE;

	TEXTURE_VERTEX *pVertices;

	if (FAILED(m_pVertexBuffer->Lock(0, 4 * sizeof(TEXTURE_VERTEX),
					                 (BYTE **)&pVertices,
					                 0)))
	{
		DestroyGeometry();
		return FALSE;
	}

	//we are creating a simple square that will be rendered with a 
	//triangle strip. First set their position.
	pVertices[0].x = -1.0f; pVertices[0].y =  1.0f; pVertices[0].z = 10.0f;
	pVertices[1].x =  1.0f; pVertices[1].y =  1.0f; pVertices[1].z = 10.0f;
	pVertices[2].x = -1.0f; pVertices[2].y = -1.0f; pVertices[2].z = 10.0f;
	pVertices[3].x =  1.0f; pVertices[3].y = -1.0f; pVertices[3].z = 10.0f;

	//Now set the texture coordinates. We'll set them to cover the full
	//texture and use the texture matrix to scale them.
	pVertices[0].u = 0.0f; pVertices[0].v = 0.0f;
	pVertices[1].u = 1.0f; pVertices[1].v = 0.0f;
	pVertices[2].u = 0.0f; pVertices[2].v = 1.0f;
	pVertices[3].u = 1.0f; pVertices[3].v = 1.0f;

	m_pVertexBuffer->Unlock();

	//Since we are not going to use another source...
	m_pD3DDevice->SetStreamSource(0, m_pVertexBuffer, sizeof(TEXTURE_VERTEX));
	m_pD3DDevice->SetVertexShader(D3DFVF_TEXTUREVERTEX);

	return TRUE;
}

void CTextureApplication::DestroyGeometry()
{
	if (m_pVertexBuffer)
	{
		m_pVertexBuffer->Release();
		m_pVertexBuffer = NULL;
	}
}

void CTextureApplication::PreRender()
{
	//We have overridden PreRender so that we can change the clear color,
	//but make sure you call BeginScene!!!!
		//Clear the device
	m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
						D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);

	//Call BeginScene to set up the device
	m_pD3DDevice->BeginScene();

}

void CTextureApplication::Render()
{
	//This is our matrix for texture transformations
	D3DXMATRIX TextureMatrix;
	//Set the texture transform back to the identity matrix
	D3DXMatrixIdentity(&TextureMatrix);
	m_pD3DDevice->SetTransform(D3DTS_TEXTURE0, &TextureMatrix);

	m_pD3DDevice->SetTexture(0, m_pCheckerTexture);
	
	//The first square shows the checkerboard pattern as it 
	//actually appears in memory.
	D3DXMatrixTranslation(&m_WorldMatrix, -2.0f, 2.0f, 0.0f);
	m_pD3DDevice->SetTransform(D3DTS_WORLD, &m_WorldMatrix);
	m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	//The second square shows how the texture can be repeated
	//to turn a simple texture into a more useful one. Scaling
	//the texture matrix by 8.0 has the same effect as setting
	//the maximum texture coordinates to (8.0, 8.0) if we had 
	//set them directly in the vertices.
	D3DXMatrixScaling(&TextureMatrix, 8.0f, 8.0f, 1.0f);
	m_pD3DDevice->SetTransform(D3DTS_TEXTURE0, &TextureMatrix);

	D3DXMatrixTranslation(&m_WorldMatrix, 2.0f, 2.0f, 0.0f);
	m_pD3DDevice->SetTransform(D3DTS_WORLD, &m_WorldMatrix);
	m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);


	//Set up a scaling factor for the texture matrix. This is
	//just an easy way to experiment with new texture coordinates
	//without changing vertex data.
	float ScaleFactor = (cos((float)GetTickCount() / 1000.0f) + 1.0) * 10.0f;
	D3DXMatrixScaling(&TextureMatrix, ScaleFactor, ScaleFactor, 1.0f);
	m_pD3DDevice->SetTransform(D3DTS_TEXTURE0, &TextureMatrix);

	//We are setting the texture coordinates to force the device to use 
	//different mipmap levels. On the left we show an image that was
	//loaded from a bitmap file with mipmaps automatically generated.
	//On the left, it's easier to explicitly see the individual levels
	//because the colors correspond to the size of the mipmap.

	//use the image texture
	m_pD3DDevice->SetTexture(0, m_pImageTexture);
	D3DXMatrixTranslation(&m_WorldMatrix, -2.0f, -2.0f, 0.0f);
	m_pD3DDevice->SetTransform(D3DTS_WORLD, &m_WorldMatrix);
	m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	//Use the mip map texture
	m_pD3DDevice->SetTexture(0, m_pMipMapTexture);
	D3DXMatrixTranslation(&m_WorldMatrix, 2.0f, -2.0f, 0.0f);
	m_pD3DDevice->SetTransform(D3DTS_WORLD, &m_WorldMatrix);
	m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}

BOOL CTextureApplication::CreateCustomTextures()
{
	//These are some working variables we'll use for various operations
	LPDIRECT3DSURFACE8 pWorkSurface;
	D3DLOCKED_RECT     WorkRect;

	//Create the simple checkerboard texture. This is a simple 2x2
	//texture. We will request a full 32bit texture
	//in managed memory. 32bit is overkill for this, but I'm using it
	//for consistency.
	if (FAILED(m_pD3DDevice->CreateTexture(2, 2, 0, 0, 
		                                   D3DFMT_A8R8G8B8,
										   D3DPOOL_MANAGED,
										   &m_pCheckerTexture)))
		return FALSE;

	//Set the checker pattern. First get the surface and lock the 
	//whole rectangle.
	m_pCheckerTexture->GetSurfaceLevel(0, &pWorkSurface);
	pWorkSurface->LockRect(&WorkRect, NULL, 0);

	//set the first 4 bytes to 0xff (white) and 
	//the second 4 bytes to 0x00 (black), then increment by the pitch
	//and so the reverse for the second row. In most cases, the pitch
	//will probably be 8, but that's not guaranteed.
	memset((BYTE *)WorkRect.pBits, 0xff, 4);
	memset((BYTE *)WorkRect.pBits + 4, 0x00, 4);
	memset((BYTE *)WorkRect.pBits + WorkRect.Pitch, 0x00, 4);
	memset((BYTE *)WorkRect.pBits + WorkRect.Pitch + 4, 0xff, 4);

	//Now unlock the rect and release the surface.
	pWorkSurface->UnlockRect();
	pWorkSurface->Release();


	//The mipmap texture is created to show off mipmaps in a very
	//obvious way. Assuming the texture is created successfully, we
	//will run through each surface and set all the bits in each surface
	//to descending levels of gray. Not particularly interesting, but
	//to shows how and when different levels are being used.
	if (FAILED(m_pD3DDevice->CreateTexture(256, 256, 0, 0, 
		                                   D3DFMT_A8R8G8B8,
										   D3DPOOL_MANAGED,
										   &m_pMipMapTexture)))
		return FALSE;

	//Loop through the levels and set each one to a gray color. This time, 
	//we do things a little differently. We call LockRect directly on the
	//texture, which has the same effect as above without all the steps.
	//We don't have direct access to the surface object, 
	//but we don't need it...
	for (long Level = 0; Level < m_pMipMapTexture->GetLevelCount(); Level++)
	{
		//Get the level description so that we know how many bytes to set.
		D3DSURFACE_DESC LevelDescription;
		m_pMipMapTexture->GetLevelDesc(Level, &LevelDescription);

		//use the width of the level to define the color
		BYTE Color = (BYTE)LevelDescription.Width - 1;

		m_pMipMapTexture->LockRect(Level, &WorkRect, NULL, 0);

		//Because we are using a 256x256 texture, in most cases, we can assume
		//that the pitch is simply 4 * our width, but it's not a guarantee.
		//To show the good practice way, here we are filling in each row, but
		//only the number of bytes that we know are valid pixels and not
		//in the cache.
		for (long Row = 0; Row < LevelDescription.Height; Row++)
		{
			memset((BYTE *)WorkRect.pBits + (Row * WorkRect.Pitch), Color,
			       LevelDescription.Width * 4);
		}

		m_pMipMapTexture->UnlockRect(Level);
	}

	return TRUE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -