• Direct3D光照系统


    光照系统用于增强场景的真实感,描述实体的形状和立体感,启用光照系统后,Direct3D会根据材质,光源属性等信息自动计算每个顶点的颜色值,使绘制结果更加逼真

    1. 光照的类型

    • Direct3D的光照模型中,光源的光由以下三个分量组成
      • 环境光(Ambient),用于模拟未处于光源直射时,照亮物体表面的反射光
      • 散射光(Diffuse),这类光到达物体表面后,将沿各方向均匀反射
      • 镜面光(Specular),这类光沿特定方向传播,到达一个表面后,严格按照另一个方向反射,形成在某个特定范围内可见的高光区域
    • Direct3D的各类光都可用D3DCOLORVALUE或D3DXCOLOR表示,使用D3DXCOLOR表示时,其中alpha值会被忽略

    2. 材质

    材质用于定义物体表面对各类光的反射比例,由结构D3DMATERIAL9表示

    typedef struct D3DMATERIAL9
    {
    	D3DCOLORVALUE Diffuse;
    	D3DCOLORVALUE Ambient;
    	D3DCOLORVALUE Specular;
    	D3DCOLORVALUE Emissive;
    	float power;
    }D3DMATERIAL9, *LPD3DMATERIAL9;
    //Emissive设置了物体的自发光属性,power指定了高光点的锐度
    

    3. 顶点法线

    Direct3D通过顶点法线计算光纤到达表面时的入射角并进一步计算光照,由于一个顶点常常被若干平面共享,因此,常采用计算所属各面法线平均值的方法来计算顶点法线

    //顶点顺时针绕序和逆时针绕序所计算出的法线方向相反
    void calcNormal(D3DXVECTOR3 *p0,
    				D3DXVECTOR3 *p1,
    				D3DXVECTOR3 *p2,
    				D3DXVECTOR3 result)
    {
    	D3DXVECTOR3 u = *p1 - *p0;
    	D3DXVECTOR3 v = *p2 - *p0;
    
    	D3DXVec3Cross(out, &u, &v);
    	D3DXVec3Normalize(out, out);
    }
    
    • 共享顶点的顶点法线
      (vec{v_{n}} = frac{1}{n}left ( vec{n_{0}} + vec{n_{1}} + cdots + vec{n_{n}} ight ))
    • 由于在变换过程中,顶点法线有可能不再是规范化的,因此最好将绘制状态设置为在变化完成后规范化所有法线
    Device->SetRenderStaes(D3DRS_NORMALIZENORMALS, true);
    

    4. 光源

    Direct3D支持三种类型的光源

    • 点光源(D3DLIGHT_POINT):除了基本的光照信息,只有位置信息,向所有方向均匀发出光线
    • 方向光(D3DLIGHT_DIRECTIONAL):没有位置信息,只有方向信息,发出的光沿该方向平行传播
    • 聚光灯(D3DLIGHT_SPOT):三种光源中最复杂的,与电筒类似,有位置信息,方向信息,还有附加的角度信息,描述光锥的角度
    • 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;
    
    • 三个Attenuation参数描述了光强随距离衰减的方式,仅用于点光源和聚光灯,具体计算公式为
      (attenuation = frac{1}{A_{0} + A_{1}cdot D + A_{2} cdot D^{2}})

    5. 实例

    方向光
    //Setup light
    	D3DLIGHT9 light1;
    	::ZeroMemory(&light1, sizeof(light1));
    	light1.Type = D3DLIGHT_DIRECTIONAL;
    	light1.Ambient = WHITE * 0.3f;
    	light1.Diffuse = RED;
    	light1.Specular = WHITE * 0.7f;
    	light1.Direction ={ 1.0f, 0.0f, 0.0f };
    
    	pD3DDEV->SetLight(0, &light1);
    	pD3DDEV->LightEnable(0, true
    
    • 效果
      Directional_Light
    点光源
    //Set Light position
    		float posinit = 0.0f;
    		D3DXMATRIX position = (&posinit);
    		position._11 = 3.0f;
    		position._22 = 3.0f;
    		position._33 = 3.0f;
    		D3DXMATRIX rotate;
    
    		static float y = 0.0f;
    		D3DXMatrixRotationY(&rotate, y);
    		y += DeltaTime;
    
    		//Set Light
    		D3DLIGHT9 lt;
    		::ZeroMemory(&lt, sizeof(lt));
    		lt.Type = D3DLIGHT_POINT;
    		lt.Ambient = WHITE * 0.3f;
    		lt.Diffuse = RED;
    		lt.Specular = WHITE * 0.7f;
    		lt.Range = 100.0f;
    		lt.Attenuation0 = 1.0f;
    		lt.Attenuation1 = 0.0f;
    		lt.Attenuation2 = 0.0f;
    
    		lt.Position = D3DXVECTOR3(position._11 * sinf(y), position._22 , position._33* cosf(y));
    
    		pD3DDEV->SetLight(0, &lt);
    		pD3DDEV->LightEnable(0, true);
    
    • 效果
      Point Light
    聚光灯
    //Set Light
    		D3DLIGHT9 light;
    		static float posx = 0.0f;
    		static float posy = 0.0f;
    		D3DXVECTOR3 dir = D3DXVECTOR3(posx, posy, 1.0f);
    
    		light.Type = D3DLIGHT_SPOT;
    		light.Ambient = WHITE * 0.3f;
    		light.Diffuse = RED;
    		light.Specular = WHITE * 0.7f;
    		light.Attenuation0 = 1.0f;
    		light.Attenuation1 = 0.0f;
    		light.Attenuation2 = 0.0f;
    		light.Position = D3DXVECTOR3(0.0f, 0.0f, -3.0f);
    		light.Falloff = 5.0f;
    		light.Range = 100.0f;
    		light.Phi = D3DX_PI / 2.5;
    		light.Theta = D3DX_PI / 45;
    		if( ::GetAsyncKeyState(VK_LEFT) & 0x8000f )
    			posx -= 0.5f * DeltaTime;
    		if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f )
    			posx += 0.5f * DeltaTime;
    		if( ::GetAsyncKeyState(VK_UP) & 0x8000f )
    			posy += 0.5f * DeltaTime;
    		if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f )
    			posy -= 0.5f * DeltaTime;
    		light.Direction = dir;
    
    		pD3DDEV->SetLight(0, &light);
    		pD3DDEV->LightEnable(0, true);
    
    • 效果
      Spot Light

    Written with StackEdit.

  • 相关阅读:
    MVC 和 MVVM
    Objective-C对象模型及应用
    面试总汇二
    iOS中常用的四种数据持久化方法简介
    iOS应用程序生命周期
    SDWebImage的总结
    面试知识点总汇
    block 的演练和使用
    Java 类 生成数据库表
    sql中写标量函数生成大写拼音首字母
  • 原文地址:https://www.cnblogs.com/current/p/4006605.html
Copyright © 2020-2023  润新知