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

📄 techniqueapplication.cpp

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

#include "TechniqueApplication.h"

#define D3DFVF_MESHVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE)

struct MESH_VERTEX
{
	float x, y, z;
	float nx, ny, nz;
	DWORD color;
};

CTechniqueApplication::CTechniqueApplication()
{
	m_pRingVertexBuffer        = NULL;
	m_pRingIndexBuffer         = NULL;
	m_pRing                    = NULL;
	m_pBoxVertexBuffer         = NULL;
	m_pBoxIndexBuffer          = NULL;
	m_pBox                     = NULL;
	m_pRingMaterials           = NULL;
	m_pBoxMaterials            = NULL;
	m_NumRingMaterials         = 0;
	m_NumBoxMaterials          = 0;
	m_XRayShader               = 0;
	m_LightingShader           = 0;
}

CTechniqueApplication::~CTechniqueApplication()
{
}

BOOL CTechniqueApplication::PostInitialize()
{	
	D3DCAPS8 Caps;
	m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &Caps);
	if (Caps.VertexShaderVersion == D3DVS_VERSION(1,1))
	{
		if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_HAL, 
						  D3DCREATE_HARDWARE_VERTEXPROCESSING)))
			return FALSE;
	}
	else
	{
		if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_HAL, 
						  D3DCREATE_SOFTWARE_VERTEXPROCESSING)))
			return FALSE;
	}

	//Do the basic camera positioning, etc.
	SetupDevice();
	
	//Load the mesh object
	LoadMesh();

	//Create the buffers we're actually going to use
	ExtractBuffers();

	//Create the shader
	if (FAILED(CreateShaders()))
		return FALSE;

	return TRUE;
}

void CTechniqueApplication::Render()
{		
	D3DXVECTOR4 EyePos(0.0, 5.0f, -30.0f, 0.0f);
	//Set the view matrix based on the position above.
	float EyeScan = 5.0f * sin((float)GetTickCount() / 1000.0f);
	D3DXMatrixLookAtLH(&m_ViewMatrix, &(D3DXVECTOR3)EyePos,
		               &D3DXVECTOR3(EyeScan, 5.0f, 0.0f),
					   &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

	//Create the concatenated transformation matrix
	D3DXMATRIX ShaderMatrix = m_WorldMatrix * 
		                      m_ViewMatrix * 
							  m_ProjectionMatrix;

	//Get the transpose
	D3DXMatrixTranspose(&ShaderMatrix, &ShaderMatrix);

	//Pass the transposed matrix to the shader
	m_pD3DDevice->SetVertexShaderConstant(0, &ShaderMatrix, 4);

	//These are all the constants for all the lights and the xray glasses
	D3DXVECTOR4 LightDir(0.0, -1.0f, 0.0f, 0.0f);
	D3DXVECTOR4 LightColor(1.0, 1.0f, 1.0f, 1.0f);
	D3DXVECTOR4 Specular(1.0, 1.0f, 1.0f, 100.0f);
	D3DXVECTOR4 Ambient(0.1f, 0.1f, 0.1f, 1.0f);
	D3DXVECTOR4 XRayParams(1.0f, 127.0f, 1.0, 1.0f);
	D3DXMATRIX InverseWorld;

	//Transform the light position and direction to object space
	D3DXMatrixInverse(&InverseWorld, NULL, &m_WorldMatrix);
	D3DXVec4Transform(&LightDir, &LightDir, &InverseWorld);

	D3DXVECTOR4 EyeDir;
	D3DXVec4Normalize(&EyeDir,   &D3DXVECTOR4(m_ViewMatrix._13, 
		                                      m_ViewMatrix._23, 
									          m_ViewMatrix._33, 
									          0.0f));


	//Transform the eye position to object space.
	D3DXVec4Transform(&EyePos, &EyePos, &InverseWorld);
	D3DXVec4Transform(&EyeDir, &EyeDir, &InverseWorld);
	D3DXVec4Normalize(&EyeDir, &EyeDir);

	//Set the constants...
	m_pD3DDevice->SetVertexShaderConstant(5, &LightDir, 1);
	m_pD3DDevice->SetVertexShaderConstant(6, &EyePos, 1);
	m_pD3DDevice->SetVertexShaderConstant(7, &Specular, 1);
	m_pD3DDevice->SetVertexShaderConstant(8, &LightColor, 1);
	m_pD3DDevice->SetVertexShaderConstant(9, &Ambient, 1);
	m_pD3DDevice->SetVertexShaderConstant(10, &EyeDir, 1);
	m_pD3DDevice->SetVertexShaderConstant(11, &XRayParams, 1);

	//Set the lighting shader and draw the ring.
	m_pD3DDevice->SetVertexShader(m_LightingShader);
	
	m_pD3DDevice->SetStreamSource(0, m_pRingVertexBuffer, sizeof(MESH_VERTEX));
	m_pD3DDevice->SetIndices(m_pRingIndexBuffer, 0);

	m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 
									   m_pRing->GetNumVertices(), 0,
									   m_pRing->GetNumFaces());


	//m_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

	//Now, draw the box with the XRay shader
	m_pD3DDevice->SetVertexShader(m_XRayShader);

	m_pD3DDevice->SetStreamSource(0, m_pBoxVertexBuffer, sizeof(MESH_VERTEX));
	m_pD3DDevice->SetIndices(m_pBoxIndexBuffer, 0);

	m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 
									   m_pBox->GetNumVertices(), 0,
									   m_pBox->GetNumFaces());

	m_pD3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
}

HRESULT CTechniqueApplication::LoadMesh()
{
	//This function is basically the same as many of the chapters,
	//only this time it's loading two meshes.
	LPD3DXBUFFER pD3DXMtrlBuffer;
	LPD3DXMESH   pOriginalMesh;

	if(FAILED(D3DXLoadMeshFromX("..\\media\\Ring.x",
								D3DXMESH_MANAGED, 
                                m_pD3DDevice, NULL, &pD3DXMtrlBuffer,
								&m_NumRingMaterials, &pOriginalMesh)))
        return FALSE;

	D3DXMATERIAL* d3dxMaterials = 
		(D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();

    m_pRingMaterials = new D3DMATERIAL8[m_NumRingMaterials];

    for(long MatCount = 0; MatCount < m_NumRingMaterials; MatCount++)
		m_pRingMaterials[MatCount] = d3dxMaterials[MatCount].MatD3D;

    pD3DXMtrlBuffer->Release();

	if (pOriginalMesh->GetFVF() != D3DFVF_MESHVERTEX)
	{
		pOriginalMesh->CloneMeshFVF(D3DXMESH_MANAGED,
									D3DFVF_MESHVERTEX,
                                    m_pD3DDevice, &m_pRing);
		
		pOriginalMesh->Release();
		pOriginalMesh = NULL;
	}
	else
		m_pRing = pOriginalMesh;

	if(FAILED(D3DXLoadMeshFromX("..\\media\\Box.x",
								D3DXMESH_MANAGED, 
                                m_pD3DDevice, NULL, &pD3DXMtrlBuffer,
								&m_NumBoxMaterials, &pOriginalMesh)))
        return FALSE;

	d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();

    m_pBoxMaterials = new D3DMATERIAL8[m_NumBoxMaterials];

    for(MatCount = 0; MatCount < m_NumBoxMaterials; MatCount++)
		m_pBoxMaterials[MatCount] = d3dxMaterials[MatCount].MatD3D;

    pD3DXMtrlBuffer->Release();

	if (pOriginalMesh->GetFVF() != D3DFVF_MESHVERTEX)
	{
		pOriginalMesh->CloneMeshFVF(D3DXMESH_MANAGED,
									D3DFVF_MESHVERTEX,
                                    m_pD3DDevice, &m_pBox);
		
		pOriginalMesh->Release();
		pOriginalMesh = NULL;
	}
	else
		m_pBox = pOriginalMesh;

	return S_OK;
}

BOOL CTechniqueApplication::PreReset()
{
	//Delete the shaders
	m_pD3DDevice->DeleteVertexShader(m_XRayShader);
	m_pD3DDevice->DeleteVertexShader(m_LightingShader);

	return TRUE;
}

BOOL CTechniqueApplication::PostReset()
{
	SetupDevice();

	//Recreate the shader
	if (FAILED(CreateShaders()))
		return FALSE;

	return TRUE;
}


BOOL CTechniqueApplication::PreTerminate()
{
	//Delete the shaders
	m_pD3DDevice->DeleteVertexShader(m_XRayShader);
	m_pD3DDevice->DeleteVertexShader(m_LightingShader);
	
	//Clean up
	if (m_pRingVertexBuffer)
	{
		m_pRingVertexBuffer->Release();
		m_pRingVertexBuffer = NULL;
	}

	if (m_pRingIndexBuffer)
	{
		m_pRingIndexBuffer->Release();
		m_pRingIndexBuffer  = NULL;
	}

	if (m_pRing)
	{
		m_pRing->Release();
		m_pRing = NULL;
	}

	if (m_pBoxVertexBuffer)
	{
		m_pBoxVertexBuffer->Release();
		m_pBoxVertexBuffer = NULL;
	}

	if (m_pBoxIndexBuffer)
	{
		m_pBoxIndexBuffer->Release();
		m_pBoxIndexBuffer  = NULL;
	}

	if (m_pBox)
	{
		m_pBox->Release();
		m_pBox = NULL;
	}

	if (m_pRingMaterials)
	{
		delete m_pRingMaterials;
		m_pRingMaterials = NULL;
	}

	if (m_pBoxMaterials)
	{
		delete m_pBoxMaterials;
		m_pBoxMaterials = NULL;
	}

	return TRUE;
}


void CTechniqueApplication::SetupDevice()
{
	//Do all the basic setup
	RECT WindowRect;
	GetClientRect(m_hWnd, &WindowRect);
	D3DXMatrixPerspectiveFovLH(&m_ProjectionMatrix,
					D3DX_PI / 4,
					(float)(WindowRect.right - WindowRect.left) / 
					(float)(WindowRect.bottom - WindowRect.top),
				    1.0f, 1000.0f);

	D3DXMatrixIdentity(&m_WorldMatrix);

	m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

	m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
}

HRESULT CTechniqueApplication::ExtractBuffers()
{
	//Get the buffers
	m_pRing->GetVertexBuffer(&m_pRingVertexBuffer);
	m_pRing->GetIndexBuffer(&m_pRingIndexBuffer);
	m_pBox->GetVertexBuffer(&m_pBoxVertexBuffer);
	m_pBox->GetIndexBuffer(&m_pBoxIndexBuffer);

	MESH_VERTEX *pMeshVertices;
	short       *pIndices;
	DWORD       *pAttribs;

	//Lock the vertex buffer, but allow writing.
	m_pRingVertexBuffer->Lock(0, m_pRing->GetNumVertices() * sizeof(MESH_VERTEX),
		                      (BYTE **)&pMeshVertices, 0);


	//We only need to read the indices
	m_pRingIndexBuffer->Lock(0, 3 * m_pRing->GetNumFaces() * sizeof(short),
	                         (BYTE **)&pIndices, D3DLOCK_READONLY);

	//The attribute buffer maps the materials to each face.
	m_pRing->LockAttributeBuffer(D3DLOCK_READONLY, &pAttribs);

	//Loop through each face and set the vertex color based on the material.
	//This is a pretty simple example, but you could also use this to preload
	//other data, such as converting colors to data that the vertex shader
	//may use in computations.
	for (long Face = 0; Face < m_pRing->GetNumFaces(); Face++)
	{
		D3DXCOLOR Diffuse = (D3DXCOLOR)m_pRingMaterials[pAttribs[Face]].Diffuse;

		pMeshVertices[pIndices[Face * 3 + 0]].color = Diffuse;
		pMeshVertices[pIndices[Face * 3 + 1]].color = Diffuse;
		pMeshVertices[pIndices[Face * 3 + 2]].color = Diffuse;
	}

	//Give back all of our buffers.
	m_pRingVertexBuffer->Unlock();
	m_pRingIndexBuffer->Unlock();
	m_pRing->UnlockAttributeBuffer();


	//Repeat the above procedure for the box
	m_pBoxVertexBuffer->Lock(0, m_pBox->GetNumVertices() * sizeof(MESH_VERTEX),
		                     (BYTE **)&pMeshVertices, 0);

	m_pBoxIndexBuffer->Lock(0, 3 * m_pBox->GetNumFaces() * sizeof(short),
	                         (BYTE **)&pIndices, D3DLOCK_READONLY);
	m_pBox->LockAttributeBuffer(D3DLOCK_READONLY, &pAttribs);

	for (Face = 0; Face < m_pBox->GetNumFaces(); Face++)
	{
		D3DXCOLOR Diffuse = (D3DXCOLOR)m_pBoxMaterials[pAttribs[Face]].Diffuse;

		pMeshVertices[pIndices[Face * 3 + 0]].color = Diffuse;
		pMeshVertices[pIndices[Face * 3 + 1]].color = Diffuse;
		pMeshVertices[pIndices[Face * 3 + 2]].color = Diffuse;
	}

	m_pBoxVertexBuffer->Unlock();
	m_pBoxIndexBuffer->Unlock();
	m_pBox->UnlockAttributeBuffer();

	return S_OK;
}

HRESULT CTechniqueApplication::CreateShaders()
{
	//Set up the declaration to match the FVF and to
	//read from stream zero.
	DWORD Declaration[] =
	{
		D3DVSD_STREAM(0),
		D3DVSD_REG(D3DVSDE_POSITION,D3DVSDT_FLOAT3),
		D3DVSD_REG(D3DVSDE_NORMAL,  D3DVSDT_FLOAT3),
		D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR),
		D3DVSD_END()
	};

	
	ID3DXBuffer* pShaderBuffer;
	ID3DXBuffer* pShaderErrors;

	//Assemble and create the first shader. Under real circumstances, you would 
	//probably want to do more error handling.
	if (FAILED(D3DXAssembleShaderFromFile("..\\media\\Shaders\\XRayGlasses.vsh", 
		                            0, NULL, &pShaderBuffer, &pShaderErrors)))
		return E_FAIL;

	if (FAILED(m_pD3DDevice->CreateVertexShader(Declaration, 
		                           (DWORD *)pShaderBuffer->GetBufferPointer(),
								   &m_XRayShader, 0)))
		return E_FAIL;

	//release the working buffers
	pShaderBuffer->Release();

	if (FAILED(D3DXAssembleShaderFromFile("..\\media\\Shaders\\DirLights.vsh", 
		                            0, NULL, &pShaderBuffer, &pShaderErrors)))
		return E_FAIL;

	if (FAILED(m_pD3DDevice->CreateVertexShader(Declaration, 
		                           (DWORD *)pShaderBuffer->GetBufferPointer(),
								   &m_LightingShader, 0)))
		return E_FAIL;

	//release the working buffers
	pShaderBuffer->Release();

	return S_OK;
}

⌨️ 快捷键说明

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