DirectX9:基础篇 第四章 光照
一.简介
二.灯光模型
1.环境光(Ambient Light)
环境光(Ambient Light):这种灯光将被其他所有表面反射且被用在照亮整个场景
2.漫射光(Diffuse Light)
漫反射(Diffuse Reflection):这种灯光按照特殊方向传播,当它照射到一个表面,它将在所有方向上均匀反射
3.镜面光(Specular Light)
镜面反射(Specular Reflection):这种灯光按照特殊方向传播,当它照射到一个表面,它会严格按照一个方向传播
镜面光默认是关闭的,要使用镜面光必须设置
1 2 | //开启镜面光反射计算 Device->SetRenderState(D3DRS_SPECULARENABLE, true ); |
三.灯光颜色
每一种灯光模型都是通过颜色结构体(D3DXCOLOR)或者颜色类(D3DCOLORVALUE)来绘制的
1 2 3 | 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)
1 2 3 4 5 6 7 8 9 10 11 12 | //只反射红光 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); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | // 全局材质 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)是描述多边形表面方向的一个向量
顶点法线能够确定灯光照射到物体表面的角度
1 2 3 4 5 6 7 8 9 10 | //在顶点结构中添加法线分量 struct Vertex { float _x, _y, _z; float _nx, _ny, _nz; static const DWORD FVF; } const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL; |
1 2 3 4 5 6 7 8 9 10 11 12 | // 通过三角形的三个顶点计算三角形的面法线 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
//表示仅用于聚光灯,指定了外部锥形的弧度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | //创建一个方向光源,沿着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.点光源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | #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.聚光灯
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #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 ; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)