DirectX 入门[04] 创建和使用光照

    技术2022-05-11  121

    原文在MS DirectX的帮助文档中:        DirectX Graphics ->Direct3D 9 ->Tutorials and Samples->Tutorials->Direct3D Tutorials        ->Tutorial 4: Creating and Using Lights

            翻译本文主要为了记录自己的学习过程, 并希望能结交一些学习DirectX的朋友. 由于该指南是在前三个指南的基础上编写的, 之前阅读后没有及时把内容翻译下来, 以后陆续补上.

            由于英文水平很菜有些语句翻译不准确, 各位看了见谅, 如果有错误和不足之处欢迎指出.   (翻译中有些语句我已经省去, 并加入了一些注释, 为了养成一些习惯我对代码进行了一点点地修改.)

     

    正文:

            Direct3D光照使3D对象的真实感大大增加。当使用光照,场景中每一个几何对象将根据其位置和使用的光照类型被照亮。本例子介绍光照和材质两个话题。

    代码路径: ( SDK root)/Samples/C++/Direct3D/Tutorials/Tut04_Lights 步骤1 -- 初始化场景中的几何体        使用光照其中一个要求是每一个平面必须具有法线。因此,光照程序中使用与以往不同的顶点结构类型。新定义的顶点结构具有3D坐标和平面法线。平面法线用于Direct3D内部的光照计算。 struct CUSTOMVERTEX {     D3DXVECTOR3 position;  //3D顶点坐标向量     D3DXVECTOR3 normal;    //顶点所在平面的法线向量 }; //自定义自由顶点格式(FVF) #define D3DFVF_CUSTOMVERTEX      (D3DFVF_XYZ | D3DFVF_NORMAL)          定义了正确的顶点格式后,光照例子程序调用应用程序定义用于创建圆筒的函数InitGeometry。首先需要创建顶点缓冲存储存储圆筒的顶点。 //创建顶点缓冲, g_pVB为顶点缓冲的接口指针 IDirect3DVertexBuffer9* If(FAILED(g_pd3dDevice->CreateVertexBuffer(50*2*sizeof( CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX), D3DPOOL_DEFAULT, &g_pVB, NULL) )     return E_FAIL;   下一步需要用圆筒的顶点数据填充顶点缓冲,注意以下代码,对每一个顶点计算其坐标与法线向量。   CUSTOMVERTEX* pVertices; if( FAILED(g_pVB->Lock(0, 0, (void**)&pVertices, 0) ) )         return E_FAIL;           //sin(x+y) = sin(x)*cos(y) + cos(x)*sin(y);      //cos(x+y) = cos(x)*cos(y) - sin(x)*sin(y);     FLOAT fDelta = (FLOAT)(2*D3DX_PI/(50-1));     FLOAT fDeltaSin = sinf(fDelta);     FLOAT fDeltaCos = cosf(fDelta);     FLOAT fSin = 0.0f;     FLOAT fCos = 1.0f;     FLOAT fTmpSin = 0.0f;     for(DWORD i=0; i<49; i++)     {        pVertices[i<<1].position = D3DXVECTOR3(fSin, -1.0f, fCos);        pVertices[i<<1].normal = D3DXVECTOR3(fSin, 0.0f, fCos);        pVertices[(i<<1)+1].position = D3DXVECTOR3(fSin, 1.0f, fCos);        pVertices[(i<<1)+1].normal = D3DXVECTOR3(fSin, 0.0f, fCos);        fTmpSin = fSin;        fSin = fSin * fDeltaCos + fCos * fDeltaSin;        fCos = fCos * fDeltaCos - fTmpSin * fDeltaSin;     }     //防止出现累计误差     pVertices[98].position = D3DXVECTOR3(fSin, -1.0f, fCos);     pVertices[98].normal = D3DXVECTOR3(fSin, 0.0f, fCos);     pVertices[99].position = D3DXVECTOR3(0.0f, 1.0f, 1.0f);     pVertices[99].normal = D3DXVECTOR3(0.0f, 0.0f, 1.0f);        使用圆筒坐标填充顶点缓冲后,即可使用它进行渲染。但是,在渲染圆筒之前首先要设定场景中的材质与光源。   步骤二 --- 设置材质与光源        在Direct3D中使用光照,你需要创建一个或多个光源。要决定几何物体反射的颜色,你需要创建用于渲染几何物体的材质。渲染场景之前,光照程序调用设置材质和方向光源的函数SetupLights。   创建材质:        材质规定几何物体表面受到光照时反射的颜色。下段代码使用D3DMATERIAL9结构创建一个黄色的材质。 D3DMATERIAL9 material; ZeroMemory(&material, sizeof( D3DMATERIAL9));     material.Diffuse.r = material.Ambient.r = 1.0f;     material.Diffuse.g = material.Ambient.g = 1.0f;     material.Diffuse.b = material.Ambient.b = 0.0f;     material.Diffuse.a = material.Ambient.a = 1.0f; g_pd3dDevice->SetMaterial( &material ); 将材质的漫反射色和环境色设置为黄色。调用SetMaterial函数将该材质用于Direct3D设备的场景渲染。SetMaterial函数仅接受待设置材质的地址作为参数。调用该函数后,每一个图元使用刚设定的材质进行渲染,直到下一次调用SetMaterial指定不同的材质。(因此,如果场景中包含多个不同材质的几何体时,需要将几何体按材质归类后进行渲染。)   创建光源:        Direct3D中具有三种可用的光源类型: l         点光源 l         方向光源 l         聚光灯 此例子三创建一个方向光源(光线方向一致),改代码使得光源方向随时间不断调整。 下一段代码使用D3DLIGHT9结构创建一个方向光源。 D3DXVECTOR3    vecDir; D3DLIGHT9     light; ZeroMemory(&light, sizeof(D3DLIGHT9)); light.Type = D3DLIGHT_DIRECTIONAL;      //光源类型:方向光源 light.Diffuse.r = 1.0f;      //设置光源漫反射色为白色。R, G, B取值[0.0f,1.0f] light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; //设置光源方向 vecDir = D3DXVECTOR3( cosf(timeGetTime()/360.0f), 0.0f, sinf(timeGetTime()/360.0f) ); //归一化方向向量 D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir ); light.Range = 1000.0f;           //设置光源能照射到的最远距离 调用D3DXVec3Normalize归一化指定光源方向的向量。 光照范围指定该方向光源光照能影响的最远距离。此成员不影响方向光源。 下面的代码调用SetLight设置光源。 g_pd3dDevice->SetLight(0, TRUE); SetLight函数的第一个参数指定光源索引,(注意:如果该索引相关光源已存在,调用该函数将用新的光源覆盖原有的光源。)第二个参数指定定义该光源的结构指针。 下面代码开启0号光源。 g_pd3dDevice->LightEnable(0, TRUE); LightEnable函数第一个参数指定光源索引,第二个参数指定开启光源(TRUE)或关闭光源(FALSE)。 下面代码调用Direct3D设备接口的SetRenderState方法开启光照计算。 g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE); SetRenderState函数第一个参数为需要改变设备状态变量,第二个参数设置该状态的值。 最后再次调用SetRenderState开启环境光(环境光使场景中每一个物体接受相同环境光照)。 g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x00202020); 上面的代码为场景设置灰色的环境光。  

    最新回复(0)