D3D中光源可大致分为3种,点光源,方向光,环境光

1)

可以大致对应我们生活中的 电灯泡,太阳光,环境光。通过抽象各种光的性质,我们可以使用结构体Light,以更方便地表示光。

光可以定义如下

Struct Light
{
  D3DXVECTOR3 pos;//位置
  D3DXVECTOR3 dir;//方向
  D3DXCOLOR ambiet;//环境光颜色
  D3DXCOLOR diffuse;//漫反射颜色
  D3DXCOLOR specular;//镜面反射颜色
  float      power;//光强

}

从C++代码中定义各个分量,再通过Effect接口传入效果文件中。定义光源。下面是使用Light结构体定义一个具体的光(方向光的例子

C++代码:

    mParallelLight.dir      = D3DXVECTOR3(0.57735f, -0.57735f, 0.57735f);
    mParallelLight.ambient  = D3DXCOLOR(0.4f, 0.4f, 0.4f, 1.0f);
    mParallelLight.diffuse  = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
    mParallelLight.specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);

2)

与之前的顶点赋色不同,当有光照参与时,需要为物体设置材质。通过计算光照与材质,最终得到物体的颜色。

例如

struct Material
{
    Material()
    {
        ZeroMemory(this,sizeof(Material));
    }

    D3DXCOLOR ambient;
    D3DXCOLOR diffuse;
    D3DXCOLOR specular;
    float specpow;
};

由于D3D用三角形网格描述物体,而网格最终由顶点组成。所以材质的定义还是要落在顶点属性里。

例如

struct Vertex
{
  D3DVECTOR3  pos;
  D3DVECTOR3 normal;
  D3DXCOLOR ambient; 
  D3DXCOLOR diffuse;
  D3DXCOLOR specular;
}

通过定义顶点布局,使效果文件知道如何使用Vertex的各个分量。

3)

光照与材质生成物体颜色的计算过程,我们在像素着色器中完成。

下面是以平行光照射物体的处理为例。一段像素着色器的HLSL代码

float4 PS(VS_OUT pIn) : SV_Target
{
    pIn.normalW = normalize(pIn.normalW);
    SurfaceInfo v = {pIn.posW, pIn.normalW, pIn.diffuse, pIn.spec};
    
    float3 litColor;
    litColor = ParallelLight(v, gLight, gEyePosW);
          
    return float4(litColor, pIn.diffuse.a);
}

补充平行光与材质作用的具体光照方程(HLSL):

float3 ParallelLight(SurfaceInfo v, Light L, float3 eyePos)
{
    float3 litColor = float3(0.0f, 0.0f, 0.0f);
 
    // The light vector aims opposite the direction the light rays travel.
    float3 lightVec = -L.dir;
    
    // Add the ambient term.
    litColor += v.diffuse * L.ambient;    
    
    // Add diffuse and specular term, provided the surface is in 
    // the line of site of the light.
    
    float diffuseFactor = dot(lightVec, v.normal);
    [branch]
    if( diffuseFactor > 0.0f )
    {
        float specPower  = max(v.spec.a, 1.0f);
        float3 toEye     = normalize(eyePos - v.pos);
        float3 R         = reflect(-lightVec, v.normal);
        float specFactor = pow(max(dot(R, toEye), 0.0f), specPower);
                    
        // diffuse and specular terms
        litColor += diffuseFactor * v.diffuse * L.diffuse;
        litColor += specFactor * v.spec * L.spec;
    }
    
    return litColor;
}

 

在我们的程序中,存放在顶点缓冲区中的顶点数据首先经过顶点着色器,从顶点着色器出来后,进入像素着色器。完成光照计算。

posted on 2013-02-21 22:41  曾健  阅读(443)  评论(0编辑  收藏  举报