燈光和材質的實現如下:
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;
}
下一篇是網 Mesh 和 着色器 Shader ~~~