游戏框架其九:灯光和材质( Lights and Material )

灯光和材质的实现如下:

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 ~~~

时间: 2024-11-05 10:58:00

游戏框架其九:灯光和材质( Lights and Material )的相关文章

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

网的重要作用可以导入3DMAX等创建的模型,到游戏中:着色器可以实现特定绚丽的效果.它们的实现如下 1. 网 Mesh的实现: #pragma once //======================================================================== // File: Mesh.h - classes to render meshes in D3D9 and D3D11 // 主要是导入3DMAX等软件生成的模型文件 基于Windows Dir

游戏框架其九:WASD方向控制 { MovementController }

下面实现的方向控制是基于键盘上的W A S D,来控制运动物体的方向的.下面是实现~ #pragma once //======================================================================== // File: MovementController.h 就是实现键盘按钮 WASD 的方向控制 //===================================================================

libgdx游戏框架介绍

libgdx作为上层为java,底层c和c++的游戏引擎.简直是优秀得一塌糊涂.  这个游戏框架最初只有1个人在维护,现在已经加入不少人了,越来越给力. libgdx的架构 很清晰, 我们先从包的结构分析: assets 代表资源包,用于资源加载等管理. audio 音频包,游戏需要播放声音时用. files 文件处理包,内部主要对象是FileHandle ,如果你用过Libgdx肯定对次很熟悉,libgdx加载纹理图片等都是通过此对象. graphics 绘画相关,就是我们要把游戏中的控件或者

Android游戏框架Libgdx使用入门

转载自:http://blog.csdn.net/cping1982/article/details/6176191 Libgdx作者博客:http://www.badlogicgames.com/ Libgdx项目地址:http://code.google.com/p/libgdx/ Libgdx是一款支持2D与3D游戏开发的游戏类库,兼容大多数微机平台(标准JavaSE实现,能执行在Mac.Linux.Windows等系统)与Android平台(Android1.5以上就可以使用.Andro

使用Html5+C#+微信 开发移动端游戏详细教程 :(三)使用html5引擎搭建游戏框架

教程里的案例我们是通过H5游戏引擎开发,目前H5的游戏引擎比较好用的是白鹭,不过对于新手来说白鹭的开发环境和工具使用过于复杂,这里推荐一个国内大神编写的游戏引擎:lufylegend. 直接在页面引入Js文件,就可以开发了,运行效率非常高效,语法是仿AS3语法,懂C#的人上手会很快. Lufylegend引擎具体的API和使用方法可以参考官网和论坛: http://www.lufylegend.com/api/zh_CN/out/classes/FPS.html 之前微信上有一款"怪兽必须死&q

JS写小游戏(一):游戏框架

前言 前一阵发现一个不错的网站,都是一些用html5+css+js写的小游戏,于是打算学习一番,写下这个系列博客主要是为了加深理解,当然也有一些个人感悟,如果英文好可以直接Click Here. 概述 一般,小游戏都要关注两个问题:刷新和交互.因为游戏一般是动态的,所以需要不断刷新.JavaScript是单线程,如果用C语言写过贪吃蛇之类的小游戏,应该知道,单线程一般是挂起一个时间来达到动态效果.比如C语言的Sleep(),JS的setInterval()等.但是js还有一种更高性能的方法req

【开源java游戏框架libgdx专题】-01-libgdx介绍

libgdx是一款开源的java游戏框架,而且还实现了Desktop/Android/BlackBerry/iOS/HTML5这些些平台的跨平台开发.官方网址:https://libgdx.badlogicgames.com/ 框架项目截图(Eclipse需要安装Gradle): libgdx项目采用工具自动生成项目(可以自己配置扩展): 原文由博主 乐智 编辑撰写,版权归博主所有. 原文地址 http://www.dtblog.cn/1086.html 转载请注明出处!

cocos2dx游戏开发——微信打飞机学习笔记(二)——游戏框架

一.游戏的基本框架: WelcomeScene    ——>    GameScene   ——>   GameOverScene ||                                       ||                                    || ∨                                      ∨                                   ∨ WelcomeLayer            

基于状态机的游戏框架

一 定义 有限状态机就是一个具有有限数量状态, 并且能够根据相应的操作从一个状态变换到另一个状态, 而在同一时刻只能处在一种状态下的智能体. 英文:Finite State Machine 简称:FSM 二 最简单的状态机 最简单的状态机:if-else 实际上if-else就是一个最有两种状态的状态机,分别是true和false 三 伪状态机 当两种情况不能满足我们的需求时,我们可以用if-else if -...-else, 不过,为了方便,我们可以使用switch-case代替 首先,定义