天行健 君子当自强而不息

D3D中的地形绘制基础(3)

13

13.4光照

cTerrain::generate_texture方法会调用cTerrain::light_terrain,顾名思义,光照使地形更接近于现实。当我们已经计算完地形纹理以后,我们只需要计算阴影系数(shade factor),使一个定义了光源的地形区域变亮或变暗。你会惊讶于为什么我们照亮地图却没有让Direct3D来做。我们自己来计算有三个好处:

内存中不必保存顶点法线。

因为纹理是静态的,所以不能随意的移动光源。虽然我们可以重新计算光源,但因此采用Direct3D实时的照亮地形是很耗时的。

我们获得了一些数学上的经验,熟悉了一些基本的光照概念,并且是用Direct3D函数实践的。

13.4.1概览(OVERVIEW)

光照是计算地形阴影shade)的一个最基本的技巧之一,一般认为的光是漫射光(diffuse lighting),给定一个平行光源,我们用“到达光源的方向(direction to light)”(该光源发出的平行光的传播方向的反方向)。因此,如果我们想让光线从空中笔直落下,那么lightRaysDirection = (0, -1, 0),按相反的方向:directionToLight = (0, 1, 0)注意:创建光照向量要使用单位向量。

注意:虽然指定方向的光是从光源发射出来的,这么说更直接一点,指定到达光源的反向在计算上要比漫谢光更合得来。

对于地形中的每个方格,我们计算光的向量与方格的面法线之间的角度。

在图13.7中我们看到,当角度变得比较大时,方格的面离光源越来越远,接收的光越少。反过来说,角度变小,方格的面则离光源越来越近,相应的会接收更多的光。注意:一旦光向量与法线角度大于90度,表面就接收不到光。

我们能够创建一个阴影shading)标量,用0..1之间的范围来表示表面能接收到光的多少。使用阴影标量,角度大则标量接近于0。当颜色与一个阴影标量接近0的值相乘时,得到的结果是:颜色变暗。相反,乘以一个阴影标量的值接近1的值时,颜色则接近于原始亮度。

 

13.4.2 计算方格的阴影(Shade

光源的方向是一个单位向量,为了计算光源方向与面法线间的夹角,首先需要找到面法线,这是叉积的一小部分应用,但首先必须在方格里找到二个共面的非0并且不平行的向量。看图 13.8有两个这样的向量:

 

给指定的格子计算阴影系数用cTerrain::compute_shade方法,它需要参数:行和列来确定方格,还有平行方向光的光源。

    float cTerrain::compute_shade(int cell_row, int cell_col, D3DXVECTOR3* dir_to_light)
    {
        
// get heights of three vertices on the quad
   
    float height_a = get_height_map_entry(cell_row,   cell_col);
        
float height_b = get_height_map_entry(cell_row,   cell_col+1);
        
float height_c = get_height_map_entry(cell_row+1, cell_col);
   
        
// build two vectors on the quad
   
        D3DXVECTOR3 u(m_cell_spacing, height_b - height_a, 0.0f);
        D3DXVECTOR3 v(0.0f,              height_c - height_a, -m_cell_spacing);
   
        
// find the normal by taking the cross product of two vectors on the quad
   
    D3DXVECTOR3 n;
        D3DXVec3Cross(&n, &u, &v);
        D3DXVec3Normalize(&n, &n);
   
        
float cosine = D3DXVec3Dot(&n, dir_to_light);
   
        
if(cosine < 0.0f)
            cosine = 0.0f;
   
        
return cosine;
    }

13.4.3 地形阴影(Shading

一旦知道了如何给指定的方格加阴影,我们就能给地形上所有的方格加阴影。只要遍例每一个方格,计算方格的阴影值,并测量方格对应的texel颜色。光照少则方格会变暗。
    bool cTerrain::light_terrain(D3DXVECTOR3* dir_to_light)
    {
        D3DSURFACE_DESC texture_desc;
        m_texture->GetLevelDesc(0, &texture_desc);
   
        
// make sure we got the requested format because our code that fills the texture is
        // hard coded to a 32 bit pixel depth.
   
    if(texture_desc.Format != D3DFMT_X8R8G8B8)
            
return false;
   
        D3DLOCKED_RECT locked_rect;
        m_texture->LockRect(0, &locked_rect, NULL, 0);
   
        DWORD* image_data = (DWORD*) locked_rect.pBits;
   
        
for(UINT row = 0; row < texture_desc.Height; row++)
        {
            
for(UINT col = 0; col < texture_desc.Width; col++)
            {
                
// Index into texture, note we use the pitch and divide by four since the pitch is given
                // in bytes and there are 4 bytes per DWORD.
   
            int index = row * (locked_rect.Pitch / 4) + col;
   
                
// get current color of quad
   
                D3DXCOLOR color(image_data[index]);
   
                
// shade current quad
   
                color *= compute_shade(row, col, dir_to_light);
   
                
// save shade color
   
                image_data[index] = (D3DCOLOR) color;
            }
        }
   
        m_texture->UnlockRect(0);
   
        
return true;
    }

posted on 2008-04-02 20:31 lovedday 阅读(1482) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论