首页 > 代码库 > 游戏框架其九:网和着色器( Mesh and Shader )

游戏框架其九:网和着色器( Mesh and Shader )

网的重要作用可以导入3DMAX等创建的模型,到游戏中;着色器可以实现特定绚丽的效果。它们的实现如下

1. 网 Mesh的实现:

#pragma once
//========================================================================
// File: Mesh.h - classes to render meshes in D3D9 and D3D11
// 主要是导入3DMAX等软件生成的模型文件 基于Windows Direct3D9 和 Direct3D11
//========================================================================


#include <SDKMesh.h>
#include "Geometry.h"
#include "ResCache.h"

#define GCC_NEW new
#if !defined(SAFE_RELEASE)
#define SAFE_RELEASE(x) if(x) x->Release(); x=NULL;
#endif
//BaseRenderComponent defined in Actors folder
typedef BaseRenderComponent* WeakBaseRenderComponentPtr;
typedef unsigned int  ActorId;
typedef unsigned int  GameViewId;
typedef D3DXCOLOR     Color;
typedef unsigned int  DWORD;
typedef unsigned char BYTE;
typedef float         FLOAT;
typedef unsigned int  UINT;
#ifdef   UNICODE
typedef wchar_t       TCHAR;
#else
typedef unsigned char TCHAR;
#endif
typedef unsigned char CHAR;
typedef unsigned wchar_t WCHAR;
enum HRESULT
{
    E_INVALIDARG,
    E_FAIL,
    S_OK,
};

enum RenderPass
{
    RenderPass_0,
    RenderPass_Static = RenderPass_0,
    RenderPass_Actor,
    RenderPass_Sky,
    RenderPass_NotRendered,
    RenderPass_Last
};

//
// class D3DSdkMeshResourceExtraData11
//

class IResourceExtraData
{
public:
    virtual std::string VToString()=0;
};

class D3DSdkMeshResourceExtraData11 : public IResourceExtraData
{
	friend class SdkMeshResourceLoader;

public:
	D3DSdkMeshResourceExtraData11() { };
	virtual ~D3DSdkMeshResourceExtraData11() { }
	virtual std::string VToString() { return "D3DSdkMeshResourceExtraData11"; }

	CDXUTSDKMesh m_Mesh11;	//This class includes functions to import, render, and destroy a mesh
};

//
// class SdkMeshResourceLoader						
//

class IResourceLoader
{
public:
    virtual std::string VGetPattern()=0;
    virtual bool VUseRawFile()=0;
    virtual bool VDiscardRawBufferAfterLoad()=0;
    virtual bool VAddNullZero() { return false; }
    virtual unsigned int VGetLoadedResourceSize(char *rawBuffer, unsigned int rawSize)=0;
    virtual bool VLoadResource(char *rawBuffer, unsigned int rawSize, shared_ptr<ResHandle> handle)=0;
};

class SdkMeshResourceLoader : public IResourceLoader
{
public:
	virtual bool VUseRawFile() { return false; }
	virtual bool VDiscardRawBufferAfterLoad() { return false; }
	virtual unsigned int VGetLoadedResourceSize(char *rawBuffer, unsigned int rawSize);
	virtual bool VLoadResource(char *rawBuffer, unsigned int rawSize, shared_ptr<ResHandle> handle);
	virtual std::string VGetPattern() { return "*.sdkmesh"; }
};


//
// D3DMeshNode9 Description
//
//    Attaches a ID3DXMesh Mesh object to the GameCode4 scene graph
//    This is a creature of D3D9, and not described in the 4th edition.
//    In the 3rd edition this was called D3DMeshNode
//

class D3DMeshNode9 : public D3DSceneNode9 // defined in SceneNode.h
{
protected:
    // http://msdn.microsoft.com/en-us/library/windows/desktop/bb174069(v=vs.85).aspx
	ID3DXMesh *m_pMesh;
	std::wstring m_XFileName;

public:
	D3DMeshNode9(const ActorId actorId, 
		WeakBaseRenderComponentPtr renderComponent,
		ID3DXMesh *Mesh, 
		RenderPass renderPass, 
		const Mat4x4 *t);

	D3DMeshNode9(const ActorId actorId, 
		WeakBaseRenderComponentPtr renderComponent,
		std::wstring xFileName, 
		RenderPass renderPass,  
		const Mat4x4 *t); 

	virtual ~D3DMeshNode9() { SAFE_RELEASE(m_pMesh); }
	HRESULT VRender(Scene *pScene);
	virtual HRESULT VOnRestore(Scene *pScene);
	virtual HRESULT VPick(Scene *pScene, RayCast *pRayCast);
	
	float CalcBoundingSphere();
};


//
// D3DShaderMeshNode9 Description
//
//    Attaches a ID3DXMesh Mesh object to the GameCode4 scene graph and renders it with a shader.
//    This is a creature of D3D9, and not described in the 4th edition.
//    In the 3rd edition this was called D3DShaderMeshNode
//

class D3DShaderMeshNode9 : public D3DMeshNode9
{
protected:
	ID3DXEffect *m_pEffect;
	std::string m_fxFileName;

public:
	D3DShaderMeshNode9(const ActorId actorId, 
		WeakBaseRenderComponentPtr renderComponent,
		ID3DXMesh *Mesh, 
		std::string fxFileName,
		RenderPass renderPass, 
		const Mat4x4 *t); 

	D3DShaderMeshNode9(const ActorId actorId,
		WeakBaseRenderComponentPtr renderComponent,
		std::wstring xFileName, 
		std::string fxFileName,
		RenderPass renderPass, 
		const Mat4x4 *t); 

	virtual ~D3DShaderMeshNode9() { SAFE_RELEASE(m_pEffect); }
	virtual HRESULT VOnRestore(Scene *pScene);
	virtual HRESULT VOnLostDevice(Scene *pScene);
	HRESULT VRender(Scene *pScene);
};

//
// class TeapotMeshNode9 teapot模型
//

class D3DTeapotMeshNode9 : public D3DShaderMeshNode9
{
public:
	D3DTeapotMeshNode9(const ActorId actorId, WeakBaseRenderComponentPtr renderComponent, std::string fxFileName, RenderPass renderPass, const Mat4x4 *t);
	virtual HRESULT VOnRestore(Scene *pScene);
};


class D3DShaderMeshNode11 : public SceneNode
{
public:
	D3DShaderMeshNode11(const ActorId actorId, 
		WeakBaseRenderComponentPtr renderComponent,
		std::string sdkMeshFileName, 
		RenderPass renderPass, 
		const Mat4x4 *t);

	virtual HRESULT VOnRestore(Scene *pScene);
	virtual HRESULT VOnLostDevice(Scene *pScene) { return S_OK; }
	virtual HRESULT VRender(Scene *pScene);
	virtual HRESULT VPick(Scene *pScene, RayCast *pRayCast);

protected:
	std::string					m_sdkMeshFileName;

	GameCode4_Hlsl_VertexShader		m_VertexShader;
	GameCode4_Hlsl_PixelShader		m_PixelShader;

	float CalcBoundingSphere(CDXUTSDKMesh *mesh11);			// this was added post press.
};


class D3DTeapotMeshNode11 : public D3DShaderMeshNode11
{
public:
	D3DTeapotMeshNode11(const ActorId actorId, WeakBaseRenderComponentPtr renderComponent, RenderPass renderPass,const Mat4x4 *t)
		: D3DShaderMeshNode11(actorId, renderComponent, "art\\teapot.sdkmesh", renderPass, t) { }
	bool VIsVisible() { return true; }
};


//========================================================================
// Mesh.cpp - classes to render meshes in D3D9 and D3D11
//========================================================================

#include "GameCodeStd.h"
#include <SDKmisc.h>
#include "GameCode.h"
#include "ResCache.h"
#include "D3DRenderer.h" // defined in Direct X渲染系统
#include "Lights.h"
#include "Mesh.h"
#include "Raycast.h"
#include "SceneNodes.h"


shared_ptr<IResourceLoader> CreateSdkMeshResourceLoader()
{
	return shared_ptr<IResourceLoader>(GCC_NEW SdkMeshResourceLoader());
}

unsigned int SdkMeshResourceLoader::VGetLoadedResourceSize(char *rawBuffer, unsigned int rawSize)
{
	// The raw data of the SDK Mesh file is needed by the CDXUTMesh class, so we're going to keep it around.
	return rawSize;
}

//
// SdkMeshResourceLoader::VLoadResource
//
bool SdkMeshResourceLoader::VLoadResource(char *rawBuffer, unsigned int rawSize, shared_ptr<ResHandle> handle)
{
	GameCodeApp::Renderer renderer = GameCodeApp::GetRendererImpl();
	if (renderer == GameCodeApp::Renderer_D3D9)
	{
		GCC_ASSERT(0 && "This is not supported in D3D9");
	}
	else if (renderer == GameCodeApp::Renderer_D3D11)
	{
		shared_ptr<D3DSdkMeshResourceExtraData11> extra = shared_ptr<D3DSdkMeshResourceExtraData11>(GCC_NEW D3DSdkMeshResourceExtraData11());

		// Load the Mesh 倒入模型文件
	    if (SUCCEEDED ( extra->m_Mesh11.Create( DXUTGetD3D11Device(), (BYTE *)rawBuffer, (UINT)rawSize, true ) ) )
		{
			handle->SetExtra(shared_ptr<D3DSdkMeshResourceExtraData11>(extra));
		}

		return true;
	}

	GCC_ASSERT(0 && "Unsupported Renderer in SdkMeshResourceLoader::VLoadResource");
	return false;
}




////////////////////////////////////////////////////
// MeshNode Implementation
////////////////////////////////////////////////////

//
// D3DMeshNode9::D3DMeshNode9
//
D3DMeshNode9::D3DMeshNode9(const ActorId actorId, 
	WeakBaseRenderComponentPtr renderComponent,
	ID3DXMesh *Mesh, 
	RenderPass renderPass, 
	const Mat4x4 *t )
 : D3DSceneNode9(actorId, renderComponent, renderPass, t) 
{ 
	m_pMesh = Mesh; 
	if (m_pMesh)
	{
		// Added post press - not all Mesh modes have Meshes. Some are just effects!
		m_pMesh->AddRef(); 
	}
}

//
// MeshNode::MeshNode
//
D3DMeshNode9::D3DMeshNode9(const ActorId actorId, 
	WeakBaseRenderComponentPtr renderComponent,
	std::wstring xFileName, 
	RenderPass renderPass,  
	const Mat4x4 *t)
 : D3DSceneNode9(actorId, renderComponent, renderPass, t) 
{ 
	m_pMesh = NULL;
	m_XFileName = xFileName;
}

//
// MeshNode::CalcBoundingSphere
//
typedef struct D3DXVECTOR3 {
    float x;
    float y;
    float z;
} D3DXVECTOR3, *LPD3DXVECTOR3;

float D3DMeshNode9::CalcBoundingSphere()
{
    D3DXVECTOR3* pData;
    D3DXVECTOR3 vCenter;
    FLOAT fObjectRadius;
	HRESULT hr;
	V( m_pMesh->LockVertexBuffer( 0, ( LPVOID* )&pData ) );
    V( D3DXComputeBoundingSphere( pData, m_pMesh->GetNumVertices(),
                                  D3DXGetFVFVertexSize( m_pMesh->GetFVF() ), &vCenter, &fObjectRadius ) );
    V( m_pMesh->UnlockVertexBuffer() );

	return fObjectRadius;
}


//
// MeshNode::VRender
//
HRESULT D3DMeshNode9::VRender(Scene *pScene)
{
	if (S_OK != D3DSceneNode9::VRender(pScene) )
		return E_FAIL;

	return m_pMesh->DrawSubset(0); 
} 

//
// MeshNode::VOnRestore
//
// This function loads the Mesh and ensures the Mesh has normals; it also optimizes the 
// Mesh for the graphics card's vertex cache, which improves performance by organizing 
// the internal triangle list for less cache misses.
//
HRESULT D3DMeshNode9::VOnRestore(Scene *pScene)
{
	if (m_XFileName.empty())
	{
		SetRadius(CalcBoundingSphere());
		return D3DSceneNode9::VOnRestore(pScene);
	}

	// Change post press - release the Mesh only if we have a valid Mesh file name to load.
	// Otherwise we likely created it on our own, and needs to be kept.
	SAFE_RELEASE(m_pMesh);

    WCHAR str[MAX_PATH];
    HRESULT hr;

    // Load the Mesh with D3DX and get back a ID3DXMesh*.  For this
    // sample we'll ignore the X file's embedded materials since we know 
    // exactly the model we're loading.  See the Mesh samples such as
    // "OptimizedMesh" for a more generic Mesh loading example.
	V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, m_XFileName.c_str() ) );

    V_RETURN( D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, DXUTGetD3D9Device(), NULL, NULL, NULL, NULL, &m_pMesh) );

    DWORD *rgdwAdjacency = NULL;

    // Make sure there are normals which are required for lighting
    if( !(m_pMesh->GetFVF() & D3DFVF_NORMAL) )
    {
        ID3DXMesh* pTempMesh;
        V( m_pMesh->CloneMeshFVF( m_pMesh->GetOptions(), 
                                  m_pMesh->GetFVF() | D3DFVF_NORMAL, 
                                  DXUTGetD3D9Device(), &pTempMesh ) );
        V( D3DXComputeNormals( pTempMesh, NULL ) );

        SAFE_RELEASE( m_pMesh );
        m_pMesh = pTempMesh;
    }

    // Optimize the Mesh for this graphics card's vertex cache 
    // so when rendering the Mesh's triangle list the vertices will 
    // cache hit more often so it won't have to re-execute the vertex shader 
    // on those vertices so it will improve perf.     

    rgdwAdjacency = GCC_NEW DWORD[m_pMesh->GetNumFaces() * 3];
    if( rgdwAdjacency == NULL )
        return E_OUTOFMEMORY;
    V( m_pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) );
    V( m_pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
    
	SAFE_DELETE_ARRAY(rgdwAdjacency);

	SetRadius(CalcBoundingSphere());

    return D3DSceneNode9::VOnRestore(pScene);
}

HRESULT D3DMeshNode9::VPick(Scene *pScene, RayCast *pRayCast)
{
	if (SceneNode::VPick(pScene, pRayCast)==E_FAIL)
		return E_FAIL;

	pScene->PushAndSetMatrix(m_Props.ToWorld());
	HRESULT hr = pRayCast->Pick(pScene, m_Props.ActorId(), m_pMesh);
	pScene->PopMatrix();

	return hr;
}


////////////////////////////////////////////////////
// D3DShaderMeshNode9 Implementation
////////////////////////////////////////////////////

//
// ShaderMeshNode::ShaderMeshNode
//
D3DShaderMeshNode9::D3DShaderMeshNode9(const ActorId actorId, 
	WeakBaseRenderComponentPtr renderComponent,
	ID3DXMesh *Mesh, 
	std::string fxFileName,			// used to be effect pointer - changed to fix a VOnRestore crash.
	RenderPass renderPass, 
	const Mat4x4 *t)
 : D3DMeshNode9(actorId, renderComponent, Mesh, renderPass, t) 
{ 
	m_pEffect = NULL;
	m_fxFileName = fxFileName;
}

//
// ShaderMeshNode::ShaderMeshNode
//
D3DShaderMeshNode9::D3DShaderMeshNode9(const ActorId actorId, 
	WeakBaseRenderComponentPtr renderComponent,
	std::wstring xFileName, 
	std::string fxFileName,
	RenderPass renderPass, 
	const Mat4x4 *t)
 : D3DMeshNode9(actorId, renderComponent, xFileName, renderPass, t) 
{
	m_pEffect = NULL;
	m_fxFileName = fxFileName;
}

//
// ShaderMeshNode::VOnRestore					- very similar to MeshNode::VOnRestore
//
HRESULT D3DShaderMeshNode9::VOnRestore(Scene *pScene)
{
	SAFE_RELEASE(m_pEffect);

	DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE | D3DXSHADER_DEBUG | D3DXSHADER_NO_PRESHADER;
	HRESULT hr;

    Resource resource(m_fxFileName);
    shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);  // this actually loads the XML file from the zip file
	V ( D3DXCreateEffect( DXUTGetD3D9Device(), pResourceHandle->Buffer(), pResourceHandle->Size(), NULL, NULL, dwShaderFlags, NULL, &m_pEffect, NULL ) );
	return D3DMeshNode9::VOnRestore(pScene);
}

//
// ShaderMeshNode::VRender
//
HRESULT D3DShaderMeshNode9::VRender(Scene *pScene)
{
	if (S_OK != D3DSceneNode9::VRender(pScene) )
		return E_FAIL;

	HRESULT hr;

    // Update the effect's variables.  Instead of using strings, it would 
    // be more efficient to cache a handle to the parameter by calling 
    // ID3DXEffect::GetParameterByName

	Mat4x4 worldViewProj = pScene->GetCamera()->GetWorldViewProjection(pScene);
	Mat4x4 world = pScene->GetTopMatrix();

	D3DXCOLOR ambient =  m_Props.GetMaterial().GetAmbient();
    V_RETURN( m_pEffect->SetValue( "g_MaterialAmbientColor", &ambient, sizeof( D3DXCOLOR ) ) );
	D3DXCOLOR diffuse =  m_Props.GetMaterial().GetDiffuse();
    V_RETURN( m_pEffect->SetValue( "g_MaterialDiffuseColor", &diffuse, sizeof( D3DXCOLOR ) ) );

	V( m_pEffect->SetMatrix( "g_mWorldViewProjection", &worldViewProj ) );
    V( m_pEffect->SetMatrix( "g_mWorld", &world ) );
    V( m_pEffect->SetFloat( "g_fTime", ( float )1.0f ) );

	int count = pScene->GetLightManager()->GetLightCount(this);
	if (count)
	{
		// Light 0 is the only one we use for ambient lighting. The rest are ignored in this simple shader.
		V( m_pEffect->SetValue( "g_LightAmbient", pScene->GetLightManager()->GetLightAmbient(this), sizeof( D3DXVECTOR4 ) * 1 ) );
		V( m_pEffect->SetValue( "g_LightDir", pScene->GetLightManager()->GetLightDirection(this), sizeof( D3DXVECTOR4 ) * MAXIMUM_LIGHTS_SUPPORTED ) );
		V( m_pEffect->SetValue( "g_LightDiffuse", pScene->GetLightManager()->GetLightDiffuse(this), sizeof( D3DXVECTOR4 ) * MAXIMUM_LIGHTS_SUPPORTED ) );
		V( m_pEffect->SetInt( "g_nNumLights", count ) );
	}

	float alpha = m_Props.GetMaterial().GetAlpha();
	V( m_pEffect->SetFloat( "g_fAlpha", alpha  ) );	
	V( m_pEffect->SetTechnique( (alpha < 1.0f ) ? "RenderSceneWithAlpha" : "RenderScene" ) );

    // Apply the technique contained in the effect 
	UINT iPass, cPasses;

    V( m_pEffect->Begin( &cPasses, 0 ) );

    for( iPass = 0; iPass < cPasses; iPass++ )
    {
        V( m_pEffect->BeginPass( iPass ) );

        // The effect interface queues up the changes and performs them 
        // with the CommitChanges call. You do not need to call CommitChanges if 
        // you are not setting any parameters between the BeginPass and EndPass.
        // V( g_pEffect->CommitChanges() );

        // Render the Mesh with the applied technique
        V( m_pMesh->DrawSubset( 0 ) );

        V( m_pEffect->EndPass() );
    }
    V( m_pEffect->End() );

	return S_OK;
} 

HRESULT D3DShaderMeshNode9::VOnLostDevice(Scene *pScene)
{
	SAFE_RELEASE(m_pEffect);

	HRESULT hr;
	V_RETURN(D3DMeshNode9::VOnLostDevice(pScene));
	return S_OK;
}


//
// TeapotMeshNode::TeapotMeshNode
//
D3DTeapotMeshNode9::D3DTeapotMeshNode9(const ActorId actorId, WeakBaseRenderComponentPtr renderComponent, std::string fxFileName, RenderPass renderPass, const Mat4x4 *t)
: D3DShaderMeshNode9(actorId, renderComponent, NULL, fxFileName, renderPass, t) 
{ 
	// there's nothing else needed here...
}

//
// TeapotMeshNode::VOnRestore
//
HRESULT D3DTeapotMeshNode9::VOnRestore(Scene *pScene)
{
	HRESULT hr;

	IDirect3DDevice9 * pDevice = DXUTGetD3D9Device();

	SAFE_RELEASE(m_pMesh);
	V( D3DXCreateTeapot( pDevice, &m_pMesh, NULL ) );

	//Rotate the teapot 90 degrees from default so that the spout faces forward
	Mat4x4 rotateY90;
	rotateY90.BuildRotationY(-GCC_PI / 2.0f);
	IDirect3DVertexBuffer9* pVB = NULL;
	m_pMesh->GetVertexBuffer(&pVB);
	Vec3* pVertices = NULL;
	pVB->Lock( 0, 0, (void**)&pVertices, 0 );
	for (unsigned int i=0; i<m_pMesh->GetNumVertices(); ++i)
	{
		*pVertices = rotateY90.Xform(*pVertices);
		++pVertices;
		//The structs depicted in this vertex buffer actually store
		//information for normals in addition to xyz, thereby
		//making the vertices in pVB twice the size of the one described
		//by *pVertices.  So we address that here.
		*pVertices = rotateY90.Xform(*pVertices);	//rotate the normals, too
		++pVertices;
	}
	pVB->Unlock();
	SAFE_RELEASE( pVB );
	//...end rotation



	// Note - the Mesh is needed BEFORE calling the base class VOnRestore.
	V ( D3DShaderMeshNode9::VOnRestore ( pScene ) );
	return S_OK;
}




//
// D3DShaderMeshNode11::D3DShaderMeshNode11
//
D3DShaderMeshNode11::D3DShaderMeshNode11(const ActorId actorId, 
	WeakBaseRenderComponentPtr renderComponent,
	std::string sdkMeshFileName, 
	RenderPass renderPass, 
	const Mat4x4 *t)
: SceneNode(actorId, renderComponent, renderPass, t)
{
	m_sdkMeshFileName = sdkMeshFileName;
}


//
// D3DShaderMeshNode11::VOnRestore
//
HRESULT D3DShaderMeshNode11::VOnRestore(Scene *pScene)
{
	HRESULT hr;

	V_RETURN(SceneNode::VOnRestore(pScene) );

	V_RETURN (m_VertexShader.OnRestore(pScene) );
	V_RETURN (m_PixelShader.OnRestore(pScene) );

    // Force the Mesh to reload
	Resource resource(m_sdkMeshFileName);
    shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);  	
	shared_ptr<D3DSdkMeshResourceExtraData11> extra = static_pointer_cast<D3DSdkMeshResourceExtraData11>(pResourceHandle->GetExtra());

	SetRadius(CalcBoundingSphere(&extra->m_Mesh11));

	return S_OK;
}

//
// D3DShaderMeshNode11::VRender
//
HRESULT D3DShaderMeshNode11::VRender(Scene *pScene)
{
	HRESULT hr;

	V_RETURN (m_VertexShader.SetupRender(pScene, this) );
	V_RETURN (m_PixelShader.SetupRender(pScene, this) );

    //Get the Mesh
	Resource resource(m_sdkMeshFileName);
    shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);  	
	shared_ptr<D3DSdkMeshResourceExtraData11> extra = static_pointer_cast<D3DSdkMeshResourceExtraData11>(pResourceHandle->GetExtra());

	// FUTURE WORK - this code WON'T be able to find texture resources referred to by the sdkmesh file 
    // in the Resource cache.

    //IA setup
    UINT Strides[1];
    UINT Offsets[1];
    ID3D11Buffer* pVB[1];
    pVB[0] = extra->m_Mesh11.GetVB11( 0, 0 );
    Strides[0] = ( UINT )extra->m_Mesh11.GetVertexStride( 0, 0 );
    Offsets[0] = 0;
    DXUTGetD3D11DeviceContext()->IASetVertexBuffers( 0, 1, pVB, Strides, Offsets );
    DXUTGetD3D11DeviceContext()->IASetIndexBuffer( extra->m_Mesh11.GetIB11( 0 ), extra->m_Mesh11.GetIBFormat11( 0 ), 0 );

    //Render
    D3D11_PRIMITIVE_TOPOLOGY PrimType;
    for( UINT subset = 0; subset < extra->m_Mesh11.GetNumSubsets( 0 ); ++subset )
    {
        // Get the subset
        SDKMESH_SUBSET *pSubset = extra->m_Mesh11.GetSubset( 0, subset );

        PrimType = CDXUTSDKMesh::GetPrimitiveType11( ( SDKMESH_PRIMITIVE_TYPE )pSubset->PrimitiveType );
        DXUTGetD3D11DeviceContext()->IASetPrimitiveTopology( PrimType );
 
        ID3D11ShaderResourceView* pDiffuseRV = extra->m_Mesh11.GetMaterial( pSubset->MaterialID )->pDiffuseRV11;
        DXUTGetD3D11DeviceContext()->PSSetShaderResources( 0, 1, &pDiffuseRV );

        DXUTGetD3D11DeviceContext()->DrawIndexed( ( UINT )pSubset->IndexCount, 0, ( UINT )pSubset->VertexStart );
    }
	return S_OK;
}

HRESULT D3DShaderMeshNode11::VPick(Scene *pScene, RayCast *pRayCast)
{
	if (SceneNode::VPick(pScene, pRayCast)==E_FAIL)
		return E_FAIL;

	pScene->PushAndSetMatrix(m_Props.ToWorld());

    //Get the Mesh
	Resource resource(m_sdkMeshFileName);
    shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);  	
	shared_ptr<D3DSdkMeshResourceExtraData11> extra = static_pointer_cast<D3DSdkMeshResourceExtraData11>(pResourceHandle->GetExtra());

	HRESULT hr = pRayCast->Pick(pScene, m_Props.ActorId(), &extra->m_Mesh11);
	pScene->PopMatrix();

	return hr;
}




float D3DShaderMeshNode11::CalcBoundingSphere(CDXUTSDKMesh *mesh11)
{
	float radius = 0.0f;
    for( UINT subset = 0; subset < mesh11->GetNumSubsets( 0 ); ++subset )
    {
		Vec3 extents = mesh11->GetMeshBBoxExtents(subset);
		extents.x = abs(extents.x);
		extents.y = abs(extents.y);
		extents.z = abs(extents.z);
		radius = (radius > extents.x) ? radius : extents.x;
		radius = (radius > extents.y) ? radius : extents.y;
		radius = (radius > extents.z) ? radius : extents.z;
	}
	return radius;
}


2. 着色器 Shader实现

#pragma once
//========================================================================
// Shaders.h - helper classes to call GameCode4_VS.hlsl and GameCode4_PS.hlsl
//========================================================================

#include <xnamath.h>
#include "Geometry.h"
#include "Material.h"


#define GCC_NEW new
#if !defined(SAFE_RELEASE)
#define SAFE_RELEASE(x) if(x) x->Release(); x=NULL;
#endif
//BaseRenderComponent defined in Actors folder
typedef BaseRenderComponent* WeakBaseRenderComponentPtr;
typedef unsigned int  ActorId;
typedef unsigned int  GameViewId;
typedef D3DXCOLOR     Color;
typedef unsigned int  DWORD;
typedef unsigned char BYTE;
typedef float         FLOAT;
typedef unsigned int  UINT;
#ifdef   UNICODE
typedef wchar_t       TCHAR;
#else
typedef unsigned char TCHAR;
#endif
typedef unsigned char CHAR;
typedef unsigned wchar_t WCHAR;
enum HRESULT
{
    E_INVALIDARG,
    E_FAIL,
    S_OK,
};


// Forward declarations
class SceneNode;
class Scene;

class GameCode4_Hlsl_VertexShader
{
public:
	GameCode4_Hlsl_VertexShader();
	~GameCode4_Hlsl_VertexShader();

	HRESULT OnRestore(Scene *pScene);
	HRESULT SetupRender(Scene *pScene, SceneNode *pNode);
	void EnableLights(bool enableLights) { m_enableLights = enableLights; }

protected:
	ID3D11InputLayout*          m_pVertexLayout11;
	ID3D11VertexShader*         m_pVertexShader;
    // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476351(v=vs.85).aspx
	ID3D11Buffer*               m_pcbVSMatrices;
	ID3D11Buffer*               m_pcbVSLighting;
	ID3D11Buffer*               m_pcbVSMaterial;
	bool						m_enableLights;
};


class GameCode4_Hlsl_PixelShader
{
public:
	GameCode4_Hlsl_PixelShader();
	~GameCode4_Hlsl_PixelShader();

	HRESULT OnRestore(Scene *pScene);
	HRESULT SetupRender(Scene *pScene, SceneNode *pNode);
	HRESULT SetTexture(const std::string& textureName);
	HRESULT SetTexture(ID3D11ShaderResourceView* const *pDiffuseRV, ID3D11SamplerState * const *ppSamplers);

protected:
	ID3D11PixelShader*          m_pPixelShader;
	ID3D11Buffer*               m_pcbPSMaterial;
	std::string					m_textureResource;
};

// http://msdn.microsoft.com/en-us/library/windows/desktop/ff476652(v=vs.85).aspx
struct ID3DX11Effect;
struct ID3DX11EffectTechnique;
struct ID3DX11EffectPass;

class LineDraw_Hlsl_Shader
{
public:
	LineDraw_Hlsl_Shader();
	~LineDraw_Hlsl_Shader();

	HRESULT OnRestore(Scene *pScene);
	HRESULT SetupRender(Scene *pScene);
	HRESULT SetDiffuse(const std::string& textureName, const Color &color);
	HRESULT SetTexture(ID3D11ShaderResourceView* const *pDiffuseRV, ID3D11SamplerState * const *ppSamplers);

protected:
	ID3D11InputLayout*          m_pVertexLayout11;
	ID3D11Buffer*               m_pcbRenderTargetSize;
	ID3DX11Effect*				m_pEffect;

	ID3DX11EffectTechnique*		m_EffectTechnique; // No need to be Release()-d.
	ID3DX11EffectPass*			m_EffectPass; // No need to be Release()-d.

	ID3D11Buffer*               m_pcbChangePerFrame;

	ID3D11Buffer*               m_pcbDiffuseColor;

	std::string					m_textureResource;

};
//=============================================================================
// Shaders.cpp - helper classes to call GameCode4_VS.hlsl and GameCode4_PS.hlsl
//=============================================================================

#include "GameCodeStd.h"
#include "GameCode.h"
#include "D3DRenderer.h"
#include "Geometry.h"
#include "Lights.h"
#include "Mesh.h"
#include "SceneNodes.h"
#include "ResCache.h"
#include <xnamath.h>
#pragma comment(lib, "effects11.lib")			// [mrmike] Note you can remove this if you don't want the D3DX11CreateEffectFromMemory API.
#include "d3dx11effect.h"

//
// GameCode4_Hlsl_VertexShader::GameCode4_Hlsl_VertexShader
//
GameCode4_Hlsl_VertexShader::GameCode4_Hlsl_VertexShader()
{
	m_pVertexLayout11 = NULL;
	m_pVertexShader = NULL;
	m_pcbVSMatrices = NULL;
	m_pcbVSLighting = NULL;
	m_pcbVSMaterial = NULL;
	m_enableLights = true;
}

//
// GameCode4_Hlsl_VertexShader::~GameCode4_Hlsl_VertexShader
//
GameCode4_Hlsl_VertexShader::~GameCode4_Hlsl_VertexShader()
{
	SAFE_RELEASE(m_pVertexLayout11);
	SAFE_RELEASE(m_pVertexShader);
	SAFE_RELEASE(m_pcbVSMatrices);
	SAFE_RELEASE(m_pcbVSLighting );
	SAFE_RELEASE(m_pcbVSMaterial);
}

//
// GameCode4_Hlsl_VertexShader::OnRestore
//
HRESULT GameCode4_Hlsl_VertexShader::OnRestore(Scene *pScene)
{
	HRESULT hr = S_OK;

	SAFE_RELEASE(m_pVertexLayout11);
	SAFE_RELEASE(m_pVertexShader);
	SAFE_RELEASE(m_pcbVSMatrices);
	SAFE_RELEASE(m_pcbVSLighting );
	SAFE_RELEASE(m_pcbVSMaterial);

	shared_ptr<D3DRenderer11> d3dRenderer11 = static_pointer_cast<D3DRenderer11>(pScene->GetRenderer());

	//========================================================
	// Set up the vertex shader and related constant buffers

    // Compile the vertex shader using the lowest possible profile for broadest feature level support
    ID3DBlob* pVertexShaderBuffer = NULL;

	std::string hlslFileName = "Effects\\GameCode4_VS.hlsl";
	Resource resource(hlslFileName.c_str());
    shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);  // this actually loads the HLSL file from the zip file
	if (FAILED (d3dRenderer11->CompileShader(pResourceHandle->Buffer(), pResourceHandle->Size(), hlslFileName.c_str(), "GameCode4_VSMain", "vs_4_0_level_9_1", &pVertexShaderBuffer ) ) )
 	{
		SAFE_RELEASE (pVertexShaderBuffer);
		return hr;
	}

    if (FAILED ( DXUTGetD3D11Device()->CreateVertexShader( pVertexShaderBuffer->GetBufferPointer(),
                                              pVertexShaderBuffer->GetBufferSize(), NULL, &m_pVertexShader ) ) )
	{
		SAFE_RELEASE (pVertexShaderBuffer);
		return hr;
	}

    DXUT_SetDebugName( m_pVertexShader, "GameCode4_VSMain" );
	
    if (SUCCEEDED ( DXUTGetD3D11Device()->CreateInputLayout( D3D11VertexLayout_UnlitTextured, ARRAYSIZE( D3D11VertexLayout_UnlitTextured ), pVertexShaderBuffer->GetBufferPointer(),
                                             pVertexShaderBuffer->GetBufferSize(), &m_pVertexLayout11 ) ) )
	{
	    DXUT_SetDebugName( m_pVertexLayout11, "Primary" );

		// Setup constant buffers
		D3D11_BUFFER_DESC Desc;
		Desc.Usage = D3D11_USAGE_DYNAMIC;
		Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
		Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		Desc.MiscFlags = 0;

		Desc.ByteWidth = sizeof( ConstantBuffer_Matrices );
		V_RETURN( DXUTGetD3D11Device()->CreateBuffer( &Desc, NULL, &m_pcbVSMatrices ) );
		DXUT_SetDebugName( m_pcbVSMatrices, "ConstantBuffer_Matrices" );

		Desc.ByteWidth = sizeof( ConstantBuffer_Lighting );
		V_RETURN( DXUTGetD3D11Device()->CreateBuffer( &Desc, NULL, &m_pcbVSLighting ) );
		DXUT_SetDebugName( m_pcbPSLighting, "ConstantBuffer_Lighting" );

		Desc.ByteWidth = sizeof( ConstantBuffer_Material );
		V_RETURN( DXUTGetD3D11Device()->CreateBuffer( &Desc, NULL, &m_pcbVSMaterial ) );
		DXUT_SetDebugName( m_pcbVSMaterial, "ConstantBuffer_Material" );
	}

    SAFE_RELEASE( pVertexShaderBuffer );
	return S_OK;
}

//
// GameCode4_Hlsl_VertexShader::SetupRender
//
HRESULT GameCode4_Hlsl_VertexShader::SetupRender(Scene *pScene, SceneNode *pNode)
{
	HRESULT hr = S_OK;

	// Set the vertex shader and the vertex layout
    DXUTGetD3D11DeviceContext()->VSSetShader( m_pVertexShader, NULL, 0 );
    DXUTGetD3D11DeviceContext()->IASetInputLayout( m_pVertexLayout11 );
	
    // Get the projection & view matrix from the camera class
	Mat4x4 mWorldViewProjection = pScene->GetCamera()->GetWorldViewProjection(pScene);
	Mat4x4 mWorld = pScene->GetTopMatrix();

	D3D11_MAPPED_SUBRESOURCE MappedResource;

	// ----- Transform Matricies ------
    V( DXUTGetD3D11DeviceContext()->Map( m_pcbVSMatrices, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) );

	ConstantBuffer_Matrices* pVSMatricies = ( ConstantBuffer_Matrices* )MappedResource.pData;
	D3DXMatrixTranspose( &pVSMatricies->m_WorldViewProj, &mWorldViewProjection );
    D3DXMatrixTranspose( &pVSMatricies->m_World, &mWorld );

	DXUTGetD3D11DeviceContext()->Unmap( m_pcbVSMatrices, 0 );

	// ----- Lighting ------
    V( DXUTGetD3D11DeviceContext()->Map( m_pcbVSLighting, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) );
    ConstantBuffer_Lighting* pLighting = ( ConstantBuffer_Lighting* )MappedResource.pData;

	if (m_enableLights)
	{
		pScene->GetLightManager()->CalcLighting(pLighting, pNode);
	}
	else
	{
		pLighting->m_nNumLights = 0;
		pLighting->m_vLightAmbient = Vec4(1.0f, 1.0f, 1.0f, 1.0f);
	}

	DXUTGetD3D11DeviceContext()->Unmap( m_pcbVSLighting, 0 );

	// ----- Material ------
	V( DXUTGetD3D11DeviceContext()->Map( m_pcbVSMaterial, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) );
    ConstantBuffer_Material* pPSMaterial = ( ConstantBuffer_Material* )MappedResource.pData;

	Color color = pNode->VGet()->GetMaterial().GetDiffuse();
	pPSMaterial->m_vDiffuseObjectColor = Vec4(color.r, color.g, color.b, color.a);
	color = (m_enableLights) ? pNode->VGet()->GetMaterial().GetAmbient() : Color(1.0f, 1.0f, 1.0f, 1.0f);
	pPSMaterial->m_vAmbientObjectColor = Vec4(color.r, color.g, color.b, color.a);
	// Note - the vertex shader doesn't care about the texture one way or another so we'll just set it to false
	pPSMaterial->m_bHasTexture = false;

    DXUTGetD3D11DeviceContext()->Unmap( m_pcbVSMaterial, 0 );

    DXUTGetD3D11DeviceContext()->VSSetConstantBuffers( 0, 1, &m_pcbVSMatrices );
    DXUTGetD3D11DeviceContext()->VSSetConstantBuffers( 1, 1, &m_pcbVSLighting );
    DXUTGetD3D11DeviceContext()->VSSetConstantBuffers( 2, 1, &m_pcbVSMaterial );

	return S_OK;
}

//
// GameCode4_Hlsl_PixelShader::GameCode4_Hlsl_PixelShader
//
GameCode4_Hlsl_PixelShader::GameCode4_Hlsl_PixelShader()
{
	m_pPixelShader = NULL;
	m_pcbPSMaterial = NULL;
}

//
// GameCode4_Hlsl_PixelShader::~GameCode4_Hlsl_PixelShader
//
GameCode4_Hlsl_PixelShader::~GameCode4_Hlsl_PixelShader()
{
	SAFE_RELEASE(m_pPixelShader);
	SAFE_RELEASE(m_pcbPSMaterial);
}

//
// GameCode4_Hlsl_PixelShader::OnRestore
//
HRESULT GameCode4_Hlsl_PixelShader::OnRestore(Scene *pScene)
{
	HRESULT hr = S_OK;

	SAFE_RELEASE(m_pPixelShader);
	SAFE_RELEASE(m_pcbPSMaterial);

	shared_ptr<D3DRenderer11> d3dRenderer11 = static_pointer_cast<D3DRenderer11>(pScene->GetRenderer());

	//========================================================
	// Set up the pixel shader and related constant buffers

    // Compile the pixel shader using the lowest possible profile for broadest feature level support
    ID3DBlob* pPixelShaderBuffer = NULL;

	std::string hlslFileName = "Effects\\GameCode4_PS.hlsl";
	Resource resource(hlslFileName.c_str());
    shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);  // this actually loads the HLSL file from the zip file
	if (FAILED (d3dRenderer11->CompileShader(pResourceHandle->Buffer(), pResourceHandle->Size(), hlslFileName.c_str(), "GameCode4_PSMain", "ps_4_0_level_9_1", &pPixelShaderBuffer ) ) )
 	{
		SAFE_RELEASE (pPixelShaderBuffer);
		return hr;
	}

    if (SUCCEEDED ( DXUTGetD3D11Device()->CreatePixelShader( pPixelShaderBuffer->GetBufferPointer(),
                                             pPixelShaderBuffer->GetBufferSize(), NULL, &m_pPixelShader ) ) )
	{
		DXUT_SetDebugName( m_pPixelShader, "GameCode4_PSMain" );

		// Setup constant buffers
		D3D11_BUFFER_DESC Desc;
		Desc.Usage = D3D11_USAGE_DYNAMIC;
		Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
		Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		Desc.MiscFlags = 0;

		Desc.ByteWidth = sizeof( ConstantBuffer_Material );
		hr = DXUTGetD3D11Device()->CreateBuffer( &Desc, NULL, &m_pcbPSMaterial );
		DXUT_SetDebugName( m_pcbPSMaterial, "ConstantBuffer_Material" );
	}

    SAFE_RELEASE( pPixelShaderBuffer );
	return hr;
}

//
// GameCode4_Hlsl_PixelShader::SetupRender
//
HRESULT GameCode4_Hlsl_PixelShader::SetupRender(Scene *pScene, SceneNode *pNode)
{
	HRESULT hr = S_OK;

    DXUTGetD3D11DeviceContext()->PSSetShader( m_pPixelShader, NULL, 0 );

    D3D11_MAPPED_SUBRESOURCE MappedResource;

	V( DXUTGetD3D11DeviceContext()->Map( m_pcbPSMaterial, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) );
    ConstantBuffer_Material* pPSMaterial = ( ConstantBuffer_Material* )MappedResource.pData;

	Color color = pNode->VGet()->GetMaterial().GetDiffuse();
	pPSMaterial->m_vDiffuseObjectColor = Vec4(color.r, color.g, color.b, color.a);

	if (m_textureResource.length() > 0)
	{
		pPSMaterial->m_bHasTexture = true;
	}
	else
	{
		pPSMaterial->m_bHasTexture = false;
	}

    DXUTGetD3D11DeviceContext()->Unmap( m_pcbPSMaterial, 0 );

    DXUTGetD3D11DeviceContext()->PSSetConstantBuffers( 0, 1, &m_pcbPSMaterial );
	
	// Set up the texture
	SetTexture(m_textureResource);	

	return S_OK;
}

//
// GameCode4_Hlsl_PixelShader::SetTexture
//
HRESULT GameCode4_Hlsl_PixelShader::SetTexture(const std::string& textureName)
{
	m_textureResource = textureName;
	if (m_textureResource.length() > 0)
	{
		Resource resource(m_textureResource);
		shared_ptr<ResHandle> texture = g_pApp->m_ResCache->GetHandle(&resource);
		if (texture)
		{
			shared_ptr<D3DTextureResourceExtraData11> extra = static_pointer_cast<D3DTextureResourceExtraData11>(texture->GetExtra());
			SetTexture(extra->GetTexture(), extra->GetSampler());
		}
	}
	return S_OK;
}

HRESULT GameCode4_Hlsl_PixelShader::SetTexture(ID3D11ShaderResourceView* const *pDiffuseRV, ID3D11SamplerState * const *ppSamplers)
{
	DXUTGetD3D11DeviceContext()->PSSetShaderResources( 0, 1, pDiffuseRV );
	DXUTGetD3D11DeviceContext()->PSSetSamplers( 0, 1, ppSamplers );
	return S_OK;
}	



struct LineDrawerChangePerFrameBuffer
{
	Mat4x4 m_WorldViewProjection;
	Vec4 m_DiffuseColor;
};

LineDraw_Hlsl_Shader::LineDraw_Hlsl_Shader()
{
	m_pEffect = NULL;
	m_pVertexLayout11 = NULL;
	m_pcbChangePerFrame = NULL;
	m_pcbRenderTargetSize = NULL;
	m_pcbDiffuseColor = NULL;
}


LineDraw_Hlsl_Shader::~LineDraw_Hlsl_Shader()
{
	SAFE_RELEASE(m_pVertexLayout11);
	SAFE_RELEASE(m_pcbChangePerFrame);
	SAFE_RELEASE(m_pcbRenderTargetSize);
	SAFE_RELEASE(m_pcbDiffuseColor);
	SAFE_RELEASE(m_pEffect);
}




HRESULT LineDraw_Hlsl_Shader::OnRestore(Scene *pScene)
{
	HRESULT hr = S_OK;

	SAFE_RELEASE(m_pEffect);
	SAFE_RELEASE(m_pcbDiffuseColor);
	SAFE_RELEASE(m_pVertexLayout11);
	SAFE_RELEASE(m_pcbChangePerFrame);
	SAFE_RELEASE(m_pcbRenderTargetSize);

	shared_ptr<D3DRenderer11> d3dRenderer11 = static_pointer_cast<D3DRenderer11>(pScene->GetRenderer());

	//========================================================
	// Set up the vertex shader and related constant buffers

    // Compile the vertex shader using the lowest possible profile for broadest feature level support
    ID3DBlob* pVertexShaderBuffer = NULL;

	std::string hlslFileName = "Effects\\LineDraw.hlsl";
	Resource resource(hlslFileName.c_str());
    shared_ptr<ResHandle> pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource);  // this actually loads the HLSL file from the zip file

	// Compile effect from HLSL file into binary Blob in memory
	// The code in this function was found here - http://asawicki.info/news_1371_effects_in_directx_11.html

	ID3D10Blob *effectBlob = 0, *errorsBlob = 0;
	hr = D3DX11CompileFromMemory(
	  pResourceHandle->Buffer(),			// srcData
	  pResourceHandle->Size(),				// srcLen
	  0, 0, 0, 0,							// fileName, pDefines, pInclude, functionName
	  "fx_5_0", 0, 0, 0,					// profile, flags1, flags2, pump
	  &effectBlob, &errorsBlob, 0);			// shader, errorMsg, pResult
	assert(SUCCEEDED(hr) && effectBlob);
	if (errorsBlob) errorsBlob->Release();

	// Create D3DX11 effect from compiled binary memory block
	if (FAILED ( D3DX11CreateEffectFromMemory(
	  effectBlob->GetBufferPointer(), effectBlob->GetBufferSize(), 0, DXUTGetD3D11Device(), &m_pEffect) ) )
	{
		return hr;
	}

	effectBlob->Release();

	m_EffectTechnique = m_pEffect->GetTechniqueByIndex(0);
	GCC_ASSERT(m_EffectTechnique && m_EffectTechnique->IsValid());

	m_EffectPass = m_EffectTechnique->GetPassByIndex(0);
	GCC_ASSERT(m_EffectPass && m_EffectPass->IsValid());	

	D3DX11_PASS_SHADER_DESC effectVsDesc;
	m_EffectPass->GetVertexShaderDesc(&effectVsDesc);
	D3DX11_EFFECT_SHADER_DESC effectVsDesc2;
	effectVsDesc.pShaderVariable->GetShaderDesc(effectVsDesc.ShaderIndex, &effectVsDesc2);
	const void *vsCodePtr = effectVsDesc2.pBytecode;
	unsigned vsCodeLen = effectVsDesc2.BytecodeLength;

    if (SUCCEEDED ( DXUTGetD3D11Device()->CreateInputLayout( D3D11VertexLayout_Position, ARRAYSIZE( D3D11VertexLayout_Position ), vsCodePtr, vsCodeLen, &m_pVertexLayout11 ) ) )
	{
	    DXUT_SetDebugName( m_pVertexLayout11, "Primary" );

		// Setup constant buffers
		D3D11_BUFFER_DESC Desc;
		Desc.Usage = D3D11_USAGE_DYNAMIC;
		Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
		Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		Desc.MiscFlags = 0;

		Desc.ByteWidth = sizeof( Vec4 );
		V_RETURN( DXUTGetD3D11Device()->CreateBuffer( &Desc, NULL, &m_pcbRenderTargetSize) );
		DXUT_SetDebugName( m_pcbRenderTargetSize, "Vec4_RenderTargetSize" );

		Desc.ByteWidth = sizeof( Mat4x4 );
		V_RETURN( DXUTGetD3D11Device()->CreateBuffer( &Desc, NULL, &m_pcbChangePerFrame ) );
		DXUT_SetDebugName( m_pcbChangePerFrame, "LineDrawerChangePerFrameBuffer" );

		Desc.ByteWidth = sizeof( Vec4 );
		V_RETURN( DXUTGetD3D11Device()->CreateBuffer( &Desc, NULL, &m_pcbDiffuseColor ) );
		DXUT_SetDebugName( m_pcbDiffuseColor, "DiffuseColor" );
	}

    SAFE_RELEASE( pVertexShaderBuffer );

	return S_OK;
}

//
// GameCode4_Hlsl_VertexShader::SetupRender					 
//
HRESULT LineDraw_Hlsl_Shader::SetupRender(Scene *pScene)
{
	HRESULT hr = S_OK;

	m_EffectPass->Apply(0, DXUTGetD3D11DeviceContext());

	DXUTGetD3D11DeviceContext()->IASetInputLayout( m_pVertexLayout11 );
	
	D3D11_MAPPED_SUBRESOURCE MappedResource;


	// ----- Render Target Size ------
    V( DXUTGetD3D11DeviceContext()->Map( m_pcbRenderTargetSize, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) );

	Vec4 * pRenderTargetSize = ( Vec4 * )MappedResource.pData;
	pRenderTargetSize->x = (FLOAT)DXUTGetWindowWidth();
	pRenderTargetSize->y = (FLOAT)DXUTGetWindowHeight();
	pRenderTargetSize->z = 0.0f;
	pRenderTargetSize->w = 0.0f;

	DXUTGetD3D11DeviceContext()->Unmap( m_pcbRenderTargetSize, 0 );

	// ----- Transform Matricies ------
    V( DXUTGetD3D11DeviceContext()->Map( m_pcbChangePerFrame, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) );

	LineDrawerChangePerFrameBuffer * pChangePerFrame = ( LineDrawerChangePerFrameBuffer* )MappedResource.pData;
	Mat4x4 mWorldViewProjection = pScene->GetCamera()->GetWorldViewProjection(pScene);
	D3DXMatrixTranspose( &pChangePerFrame->m_WorldViewProjection, &mWorldViewProjection );

	DXUTGetD3D11DeviceContext()->Unmap( m_pcbChangePerFrame, 0 );

	// ----- Constant Buffers -----

	ID3DX11EffectConstantBuffer* fxRenderTargetCB = m_pEffect->GetConstantBufferByName("cbRenderTarget")->AsConstantBuffer();
	ID3DX11EffectConstantBuffer* fxChangePerFrameCB = m_pEffect->GetConstantBufferByName("cbChangePerFrame")->AsConstantBuffer();
	ID3DX11EffectConstantBuffer* fxDiffuseCB = m_pEffect->GetConstantBufferByName("cbDiffuseColor")->AsConstantBuffer();

	fxRenderTargetCB->SetConstantBuffer(m_pcbRenderTargetSize);
	fxChangePerFrameCB->SetConstantBuffer(m_pcbChangePerFrame);
	fxDiffuseCB->SetConstantBuffer(m_pcbDiffuseColor);

	return S_OK;
}




// FUTURE WORK - Creating a component like architecture for C++ shader integration would be a good idea! 
// For example - a texture component like the one below is almost exactly line the one
// int the GameCode4_Hlsl_PixelShader - this could be factored into a single component.
HRESULT LineDraw_Hlsl_Shader::SetDiffuse(const std::string& textureName, const Color &color)
{
	m_textureResource = textureName;
	if (m_textureResource.length() > 0)
	{
		Resource resource(m_textureResource);
		shared_ptr<ResHandle> texture = g_pApp->m_ResCache->GetHandle(&resource);
		if (texture)
		{
			shared_ptr<D3DTextureResourceExtraData11> extra = static_pointer_cast<D3DTextureResourceExtraData11>(texture->GetExtra());
			SetTexture(extra->GetTexture(), extra->GetSampler());
		}
	}

	HRESULT hr;
	D3D11_MAPPED_SUBRESOURCE MappedResource;

	// ----- Diffuse Color ------
    V( DXUTGetD3D11DeviceContext()->Map( m_pcbDiffuseColor, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource ) );
	Vec4 * pDiffuseColor = ( Vec4* )MappedResource.pData;
	*pDiffuseColor = Vec4(color.r, color.g, color.b, color.a);
	DXUTGetD3D11DeviceContext()->Unmap( m_pcbDiffuseColor, 0 );

	return S_OK;
}

HRESULT LineDraw_Hlsl_Shader::SetTexture(ID3D11ShaderResourceView* const *pDiffuseRV, ID3D11SamplerState * const *ppSamplers)
{
	DXUTGetD3D11DeviceContext()->PSSetShaderResources( 0, 1, pDiffuseRV );
	DXUTGetD3D11DeviceContext()->PSSetSamplers( 0, 1, ppSamplers );
	return S_OK;
}	
以上就是网和着色器的实现,它们大大增强了游戏的画面效果,令游戏呈现出绚丽多彩的画面。下一篇关于光线投射和天空盒子 Raycast and Sky~~


游戏框架其九:网和着色器( Mesh and Shader )