techniqueapplication.cpp

来自「real-time(实时渲染技术DirectX)25-30(1)」· C++ 代码 · 共 634 行 · 第 1/2 页

CPP
634
字号
/***************************************************************
* 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 TEX_DIMENSION 1024

#define D3DFVF_MESHVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE)
#define D3DFVF_TESTVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)

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

struct TEST_VERTEX
{
	float x, y, z, rhw;
	float u, v;
};

CTechniqueApplication::CTechniqueApplication()
{
	m_pPlaneVertexBuffer       = NULL;
	m_pMeshVertexBuffer        = NULL;
	m_pTestVertexBuffer        = NULL;
	m_pMeshIndexBuffer         = NULL;
	m_pMesh                    = NULL;
	m_pMeshMaterials           = NULL;
	m_pShadowTexture           = NULL;
	m_pShadowTextureSurface    = NULL;
	m_pShadowZSurface          = NULL;
	m_pBackBuffer              = NULL;
	m_pZBuffer                 = NULL;
	m_NumMaterials             = 0;
	m_CompareShader            = 0;
	m_DistanceShader           = 0;
}

CTechniqueApplication::~CTechniqueApplication()
{
}

BOOL CTechniqueApplication::PostInitialize()
{	
	D3DCAPS8 Caps;
	m_pD3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &Caps);
	if (Caps.VertexShaderVersion == D3DVS_VERSION(1,1) && 
		Caps.PixelShaderVersion == D3DPS_VERSION(1,1))
	{
		if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_HAL, 
						  D3DCREATE_HARDWARE_VERTEXPROCESSING)))
			return FALSE;
	}
	else
	{
		if (FAILED(EasyCreateWindowed(m_hWnd, D3DDEVTYPE_REF, 
						  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();

	if (FAILED(CreatePlaneBuffers()))
		return FALSE;

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

	return TRUE;
}

void CTechniqueApplication::Render()
{
	//The light is moving side to side over the model.
	float Time = (float)GetTickCount() / 2000.0f;

	//These are reusable matrices
    D3DXMATRIX LightViewMatrix;
	D3DXMATRIX TextureMatrix;


	//Create the Texture Matrix
	float Offset = 0.5f + (0.5f / (float)TEX_DIMENSION);
	ZeroMemory(&TextureMatrix, sizeof(D3DXMATRIX));
    TextureMatrix._11 =  0.5f;
    TextureMatrix._22 = -0.5f;
    TextureMatrix._33 =  1.0f;
    TextureMatrix._41 =  Offset;
    TextureMatrix._42 =  Offset;
    TextureMatrix._44 =  1.0f;


	//Set the view parameters
	D3DXVECTOR4 EyePos(75.0, 75.0f, -75.0f, 0.0f);
	D3DXVECTOR4 LightPos(-25.0f * sin(Time) - 50.0f, 90.0f, 0.0f, 1.0f);

	//Set things up for the light
	D3DXMatrixLookAtLH(&LightViewMatrix, &(D3DXVECTOR3)LightPos,
		               &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
					   &D3DXVECTOR3(0.0f, 1.0f, 0.0f));

	//Assume the light is pointed toward the origin.
	D3DXVECTOR4 LightDir = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f) - LightPos;
	D3DXVec4Normalize(&LightDir, &LightDir);

	//Set the ambient light value.
	D3DXVECTOR4 Ambient    (0.1f,  0.1f, 0.1f, 0.0f);
	m_pD3DDevice->SetVertexShaderConstant(6, &Ambient, 1);

	//For this sample only - there is now world matrix transformation,
	//so there is no need to transform to object space.
	m_pD3DDevice->SetVertexShaderConstant(5, &LightDir, 1);


	//Set things up for the viewer
	D3DXMatrixLookAtLH(&m_ViewMatrix, &(D3DXVECTOR3)EyePos,
		               &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
					   &D3DXVECTOR3(0.0f, 1.0f, 0.0f));


	D3DXMATRIX LightShaderMatrix = m_WorldMatrix * 
		                           LightViewMatrix * 
								   m_ProjectionMatrix;

	D3DXMATRIX EyeShaderMatrix =   m_WorldMatrix * 
		                           m_ViewMatrix * 
								   m_ProjectionMatrix;

	D3DXMATRIX TextureShaderMatrix = m_WorldMatrix * LightViewMatrix * 
		                             m_ProjectionMatrix * TextureMatrix;

	D3DXMatrixTranspose(&LightShaderMatrix,   &LightShaderMatrix);
	D3DXMatrixTranspose(&EyeShaderMatrix,     &EyeShaderMatrix);
	D3DXMatrixTranspose(&TextureShaderMatrix, &TextureShaderMatrix);

	//Set the global distance scaling constants
	D3DXVECTOR4 DistanceScalers(100.0f, 0.025f, 0.0f, 1.0f);
	m_pD3DDevice->SetVertexShaderConstant(4, &DistanceScalers, 1);

	//The texture should be null for all distance operations
	m_pD3DDevice->SetTexture(0, NULL);

	//First, render the light's point of view into the render target.
	m_pD3DDevice->SetVertexShader(m_DistanceShader);


	D3DVIEWPORT8 NormalViewport;
	m_pD3DDevice->GetViewport(&NormalViewport);

	//Set up the renderTarget
	m_pD3DDevice->SetRenderTarget(m_pShadowTextureSurface, m_pShadowZSurface);

	D3DVIEWPORT8 ShadowViewport;
	ShadowViewport.X = 0;
	ShadowViewport.Y = 0;
	ShadowViewport.Width  = TEX_DIMENSION;
	ShadowViewport.Height = TEX_DIMENSION;
	ShadowViewport.MinZ = 0.0f;
	ShadowViewport.MaxZ = 1.0f;
	m_pD3DDevice->SetViewport(&ShadowViewport);

	m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 
		                D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0);

	//Draw the plane and the mesh using the light view matrix
	m_pD3DDevice->SetVertexShaderConstant(0, &LightShaderMatrix, 4);
	RenderPlane();

	//Draw the mesh
	m_pD3DDevice->SetStreamSource(0, m_pMeshVertexBuffer, sizeof(MESH_VERTEX));
	m_pD3DDevice->SetIndices(m_pMeshIndexBuffer, 0);
	m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 
    								   m_pMesh->GetNumVertices(), 0,
									   m_pMesh->GetNumFaces());


	//Set the renderTarget back to the normal back buffer
	m_pD3DDevice->SetRenderTarget(m_pBackBuffer, m_pZBuffer);

	m_pD3DDevice->SetViewport(&NormalViewport);

	//Use the compare shader
	m_pD3DDevice->SetVertexShader(m_CompareShader);

	//Set the pixel shader
	m_pD3DDevice->SetPixelShader(m_PixelShader);

	//Set the texture states to clamp the coordinates
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);

	//Render everything from the eye's point of view - use the first
	//rendering as a texture.
	m_pD3DDevice->SetTexture(0, m_pShadowTexture);

	m_pD3DDevice->SetVertexShaderConstant(0,  &EyeShaderMatrix, 4);
	m_pD3DDevice->SetVertexShaderConstant(10, &LightShaderMatrix, 4);
	m_pD3DDevice->SetVertexShaderConstant(20, &TextureShaderMatrix, 4);

	RenderPlane();

	m_pD3DDevice->SetStreamSource(0, m_pMeshVertexBuffer, sizeof(MESH_VERTEX));
	m_pD3DDevice->SetIndices(m_pMeshIndexBuffer, 0);
	m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 
    								   m_pMesh->GetNumVertices(), 0,
									   m_pMesh->GetNumFaces());

	//Turn off the pixel shader
	m_pD3DDevice->SetPixelShader(NULL);

	//Draw a small rectangle showing the light's view (for debugging)..
	m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
	m_pD3DDevice->SetVertexShader(D3DFVF_TESTVERTEX);
	m_pD3DDevice->SetStreamSource(0, m_pTestVertexBuffer, sizeof(TEST_VERTEX));
	m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
	m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
	m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
}

HRESULT CTechniqueApplication::LoadMesh()
{
	LPD3DXBUFFER pD3DXMtrlBuffer;
	LPD3DXMESH   pOriginalMesh;

    //Load and initialize the mesh. This is a repeat of the code
	//from Chapter 10.
	if(FAILED(D3DXLoadMeshFromX("..\\media\\fattorus.x",
								D3DXMESH_MANAGED, 
                                m_pD3DDevice, NULL, &pD3DXMtrlBuffer,
								&m_NumMaterials, &pOriginalMesh)))
        return FALSE;

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

    m_pMeshMaterials = new D3DMATERIAL8[m_NumMaterials];

    for(long MatCount = 0; MatCount < m_NumMaterials; MatCount++)
		m_pMeshMaterials[MatCount] = d3dxMaterials[MatCount].MatD3D;

    pD3DXMtrlBuffer->Release();

	//This is new. If the FVF doesn't match, clone the mesh and
	//create one that does. Then, release the loaded mesh. If the 
	//FVF does match, set the member mesh and move on.
	if (pOriginalMesh->GetFVF() != D3DFVF_MESHVERTEX)
	{
		pOriginalMesh->CloneMeshFVF(D3DXMESH_MANAGED,
									D3DFVF_MESHVERTEX,
                                    m_pD3DDevice, &m_pMesh);
		
		pOriginalMesh->Release();
		pOriginalMesh = NULL;
	}
	else
		m_pMesh = pOriginalMesh;

	return S_OK;
}

BOOL CTechniqueApplication::PreReset()
{
	//Delete the shaders
	m_pD3DDevice->DeleteVertexShader(m_CompareShader);
	m_pD3DDevice->DeleteVertexShader(m_DistanceShader);
	m_pD3DDevice->DeletePixelShader(m_PixelShader);

	//Get rid of all the render target objects
	CleanUpTarget();

	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_CompareShader);
	m_pD3DDevice->DeleteVertexShader(m_DistanceShader);
	m_pD3DDevice->DeletePixelShader(m_PixelShader);

	//Get rid of all the render target objects
	CleanUpTarget();

⌨️ 快捷键说明

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