DirectX9:基础篇 第四章 光照

一.简介

 

 

二.灯光模型

1.环境光(Ambient Light)

 环境光(Ambient Light):这种灯光将被其他所有表面反射且被用在照亮整个场景

 

2.漫射光(Diffuse Light)

漫反射(Diffuse Reflection):这种灯光按照特殊方向传播,当它照射到一个表面,它将在所有方向上均匀反射

 

3.镜面光(Specular Light)

镜面反射(Specular Reflection):这种灯光按照特殊方向传播,当它照射到一个表面,它会严格按照一个方向传播

镜面光默认是关闭的,要使用镜面光必须设置

 

//开启镜面光反射计算
Device->SetRenderState(D3DRS_SPECULARENABLE,true);

 

三.灯光颜色

每一种灯光模型都是通过颜色结构体(D3DXCOLOR)或者颜色类(D3DCOLORVALUE)来绘制的

 

D3DXCOLOR redAmbient(1.0f, 0.0f, 0.0f, 1.0f);
D3DXCOLOR blueDiffuse(0.0f, 0.0f, 1.0f, 1.0f);
D3DXCOLOR whiteSpecular(1.0f, 1.0f, 1.0f, 1.0f);

 

四.灯光材质

材质允许我们定义物体表面对各种颜色光的反射比例

 

//材质用结构体D3DMATERIAL9
typedef struct D3DMATERIAL9{
    D3DCOLORVALUE Diffuse;        
    D3DCOLORVALUE Ambient;      
    D3DCOLORVALUE Specular;       
    D3DCOLORVALUE Emissive;        
    float Power;                        
}D3DMATERIAL9,*LPD3DMATERIAL9;

 

  • Diffuse

    //指定材质对漫射光的反射率

  • Ambient

    //指定材质对环境光的反射率   

  • Specular

    //指定材质对镜面光的反射率

  • Emissive

    //用于增强物体的亮度

  • Power

    //指定镜面高光点的锐度(sharpness)

 

//只反射红光

D3DMATERIAL9 red;
::ZeroMemory(&red,sizeof(red));
red.Diffuse=D3DXCOLOR(1.0f,0.0f,0.0f,1.0f);  
red.Ambient=D3DXCOLOR(1.0f,0,0f,0.0f,1.0f);
red.Specular=D3DXCOLOR(1.0f,0.0f,0.0f,1.0f);
red.Emissive=D3DXCOLOR(0.0f,0.0f,0.0f,1.0f);
red.Power=5.0f;


Device->SetMaterial(&red);

 

 

// 全局材质

D3DMATERIAL9 d3d::InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR  e, float p)
{

    D3DMATERIAL9 mtrl;
    mtrl.Ambient = a;
    mtrl.Diffuse = d;
    mtrl.Specular = s;
    mtrl.Emissive = e;
    mtrl.Power = p;
    return mtrl;            
}

namespace d3d
{
    ...
    D3DMATERIAL9 InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p);

    const D3DMATERIAL9 WHITE_MTRL = InitMtrl(WHITE, WHITE, WHITE, BLACK, 8.0f);

    const D3DMATERIAL9 RED_MTRL = InitMtrl(RED, RED, RED, BLACK, 8.0f);

    const D3DMATERIAL9 GREEN_MTRL = InitMtrl(GREEN, GREEN, GREEN, BLACK, 8.0f);

    const D3DMATERIAL9 BLUE_MTRL = InitMtrl(BLUE, BLUE, BLUE, BLACK, 8.0f);

    const D3DMATERIAL9 YELLOW_MTRL = InitMtrl(YELLOW, YELLOW, YELLOW, BLACK, 8.0f);     
}

// IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9* pMaterial)

D3DMATERIAL9 blueMaterial;
Device->SetMaterial(&blueMaterial);
drawSphere();

 

 

五.顶点法线

面法线(face normal)是描述多边形表面方向的一个向量

顶点法线能够确定灯光照射到物体表面的角度

//在顶点结构中添加法线分量

struct Vertex {
    
    float _x, _y, _z;
    float _nx, _ny, _nz;
    static const DWORD FVF;
}

const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL;

 

// 通过三角形的三个顶点计算三角形的面法线

void ComputeNormal(D3DXVECTOR3* p0, D3DXVECTOR3* p1, D3DXVECTOR3* p2, D3DXVECTOR3* out)
{

    D3DXVECTOR3 u = *p1 - *p0;
    D3DXVECTOR3 v = *p2 - *p0;
    D3DXVec3Cross(out, &u, &v);
    D3DXVec3Normalize(out, out);
} 

Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);   

 

六.光源

1.点光源(Point lights)

该光源在世界坐标系中有固定的位置,并向所有的方向发射光线

2.方向光(Directional lights)

该光源没有位置信息,所发射的光线相互平行地沿某一特定方向传播

3.聚光灯(Spot lights)

这种类型的光源和手电筒类似,没有位置信息,其发射的光线呈锥形(conical shape)沿着特定方向传播.

该锥形有两个角度,一个是内部锥形,一个是外部锥形

4.D3DLIGHT9(光源类)

//光源用结构D3DLIGHT9来表示
typedef struct D3DLIGHT9{
D3DLIGHTTYPE Type;           
    D3DCOLORVALUE Diffuse;   
    D3DCOLORVALUE Specular;  
    D3DCOLORVALUE Ambient;  
    D3DVECTOR Position;            
    D3DVECTOR Direction;         
    float Range;                            
    float Falloff;                             
    float Attenuation0;                  
    float Attenuation1;
    float Attenuation2;
    float Theta;                         
    float Phi;                              
}D3DLIGHT9,*LPD3DLIGHT;

  • Type

    //表示光源类型:D3DLIGHT_POINT,D3DLIGHT_SPOT,D3DLIGHT_DIRECTIONAL

  • Diffuse

    //表示该光源所发出的漫射光的颜色

  • Specular

    //表示该光源所发出的镜面光的颜色

  • Ambient

    //表示该光源所发出的环境光的颜色

  • Position

    //表示用于描述光源在世界坐标系中位置的向量

  • Direction

    //表示一个描述光在世界坐标系

  • Range

      //表示最大光程,对于方向光无意义  

  • Falloff

      //表示仅用于聚光灯,表示光强(intensity) 

  • Attenuation0

     //Attenuation012表示光强随距离衰减的方式,仅用于点光源和聚光灯

  • Theta

    //表示仅用于聚光灯,指定内部锥形的弧度

  • Phi

   //表示仅用于聚光灯,指定了外部锥形的弧度

 

//创建一个方向光源,沿着x轴正方向照射白色灯光

namespace d3d
{
  ...
  D3DLIGHT9 InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color);
  D3DLIGHT9 InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color);
  D3DLIGHT9 InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color);
}

D3DLIGHT9 d3d::InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color)
{
  D3DLIGHT light;
  ::ZeroMemory(&light, sizeof(light));
  light.Type = D3DLIGHT_DIRECTIONAL;
  light.Ambient = *color * 0.4f;
  light.Diffuse = *color;
  light.Specular = *color * 0.6f;
  light.Direction = *direction;
  return light;
}

D3DXVECTOR3 dire(1.0f, 0.0f, 0.0f);
D3DXCOLOR c = d3d::WHITE;
D3DLIGHT9 dirLight = d3d::InitDirectionalLight(&dir, &c);

Device->SetLight(0, &light);
Device->LightEnable(0, true);

 

 

七.例子

1.点光源

#include "d3dUtility.h"

//
// Globals
//

IDirect3DDevice9* Device = 0;

const int Width = 640;
const int Height = 480;

ID3DXMesh* Objects[4] = {0, 0, 0, 0};
D3DXMATRIX Worlds[4];
D3DMATERIAL9 Mtrls[4];

//
// Framework Functions
//

bool Setup()
{
	//
	// Create objects
	//

	D3DXCreateTeapot(Device, &Objects[0], 0);
	D3DXCreateSphere(Device, 1.0f, 20, 20, &Objects[1], 0);
	D3DXCreateTorus(Device, 0.5f, 1.0f, 20, 20, &Objects[2], 0);
	D3DXCreateCylinder(Device, 0.5f, 0.5f, 2.0f, 20, 20, &Objects[3], 0);

	D3DXMatrixTranslation(&Worlds[0], 0.0f, 2.0f, 0.0f);
	D3DXMatrixTranslation(&Worlds[1], 0.0f, -2.0f, 0.0f);
	D3DXMatrixTranslation(&Worlds[2], -3.0f, 0.0f, 0.0f);
	D3DXMatrixTranslation(&Worlds[3], 3.0f, 0.0f, 0.0f);

	//
	// Setup the object's materials
	//

	Mtrls[0] = d3d::RED_MTRL;
	Mtrls[1] = d3d::BLUE_MTRL;
	Mtrls[2] = d3d::GREEN_MTRL;
	Mtrls[3] = d3d::YELLOW_MTRL;

	//
	// Setup a point light . Note that the point light is positioned at the origin
	//

	D3DXVECTOR3 pos(0.0f, 0.0f, 0.0f);
	D3DXCOLOR c = d3d::WHITE;
	D3DLIGHT9 point = d3d::InitPointLight(&pos, &c);

	//
	// Set and Enable the light
	//

	Device->SetLight(0, &point);
	Device->LightEnable(0, true);

	//
	// Set lighting related render states
	//

	Device->SetRenderState(D3DRS_NORMALIZENORMALS,true);
	Device->SetRenderState(D3DRS_SPECULARENABLE, false);

	//
	// Set the projection matrix
	//

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.25f,
		(float)Width / (float)Height,
		1.0f,
		1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}

void Cleanup()
{
	for (int i = 0; i < 4; i++)
		d3d::Release<ID3DXMesh*>(Objects[i]);
}

bool Display(float timeDelta)
{
	if (Device)
	{

		//
		// Update the scene : update camera position
		//

		static float angle = (3.0f * D3DX_PI) / 2.0f;
		static float height = 5.0f;

		if (::GetAsyncKeyState(VK_LEFT) & 0x8000f)
			angle -= 0.5f * timeDelta;

		if (::GetAsyncKeyState(VK_RIGHT) & 0x8000f)
			angle += 0.5f*timeDelta;

		if (::GetAsyncKeyState(VK_UP) & 0x8000f)
			height += 5.0f * timeDelta;

		if (::GetAsyncKeyState(VK_DOWN) & 0x8000f)
			height -= 5.0f * timeDelta;

		D3DXVECTOR3 position(cosf(angle) * 7.0f, height, sinf(angle) * 7.0f);
		D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
		D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
		D3DXMATRIX V;
		D3DXMatrixLookAtLH(&V, &position, &target, &up);

		Device->SetTransform(D3DTS_VIEW, &V);

		//
		// Draw the scene:
		//
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
		Device->BeginScene();

		for (int i = 0; i < 4; i++)
		{
			// set material and world matrix for in 
			Device->SetMaterial(&Mtrls[i]);
			Device->SetTransform(D3DTS_WORLD, &Worlds[i]);
			Objects[i]->DrawSubset(0);
		}

		Device->EndScene();
		Device->Present(0, 0, 0, 0);

	}
	return true;
}

 

 

2.方向光

 

3.聚光灯

#include "d3dUtility.h"

IDirect3DDevice9* Device = 0;

const int Width = 640;
const int Height = 480;

ID3DXMesh* Objects[4] = {0, 0, 0, 0};
D3DXMATRIX Worlds[4];
D3DMATERIAL9 Mtrls[4];

D3DLIGHT9 Spot;

bool Setup()
{
	D3DXCreateTeapot(Device, &Objects[0], 0);
	D3DXCreateSphere(Device, 1.0f, 20, 20, &Objects[1], 0);
	D3DXCreateTorus(Device, 0.5f, 1.0f, 20, 20, &Objects[2], 0);
	D3DXCreateCylinder(Device, 0.5f, 0.5f, 2.0f, 20, 20, &Objects[3], 0);

	D3DXMatrixTranslation(&Worlds[0], 0.0f, 2.0f, 0.0f);
	D3DXMatrixTranslation(&Worlds[1], 0.0f, -2.0f, 0.0f);
	D3DXMatrixTranslation(&Worlds[2], -3.0f, 0.0f, 0.0f);
	D3DXMatrixTranslation(&Worlds[3], 3.0f, 0.0f, 0.0f);

	D3DXMATRIX Rx;
	D3DXMatrixRotationX(&Rx, D3DX_PI * 0.5f);
	Worlds[3] = Rx * Worlds[3];

	Mtrls[0] = d3d::RED_MTRL;
	Mtrls[1] = d3d::BLUE_MTRL;
	Mtrls[2] = d3d::GREEN_MTRL;
	Mtrls[3] = d3d::YELLOW_MTRL;

	for (int i = 0; i < 4; i++)
		Mtrls[i].Power = 20.0f;

	D3DXVECTOR3 pos(0.0f, 0.0f, -5.0f);
	D3DXVECTOR3 dir(0.0f, 0.0f, 1.0f);
	D3DXCOLOR c = d3d::WHITE;
	Spot = d3d::InitSpotLight(&pos, &dir, &c);

	Device->SetLight(0, &Spot);
	Device->LightEnable(0, true);

	Device->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	Device->SetRenderState(D3DRS_SPECULARENABLE, true);

	D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
	D3DXMATRIX V;
	D3DXMatrixLookAtLH(&V, &position, &target, &up);
	Device->SetTransform(D3DTS_VIEW, &V);

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.5f,
		(float)Width / (float)Height,
		1.0f,
		1000.0f);

	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}

void Cleanup()
{
	for (int i = 0; i < 4; i++)
		d3d::Release<ID3DXMesh*> (Objects[i]);
}

bool Display(float timeDelta)
{
	if (Device)
	{

		static float angle = (3.0f * D3DX_PI) / 2.0f;

		if (::GetAsyncKeyState(VK_LEFT) & 0x8000f)
			Spot.Direction.x -= 0.5f * timeDelta;

		if (::GetAsyncKeyState(VK_RIGHT) & 0x8000f)
			Spot.Direction.x += 0.5f * timeDelta;

		if (::GetAsyncKeyState(VK_DOWN) & 0x8000f)
			Spot.Direction.y -= 0.5f * timeDelta;

		if (::GetAsyncKeyState(VK_UP) & 0x8000f)
			Spot.Direction.y += 0.5f * timeDelta;

		Device->SetLight(0, &Spot);
		Device->LightEnable(0, true);

		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
		Device->BeginScene();

		for (int i = 0; i < 4; i++)
		{
			Device->SetMaterial(&Mtrls[i]);
			Device->SetTransform(D3DTS_WORLD, &Worlds[i]);
			Objects[i]->DrawSubset(0);
		}

		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}

	return true;
}

 

转载于:https://www.cnblogs.com/k5bg/p/11096649.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值