DX 简单阴影

View Code
//
// 在场景中渲染出一个茶壶Mesh以及这个茶壶的影子
//

#include "header.h"

ID3DXMesh *pTeapot = NULL;
D3DMATERIAL9 teapotMtrl;
D3DLIGHT9 pointLight; // 点光

bool DXSetup()
{
// 初始化材质
::ZeroMemory(&teapotMtrl, sizeof(teapotMtrl));
teapotMtrl.Ambient = RED;
teapotMtrl.Diffuse = RED;
teapotMtrl.Specular = RED;

// 初始化茶壶Mesh
D3DXCreateTeapot(g_pd3dDevice, &pTeapot, NULL);

// 初始化灯光
::ZeroMemory(&pointLight, sizeof(pointLight));
pointLight.Type = D3DLIGHT_POINT; // 点灯类型
pointLight.Diffuse = WHITE;
pointLight.Ambient = WHITE * 0.3f;
pointLight.Specular = WHITE * 0.3f;
pointLight.Position = D3DXVECTOR3(0.0f, 50.0f, 0.0f);
pointLight.Range = 200.0f;
g_pd3dDevice->SetLight(0, &pointLight);
g_pd3dDevice->LightEnable(0, TRUE);

// 设置摄影机
D3DXVECTOR3 position(0.0f, 0.0f, -10.0f);
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX camera;
D3DXMatrixLookAtLH(&camera,&position, &target, &up);
g_pd3dDevice->SetTransform(D3DTS_VIEW, &camera);

// 设置可视体 - 投影矩阵
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI * 0.5f, // 90 - degree
(float)Width / (float)Height,
1.0f,
1000.0f);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj);

return true;
}

void Render()
{
// 移动视点的位置
MovePosition();

g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, D3DCOLOR_XRGB(200,200,200), 1.0f, 0);
g_pd3dDevice->BeginScene();

// 渲染茶壶
D3DXMATRIX priCode;
D3DXMatrixTranslation(&priCode, 0,0,0); // 将DX设备移动到空间的原点
g_pd3dDevice->SetTransform(D3DTS_WORLD, &priCode);
g_pd3dDevice->SetMaterial(&teapotMtrl);
g_pd3dDevice->SetFVF(DX8Vertex_FVF);
pTeapot->DrawSubset(0);

// 在xy面渲染茶壶的影子
D3DXMATRIX shadowMatrix;
D3DXPLANE plane(0.0f, 1.0f, 0.0f, 5.0f); // xy plane
D3DXVECTOR4 lightDirection(0.0f, 5.0f, 0.0f, 1); // 设置产生阴影的灯光的类型及位置(或者方向). w=0是平等光,前三个参数表示方向;w=1是点光,前三个参数表示位置
D3DXMatrixShadow(&shadowMatrix, &lightDirection, &plane);
D3DXMATRIX shadowPosMatrix;
D3DXMatrixTranslation(&shadowPosMatrix, 0.0f, 0.0f, 0.0f);
D3DXMATRIX w = shadowPosMatrix * shadowMatrix;
g_pd3dDevice->SetTransform(D3DTS_WORLD, &w);
g_pd3dDevice->SetMaterial(&BLACK_MTRL);
pTeapot->DrawSubset(0);

g_pd3dDevice->EndScene();
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}

这是在屏幕上面渲染出一个茶壶以及茶壶的阴影,没有使用模版技术来防止二次混合,就是一个简单的成像.部分代码如上所示.下面记录一下我之前不太理解的东西.


首先是在空间的原点渲染出一个茶壶,然后在茶壶下面画一出这个茶壶在"地上的阴影".
设置产生阴影的灯光类型及这个灯光的位置(如果是平行光,那就是设置这个灯光的方向),灯光的位置在正上方(0,5,0)位置.即:D3DXVECTOR4 lightDirection(0.0f, 5.0f, 0.0f, 1);
设置阴影成像的平面为xy面,面的深度为-5,即,在空间z轴的坐标为-5;即:D3DXPLANE plane(0.0f, 1.0f, 0.0f, 5.0f);
设置待投影的物体在原点,即,茶壶所在地方,即:D3DXMatrixTranslation(&shadowPosMatrix, 0.0f, 0.0f, 0.0f);

平面公式是:
n.p+d=0     表示点在平面上(点在面上);
n.p+d>0     表示点在平面的上方(点不在面上)
n.p+d<0     表示点在平面的下方(点不在面上)

D3DXPLANE 所创建的面,指定的四个参数分别是n这个向量与d这个系数,p这个点来自于D3DXMatrixTranslation设置的后面三个参数.
这样就可以理解了,0*0 + 1*0 + 0*0 + 5 = 5,这个值是>0的,所以画出来的阴影是在平面上(如果在平面下是看不到的),根据这个公式来调整面与物体的位置即可.
posted @ 2011-12-22 20:38  莫压枯枯地  阅读(766)  评论(1编辑  收藏  举报