zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    AtCoder Regular Contest 061
    Codeforces Round #370 (Div. 2)
    2016 ACM/ICPC Asia Regional Dalian Online
    HDU 5513 Efficient Tree
    Codeforces Round #104 (Div. 1)
    2016 Hunan Province Programming Contest
    2016 Multi-University Training Contest 7
    2016中国大学生程序设计竞赛
    聚会「AHOI 2008」
    游戏「AHOI / HNOI2018」
  • 原文地址:https://www.cnblogs.com/k5bg/p/11096649.html
Copyright © 2011-2022 走看看