灯光和材质的实现如下:
1. 灯光
#pragma once //========================================================================= // Lights.h - implements a simple light class for the scene graph //========================================================================= #include "D3DRenderer.h" #include "Geometry.h" #include "Scene.h" #include "SceneNodes.h" // 光的颜色刚好反映在材质上面 // Note: Light color is stored in the Material structure, which is already present in all SceneNodes. // // struct LightProperties // struct LightProperties { float m_Attenuation[3]; /* Attenuation coefficients 衰减系数 */ float m_Range; /* 光照范围 */ float m_Falloff; float m_Theta; float m_Phi; }; // // class LightNode // // Note: In the book this class implements the LightNode in D3D11, but here it is a base // class. The derived classes make it possible to run the engine in D3D9 or D3D11. // typedef unsigned int ActorId; typedef unsigned int GameViewId; typedef D3DXCOLOR Color; typedef unsigned int DWORD; typedef unsigned char BYTE; #define GCC_NEW new enum HRESULT { E_INVALIDARG, E_FAIL, S_OK, }; class LightNode : public SceneNode { protected: LightProperties m_LightProps; public: LightNode(const ActorId actorId, WeakBaseRenderComponentPtr renderComponent, const LightProperties &props, const Mat4x4 *t); }; class D3DLightNode9 : public LightNode { public: D3DLightNode9(const ActorId actorId, WeakBaseRenderComponentPtr renderComponent, const LightProperties &lightProps, const Mat4x4 *t) : LightNode(actorId, renderComponent, lightProps, t) { } D3DLIGHT9 m_d3dLight9; virtual HRESULT VOnRestore(Scene *pScene); virtual HRESULT VOnUpdate(Scene *, DWORD const elapsedMs); }; class D3DLightNode11 : public LightNode { public: D3DLightNode11(const ActorId actorId, WeakBaseRenderComponentPtr renderComponent, const LightProperties &lightProps, const Mat4x4 *t) : LightNode(actorId, renderComponent, lightProps, t) { } virtual HRESULT VOnRestore() { return S_OK; }; virtual HRESULT VOnUpdate(Scene *, DWORD const elapsedMs); }; struct ConstantBuffer_Lighting; // // class LightManager // class LightManager { friend class Scene; protected: Lights m_Lights; Vec4 m_vLightDir[MAXIMUM_LIGHTS_SUPPORTED]; Color m_vLightDiffuse[MAXIMUM_LIGHTS_SUPPORTED]; Vec4 m_vLightAmbient; public: void CalcLighting(Scene *pScene); void CalcLighting(ConstantBuffer_Lighting* pLighting, SceneNode *pNode); int GetLightCount(const SceneNode *node) { return m_Lights.size(); } const Vec4 *GetLightAmbient(const SceneNode *node) { return &m_vLightAmbient; } const Vec4 *GetLightDirection(const SceneNode *node) { return m_vLightDir; } const Color *GetLightDiffuse(const SceneNode *node) { return m_vLightDiffuse; } };
//========================================================================= // Lights.h - implements a simple light class for the GameCode4 scene graph //========================================================================= #include "GameCodeStd.h" #include "GameCode.h" #include "RenderComponent.h" #include "Lights.h" LightNode::LightNode(const ActorId actorId, WeakBaseRenderComponentPtr renderComponent, const LightProperties &props, const Mat4x4 *t) : SceneNode(actorId, renderComponent, RenderPass_NotRendered, t) { m_LightProps = props; } HRESULT D3DLightNode9::VOnRestore(Scene *pScene) { ZeroMemory( &m_d3dLight9, sizeof(D3DLIGHT9) ); m_d3dLight9.Type = D3DLIGHT_DIRECTIONAL; // These parameters are constant for the list after the scene is loaded m_d3dLight9.Range = m_LightProps.m_Range; m_d3dLight9.Falloff = m_LightProps.m_Falloff; m_d3dLight9.Attenuation0 = m_LightProps.m_Attenuation[0]; m_d3dLight9.Attenuation1 = m_LightProps.m_Attenuation[0]; m_d3dLight9.Attenuation2 = m_LightProps.m_Attenuation[0]; m_d3dLight9.Theta = m_LightProps.m_Theta; m_d3dLight9.Phi = m_LightProps.m_Phi; return S_OK; } HRESULT D3DLightNode9::VOnUpdate(Scene *, DWORD const elapsedMs) { // light color can change anytime! Check the BaseRenderComponent! LightRenderComponent* lrc = static_cast<LightRenderComponent*>(m_RenderComponent); m_Props.GetMaterial().SetDiffuse(lrc->GetColor()); m_d3dLight9.Diffuse = m_Props.GetMaterial().GetDiffuse(); float power; Color spec; m_Props.GetMaterial().GetSpecular(spec, power); m_d3dLight9.Specular = spec; m_d3dLight9.Ambient = m_Props.GetMaterial().GetAmbient(); m_d3dLight9.Position = GetPosition(); m_d3dLight9.Direction = GetDirection(); return S_OK; } HRESULT D3DLightNode11::VOnUpdate(Scene *, DWORD const elapsedMs) { // light color can change anytime! Check the BaseRenderComponent! LightRenderComponent* lrc = static_cast<LightRenderComponent*>(m_RenderComponent); m_Props.GetMaterial().SetDiffuse(lrc->GetColor()); return S_OK; } // // LightManager::CalcLighting // void LightManager::CalcLighting(Scene *pScene) { // FUTURE WORK: There might be all kinds of things you'd want to do here for optimization, especially turning off lights on actors that can't be seen, etc. pScene->GetRenderer()->VCalcLighting(&m_Lights, MAXIMUM_LIGHTS_SUPPORTED); int count = 0; GCC_ASSERT(m_Lights.size() < MAXIMUM_LIGHTS_SUPPORTED); for(Lights::iterator i=m_Lights.begin(); i!=m_Lights.end(); ++i, ++count) { shared_ptr<LightNode> light = *i; if (count==0) { // Light 0 is the only one we use for ambient lighting. The rest are ignored in the simple shaders used for GameCode4. Color ambient = light->VGet()->GetMaterial().GetAmbient(); m_vLightAmbient = D3DXVECTOR4(ambient.r, ambient.g, ambient.b, 1.0f); } Vec3 lightDir = light->GetDirection(); m_vLightDir[count] = D3DXVECTOR4(lightDir.x, lightDir.y, lightDir.z, 1.0f); m_vLightDiffuse[count] = light->VGet()->GetMaterial().GetDiffuse(); } } void LightManager::CalcLighting(ConstantBuffer_Lighting* pLighting, SceneNode *pNode) { int count = GetLightCount(pNode); if (count) { pLighting->m_vLightAmbient = *GetLightAmbient(pNode); memcpy(pLighting->m_vLightDir, GetLightDirection(pNode), sizeof( Vec4 ) * count ); memcpy(pLighting->m_vLightDiffuse, GetLightDiffuse(pNode), sizeof( Vec4 ) * count); pLighting->m_nNumLights = count; } }2. 材质
#pragma once //============================================================================== // File: Material.h - stores texture and material information for D3D9 and D3D11 //============================================================================== // class Material #include "Geometry.h" #include "ResCache.h" class Material { D3DMATERIAL9 m_D3DMaterial;// This structure stores diffuse,ambient,specular,emissive,power. public: Material(); void SetAmbient(const Color &color); const Color GetAmbient() { return m_D3DMaterial.Ambient; } void SetDiffuse(const Color &color); const Color GetDiffuse() { return m_D3DMaterial.Diffuse; } void SetSpecular(const Color &color, const float power); void GetSpecular(Color &_color, float &_power) { _color = m_D3DMaterial.Specular; _power = m_D3DMaterial.Power; } void SetEmissive(const Color &color); const Color GetEmissive() { return m_D3DMaterial.Emissive; } void SetAlpha(const float alpha); bool HasAlpha() const { return GetAlpha() != fOPAQUE; } float GetAlpha() const { return m_D3DMaterial.Diffuse.a; } void D3DUse9(); }; // // class D3DTextureResourceExtraData9, also see D3DTextureResourceExtraData11 // class D3DTextureResourceExtraData9 : public IResourceExtraData { friend class TextureResourceLoader; public: D3DTextureResourceExtraData9(); virtual ~D3DTextureResourceExtraData9() { SAFE_RELEASE(m_pTexture); } virtual std::string VToString() { return "D3DTextureResourceExtraData9"; } LPDIRECT3DTEXTURE9 const GetTexture() { return m_pTexture; } protected: LPDIRECT3DTEXTURE9 m_pTexture; }; // // class D3DTextureResourceExtraData11 // class D3DTextureResourceExtraData11 : public IResourceExtraData { friend class TextureResourceLoader; public: D3DTextureResourceExtraData11(); virtual ~D3DTextureResourceExtraData11() { SAFE_RELEASE(m_pTexture); SAFE_RELEASE(m_pSamplerLinear); } virtual std::string VToString() { return "D3DTextureResourceExtraData11"; } ID3D11ShaderResourceView * const *GetTexture() { return &m_pTexture; } ID3D11SamplerState * const *GetSampler() { return &m_pSamplerLinear; } protected: ID3D11ShaderResourceView *m_pTexture; ID3D11SamplerState* m_pSamplerLinear; }; // // class TextureResourceLoader // class TextureResourceLoader : public IResourceLoader { public: virtual bool VUseRawFile() { return false; } virtual bool VDiscardRawBufferAfterLoad() { return true; } virtual unsigned int VGetLoadedResourceSize(char *rawBuffer, unsigned int rawSize); virtual bool VLoadResource(char *rawBuffer, unsigned int rawSize, shared_ptr<ResHandle> handle); };
//================================================================================ // File: Material.cpp - stores texture and material information for D3D9 and D3D11 //================================================================================ #include "GameCodeStd.h" #include "GameCode.h" #include "ResCache.h" #include "SceneNodes.h" //////////////////////////////////////////////////// // class Material //////////////////////////////////////////////////// Material::Material() { ZeroMemory( &m_D3DMaterial, sizeof( D3DMATERIAL9 ) ); m_D3DMaterial.Diffuse = g_White; m_D3DMaterial.Ambient = Color(0.10f, 0.10f, 0.10f, 1.0f); m_D3DMaterial.Specular = g_White; m_D3DMaterial.Emissive = g_Black; } void Material::SetAmbient(const Color &color) { m_D3DMaterial.Ambient = color; } void Material::SetDiffuse(const Color &color) { m_D3DMaterial.Diffuse = color; } void Material::SetSpecular(const Color &color, const float power) { m_D3DMaterial.Specular = color; m_D3DMaterial.Power = power; } void Material::SetEmissive(const Color &color) { m_D3DMaterial.Emissive = color; } void Material::SetAlpha(float alpha) { m_D3DMaterial.Diffuse.a = alpha; } void Material::D3DUse9() { DXUTGetD3D9Device()->SetMaterial( &m_D3DMaterial ); } // // class DdsResourceLoader - creates an interface with the Resource cache to load DDS files // class DdsResourceLoader : public TextureResourceLoader { public: virtual std::string VGetPattern() { return "*.dds"; } }; shared_ptr<IResourceLoader> CreateDDSResourceLoader() { return shared_ptr<IResourceLoader>(GCC_NEW DdsResourceLoader()); } // // class JpgResourceLoader - creates an interface with the Resource cache to load JPG files // class JpgResourceLoader : public TextureResourceLoader { public: virtual std::string VGetPattern() { return "*.jpg"; } }; shared_ptr<IResourceLoader> CreateJPGResourceLoader() { return shared_ptr<IResourceLoader>(GCC_NEW JpgResourceLoader()); } D3DTextureResourceExtraData9::D3DTextureResourceExtraData9() : m_pTexture(NULL) { } D3DTextureResourceExtraData11::D3DTextureResourceExtraData11() : m_pTexture(NULL), m_pSamplerLinear(NULL) { } unsigned int TextureResourceLoader::VGetLoadedResourceSize(char *rawBuffer, unsigned int rawSize) { // This will keep the resource cache from allocating memory for the texture, so DirectX can manage it on it's own. return 0; } // // TextureResourceLoader::VLoadResource // bool TextureResourceLoader::VLoadResource(char *rawBuffer, unsigned int rawSize, shared_ptr<ResHandle> handle) { GameCodeApp::Renderer renderer = GameCodeApp::GetRendererImpl(); if (renderer == GameCodeApp::Renderer_D3D9) { shared_ptr<D3DTextureResourceExtraData9> extra = shared_ptr<D3DTextureResourceExtraData9>(GCC_NEW D3DTextureResourceExtraData9()); if ( FAILED ( D3DXCreateTextureFromFileInMemory( DXUTGetD3D9Device(), rawBuffer, rawSize, &extra->m_pTexture ) ) ) return false; else { handle->SetExtra(shared_ptr<D3DTextureResourceExtraData9>(extra)); return true; } } else if (renderer == GameCodeApp::Renderer_D3D11) { shared_ptr<D3DTextureResourceExtraData11> extra = shared_ptr<D3DTextureResourceExtraData11>(GCC_NEW D3DTextureResourceExtraData11()); // Load the Texture if ( FAILED ( D3DX11CreateShaderResourceViewFromMemory( DXUTGetD3D11Device(), rawBuffer, rawSize, NULL, NULL, &extra->m_pTexture, NULL ) ) ) return false; // Create the sample state D3D11_SAMPLER_DESC sampDesc; ZeroMemory( &sampDesc, sizeof(sampDesc) ); sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampDesc.MinLOD = 0; sampDesc.MaxLOD = D3D11_FLOAT32_MAX; if( FAILED( DXUTGetD3D11Device()->CreateSamplerState( &sampDesc, &extra->m_pSamplerLinear ) ) ) return false; handle->SetExtra(shared_ptr<D3DTextureResourceExtraData11>(extra)); return true; } GCC_ASSERT(0 && "Unsupported Renderer in TextureResourceLoader::VLoadResource"); return false; }
游戏框架其九:灯光和材质( Lights and Material )
原文:http://blog.csdn.net/wanghexu09008126/article/details/39941183