光照

原创 2013年12月04日 22:47:25
1.光照的组成

为了增强所绘场景的真实感,我们可以为场景增加光照,使用光照时,我们无需自行指定顶点的颜色值,依据光源类型,材质,以及物体表面相对于光源的朝向,计算出每个顶点的颜色值,

光照由以下三种类型光组成,

环境光(Ambient Light)
这种类型的光经其它表面反射到物体表面,并照亮整个场景,例如,物体的一些部份被一定程度的照亮,但物体并没有处于光源的直接照射下,物体之所以会被照亮,是由于其它物体对光的反射,

漫射光(Diffuse Light)
这种类型的光沿着特定的方向传播,当它到达一些表面时,将沿着各个方向反射,由于漫射光沿所有方向均匀反射,无论从哪个方面观察,,表面亮度都是相同的,采用这种模形时,无须考虑观察者的位置,仅需考虑光传播的方向以及表面的朝向,

镜面光(Specular Light)
这种类型的光沿特定方向传播,当此类型光到达一个表面时,将严格地沿着另一个方向反射,从而形成只能在一定角度内才能观察到的高亮度照射,


每种光的结构都可以用结构D3DCOLORVALUE或是D3DXCOLOR来表示,描述光线的颜色时,D3DXCOLOR类中的Alpha值都将被忽略

2.材质

在现实世界中,我们观察到的物体的颜色是由该物体所反射的光的颜色决定的,例如,一个纯红色的球体,反射了全部的红色入射光,并吸收了所以非红色的光,所以该球体表现为红色,D3D通过定义物体的材质(materials)来模拟这种现像,材质允许我们定义物体表面上对种种颜色光的反射比例,

材质用结构D3DMATERIAL9表示

typedef struct D3DMATERIAL9
{
    D3DCOLORVALUE Diffuse; //指定材质对漫射光的反射率
    D3DCOLORVALUE Ambient; //指定材质对环境光的反射率
    D3DCOLORVALUE Specular;//指定材质对镜面光的反射率
    D3DCOLORVALUE Emissive;//用于增强物体的亮度,使之看起起来可以自己发光
    float Power;           //指定镜面高光点的锐度,值越大,高光点的锐度越大
}D3DMATERIAL9,*LPD3DMATERIAL9;

例如,假如有一个红色的球体,我们想将该球体的材质的属性定义只反射红色光,而吸走所有其它颜色的光,

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



如果用一个只能发出蓝色的光,来照射一个红色的球体,该物体无法被照亮,当一个物体吸收了所有光时,便呈现了黑色, 反之如果一个物体能够100%地反射红色光,绿色光,和蓝色光,它将呈成为白色



顶点结构中不含有材质属性,但我们必须对当前材质进行设定,下面这个函数可以用来对当前材质进行设定: IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9 *pMaterial)


3.顶点法线
    
    1.面法线
    2.顶点法线

4.光源

    1.点光源    
    2.方向光
    3.聚光灯

typedef struct D3DLIGHT9
{
    D3DLIGHTTYPE     Type;        //光源类型
    D3DCOLORVALUE     Diffuse;    //该光源所发出的漫射光的颜色
    D3DCOLORVALUE     Specular;    //该光源所发出的镜面光的颜色
    D3DCOLORVALUE     Ambient;    //该光源所发出的环境光的颜色
    D3DVECTOR    Position;    //用于描述光源在世界坐标系中位置的向量,对于方向光,该参数无意义
    D3DVECTOR    Direction;    //描述光在世界坐标系中传播方向的向量,对于点光源,该参数无意义
    float        Range;        //光在消亡前,所能达到的最大光程,该值的最大取值为,根号FLT_MAX
    float        Falloff;    //该类型仅用于聚光灯,该参数定义了光强从内锥到到外锥形的衰减方式,一般设1.0f
    float        Attenuation0;    //定义了光强随距离衰减的方式,0表示常量
    float        Attenuation1;    // 这个表示线性
    float        Attenuation2;    // 这个表示2次距离衰减系数,attenuation = 1/(a0+a1*D+a2*D*D)
    float        Theta;        //仅用于聚光灯,指定了内部锥形圆锥角,单位为弧度
    float        Phi;        //仅用于聚光灯,指定了外部锥形的圆锥角,单位为弧度
}D3DLIGHT9,*LPD3DLIGHT;

光源初始化完毕之后,我们需要在D3D所维护的一个光源内部列表中对所要使用的光源进行注册

g_pDeive->SetLight(0,&ligth);

g_pDevice->LightEnable(0,true);

下面代码简单示例
(1)启用光照
(2)为每个物体创建一种材质,并在绘制相应物体前应用设置该材质
(3)创建一种或多种光源,,设置并启用
(4)启用所有其余的光照状态,
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")

IDirect3D9 *g_pD3d = NULL;
IDirect3DDevice9 *g_pDevice= NULL;

IDirect3DVertexBuffer9 *g_pbuf = NULL;


struct Vertex{
	float x,y,z;
	float _nx,_ny,_nz;
	Vertex(){}
	Vertex(float x,float y,float z,float nx,float ny,float nz)
	{
		this->x = x;
		this->y = y;
		this->z = z;

		this->_nx = nx;
		this->_ny = ny;
		this->_nz = nz;
	}
	static const DWORD FVF;
};

const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL;

#define WHITE D3DCOLOR_XRGB(255,255,255)
#define BLACK D3DCOLOR_XRGB(0,0,0)
#define RED   D3DCOLOR_XRGB(255,0,0)
#define BLUE  D3DCOLOR_XRGB(0,0,255)
#define GREEN D3DCOLOR_XRGB(0,255,0)

#define _WHITE D3DCOLORVALUE() 

D3DMATERIAL9 InitMtrl(D3DXCOLOR a,	//Ambient
					  D3DXCOLOR d,	//Diffuse
					  D3DXCOLOR s,	//Specular
					  D3DXCOLOR e,	//Emissive
					  float p)		//Power
{
	D3DMATERIAL9 mtrl;
	mtrl.Ambient	= a;
	mtrl.Diffuse	= d;
	mtrl.Emissive	= e;
	mtrl.Specular	= s;
	mtrl.Power		= p;

	return mtrl;
}

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);


//方向光
D3DLIGHT9 InitDirectLight(D3DXVECTOR3 *dir,D3DXCOLOR* clr)
{
	D3DLIGHT9 light;
	ZeroMemory(&light,sizeof(light));

	light.Type      = D3DLIGHT_DIRECTIONAL;
	light.Ambient   = *clr * 0.4f;
	light.Diffuse   = *clr;
	light.Direction = *dir;
	light.Specular  = *clr * 0.6f;

	return light;
}



bool InitObject()
{

	g_pDevice->SetRenderState(D3DRS_LIGHTING,true);
	g_pDevice->CreateVertexBuffer(
		12 * sizeof(Vertex),
		D3DUSAGE_WRITEONLY,
		Vertex::FVF,
		D3DPOOL_MANAGED,
		&g_pbuf,
		0);

	Vertex *v;
	g_pbuf->Lock(0,0,(void**)&v,0);

	//front face
	v[0] = Vertex(-1.0f , 0.0f , -1.0f , 0.0f	 , 0.707f , -0.707f);
	v[1] = Vertex( 0.0f , 1.0f ,  0.0f , 0.0f	 , 0.707f , -0.707f);
	v[2] = Vertex( 1.0f , 0.0f , -1.0f , 0.0f	 , 0.707f , -0.707f);

	//left face
	v[3] = Vertex(-1.0f , 0.0f ,  1.0f , -0.707f , 0.707f , 0.0f);
	v[4] = Vertex( 0.0f , 1.0f ,  0.0f , -0.707f , 0.707f , 0.0f);
	v[5] = Vertex(-1.0f , 0.0f , -1.0f , -0.707f , 0.707f , 0.0f);

	//right face
	v[6] = Vertex( 1.0f , 0.0f , -1.0f , 0.707f	 , 0.707f , 0.0f);
	v[7] = Vertex( 0.0f , 1.0f ,  0.0f , 0.707f	 , 0.707f , 0.0f);
	v[8] = Vertex( 1.0f , 0.0f ,  1.0f , 0.707f	 , 0.707f , 0.0f);

	//back face
	v[9] = Vertex( 1.0f , 0.0f ,  1.0f , 0.0f	 , 0.707f , 0.707f);
   v[10] = Vertex( 0.0f , 1.0f ,  0.0f , 0.0f	 , 0.707f , 0.707f);
   v[11] = Vertex(-1.0f , 0.0f ,  1.0f , 0.0f	 , 0.707f , 0.707f);

   g_pbuf->Unlock();

   //材质
   D3DMATERIAL9 mtrl;
   mtrl = InitMtrl(WHITE,WHITE,WHITE,BLACK,5.0f);
   g_pDevice->SetMaterial(&mtrl);

   //光源
   D3DLIGHT9 light;
   D3DXVECTOR3 dir(1.0f,0.0f,0.0f);
   D3DXCOLOR clr = D3DCOLOR_XRGB(210,255,25);
   ZeroMemory(&light,sizeof(light));
   light = InitDirectLight(&dir,&clr);

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

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

   
   D3DXVECTOR3 pos(2.0f,2.0f,-1.0f);
   D3DXVECTOR3 tar(0.0f,0.0f,0.0f);
   D3DXVECTOR3 up( 0.0f,1.0f,0.0f);

   D3DXMATRIX _v;
   D3DXMatrixLookAtLH(&_v,&pos,&tar,&up);
   g_pDevice->SetTransform(D3DTS_VIEW,&_v);

   
   D3DXMATRIX proj;
   D3DXMatrixPerspectiveFovLH(&proj,D3DX_PI * 0.5f,
	   float(800)/float(600),
	   0.20f,100.0f);
   g_pDevice->SetTransform(D3DTS_PROJECTION,&proj);


	return true;
}


bool Initd3d(HWND hwnd)
{
	g_pD3d = Direct3DCreate9(D3D_SDK_VERSION);

	D3DDISPLAYMODE displaymode;
	ZeroMemory(&displaymode,sizeof(displaymode));
	g_pD3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displaymode);


	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp,sizeof(d3dpp));

	d3dpp.BackBufferHeight = 600;
	d3dpp.BackBufferWidth = 800;
	d3dpp.hDeviceWindow = hwnd;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.Windowed = TRUE;
//	d3dpp.BackBufferFormat = D3DFMT_A8B8G8R8;

	g_pD3d->CreateDevice(
		D3DADAPTER_DEFAULT,
		D3DDEVTYPE_HAL,
		hwnd,
		D3DCREATE_HARDWARE_VERTEXPROCESSING,
		&d3dpp,
		&g_pDevice);
	
	return true;
}

void RenderScene()
{
	g_pDevice->Clear(0,NULL,D3DCLEAR_TARGET ,0xffffffff,1.0f,0);

	g_pDevice->BeginScene();

	g_pDevice->SetFVF(Vertex::FVF);
	g_pDevice->SetStreamSource(0,g_pbuf,0,sizeof(Vertex));



	g_pDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,4);

	g_pDevice->EndScene();

	g_pDevice->Present(0,0,0,0);
}

void Shutdown()
{
	if(g_pD3d)
	{
		g_pD3d->Release();
	}
	if(g_pDevice)
	{
		g_pDevice->Release();
	}
	if(g_pbuf)
	{
		g_pbuf->Release();
	}
}




LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("Light");
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX   wndclassex = {0};
    wndclassex.cbSize        = sizeof(WNDCLASSEX);
    wndclassex.style         = CS_HREDRAW | CS_VREDRAW;
    wndclassex.lpfnWndProc   = WndProc;
    wndclassex.cbClsExtra    = 0;
    wndclassex.cbWndExtra    = 0;
    wndclassex.hInstance     = hInstance;
    wndclassex.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
    wndclassex.hCursor       = LoadCursor (NULL, IDC_ARROW);
    wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    wndclassex.lpszMenuName  = NULL;
    wndclassex.lpszClassName = szAppName;
    wndclassex.hIconSm       = wndclassex.hIcon;
	
    if (!RegisterClassEx (&wndclassex))
    {
        MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
        return 0;
    }
    hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, 
		                  szAppName, 
        		          TEXT ("WindowTitle"),
                		  WS_OVERLAPPEDWINDOW,
		                  CW_USEDEFAULT, 
        		          CW_USEDEFAULT, 
                		  800, 
		                  600, 
        		          NULL, 
                		  NULL, 
		                  hInstance,
        		          NULL); 
			
	//////////////////////////////////////////////////////////////////////////
	Initd3d(hwnd);
	InitObject();

    ShowWindow (hwnd, iCmdShow);
    UpdateWindow (hwnd);
    while (msg.message!=WM_QUIT)
    {
		if(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
		{
			TranslateMessage (&msg);
			DispatchMessage (&msg);
		}
		else
		{
			RenderScene();
		}
    }
	Shutdown();
    return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage (0);
        return (0);
    }
    return DefWindowProc (hwnd, message, wParam, lParam);
}









版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

光照(Lighting)

  • 2017-06-30 17:19
  • 692KB
  • 下载

OpenGL编程指南-光照

OpenGL通过光源、材料和光照模型,渲染光照物体,模拟现实世界1.光源1.创建光源 OpenGL至少支持8个光源,即GL_LIGHT0到GL_LIGHT7,可以使用glEnable开启光源 2....

球体的光照渲染

1602显示光照强度

2015年完美讲课的PPT拿出来分享-Unity 5 光照模型解析

2015年完美讲课的PPT拿出来分享,希望对想了解unity图形这块的同学有所帮助!

Unity Shader Example 8 (光照贴图)

Shader "LightMap" { Properties { _Color ("Main Color", Color) = (1, 1, 1, 1) _Ma...

Bezier曲面及光照阴影

  • 2014-12-01 23:02
  • 30.62MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)