|

在light’s post perspective space中根据视锥构建的梯形,为了方便表示,贴了一张贴图表示.贴图中的Top表示靠近视锥前截面的梯形的上底,Bottom表示靠近视锥后截面的梯形的下底。

梯形转换到trapezoidal space后的显示情况
light’s post perspective space->trapezoidal space的距阵计算:
HRESULT CTrapezoidalShadowMap::ComputeTrapezoidalMatrix(D3DXMATRIX& matrix,D3DXVECTOR3& topl,D3DXVECTOR3& topr,D3DXVECTOR3& bottoml,D3DXVECTOR3& bottomr,D3DXVECTOR3& intersection) { // 平移TopLine的中点到Light's Post-Perspective Space的中点 D3DXMatrixTranslation(&matrix,-(topl.x+topr.x)/2.0f,-(topl.y+topr.y)/2.0f,0);
// 旋转梯形使得TopLine和Light's Post-Perspective Space的x轴重合 D3DXVECTOR3 t_topline=(topl-topr); D3DXVec3Normalize(&t_topline,&t_topline);
float t_angle=D3DXVec3Dot(&t_topline,&D3DXVECTOR3(1,0,0));
D3DXMATRIX t_matrix; D3DXMatrixRotationZ(&t_matrix,-acosf(t_angle));
matrix*=t_matrix;
// 平移梯形使得两侧边交点到Light's Post-Perspective Space的中点 D3DXVECTOR3 t_intersection;
D3DXVec3TransformCoord(&t_intersection,&intersection,&matrix);
D3DXMatrixTranslation(&t_matrix,-t_intersection.x,-t_intersection.y,0);
matrix*=t_matrix;
// 变换使得成为等边梯形 D3DXVECTOR3 t_point1,t_point2; D3DXVec3TransformCoord(&t_point1,&topl,&matrix); D3DXVec3TransformCoord(&t_point2,&topr,&matrix);
t_point1+=t_point2;
D3DXMatrixIdentity(&t_matrix); t_matrix._21=-t_point1.x/t_point1.y;
matrix*=t_matrix;
// 变换使得两侧边成90度,TopLine的两点在[-1,1]和[1,1]上 D3DXVec3TransformCoord(&t_point1,&topr,&matrix);
D3DXMatrixScaling(&t_matrix,1.0f/t_point1.x,1.0f/t_point1.y,1.0f);
matrix*=t_matrix;
// 变换使得梯形变成矩形 t_matrix._11=t_matrix._22=t_matrix._33=t_matrix._24=t_matrix._42=1.0f; t_matrix._12=t_matrix._13=t_matrix._14=t_matrix._21=t_matrix._23=0.0f; t_matrix._31=t_matrix._32=t_matrix._34=t_matrix._41=t_matrix._43=t_matrix._44=0.0f;
matrix*=t_matrix;
// 平移使得矩形的中心到Light's Post-Perspective Space的中点 D3DXVec3TransformCoord(&t_point1,&topl,&matrix); D3DXVec3TransformCoord(&t_point2,&bottomr,&matrix);
D3DXMatrixTranslation(&t_matrix,0,-(t_point1.y+t_point2.y)/2.0f,0);
matrix*=t_matrix;
// 拉伸矩形的Y方向,使得充满整个Light's Post-Perspective Space D3DXVECTOR4 t_point3; D3DXVec3Transform(&t_point3,&topl,&matrix);
D3DXMatrixIdentity(&t_matrix);
t_matrix._22=-t_point3.w/t_point3.y;
matrix*=t_matrix;
// return S_OK; };
参加讨论

中间的红色框包起来的是在light's post−perspective space中的视锥,红色框是构造出的trapezoidal,外围的是在trapezoidal space中的视锥.其中蓝色的表示视锥的Near Plane,绿色的表示Far Plane和边.
通过视锥计算梯形的代码:
HRESULT CTrapezoidalShadowMap::ComplteLightPostPerspectiveTrapezoidal(SFrustum& frustum,D3DXMATRIX& lightviewproj,D3DXVECTOR3& topl,D3DXVECTOR3& topr,D3DXVECTOR3& bottoml,D3DXVECTOR3& bottomr,D3DXVECTOR3& intersection) { D3DXVECTOR3 t_frustumvertex[9];
// 转换到Light's Post-Perspective Space D3DXVec3TransformCoordArray( t_frustumvertex, sizeof(D3DXVECTOR3), frustum.m_Vertexs, sizeof(D3DXVECTOR3), &lightviewproj, sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3) );
for (int i=0;i<9;++i) { t_frustumvertex[i].z=0.0f; }
// 求出中轴线 D3DXVECTOR3 t_topcenter =0.25*(t_frustumvertex[0]+t_frustumvertex[1]+t_frustumvertex[2]+t_frustumvertex[3]); D3DXVECTOR3 t_bottomcenter =0.25*(t_frustumvertex[4]+t_frustumvertex[5]+t_frustumvertex[6]+t_frustumvertex[7]);
D3DXVECTOR3 t_centerline = t_topcenter - t_bottomcenter; D3DXVec3Normalize(&t_centerline,&t_centerline);
// 平移和旋转使得中轴线的中点在Light's Post-Perspective Space中点,方向指向Light's Post-Perspective Space的Y轴 D3DXMATRIX t_trans; D3DXMatrixTranslation(&t_trans,-0.5f*(t_topcenter.x+t_bottomcenter.x),-0.5f*(t_topcenter.y+t_bottomcenter.y),0);
D3DXMATRIX t_rotation; float t_angle=acosf(D3DXVec3Dot(&t_centerline,&D3DXVECTOR3(0,1,0)));
if (t_centerline.x>0) D3DXMatrixRotationZ(&t_rotation,-t_angle); else D3DXMatrixRotationZ(&t_rotation,t_angle);
t_trans*=t_rotation;
D3DXVec3TransformCoordArray( t_frustumvertex, sizeof(D3DXVECTOR3), t_frustumvertex, sizeof(D3DXVECTOR3), &t_trans, sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3) );
// 求出2D AABB BoundingBox frustumAABB2D( t_frustumvertex, (sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3)-1) );
// 计算梯形的四个顶点 D3DXVECTOR3 t_topl,t_topr,t_bottoml,t_bottomr;
D3DXVECTOR3 t_side[4]; float t_value[4];
for (int i=0;i<4;++i) { t_side[i]=t_frustumvertex[i]-t_frustumvertex[i+4]; D3DXVec3Normalize(&t_side[i],&t_side[i]); t_value[i]=D3DXVec3Dot(&t_side[i],&D3DXVECTOR3(0,1,0)); }
float t_min=1.0f; int t_no; for (int i=0;i<4;++i) { if (t_side[i].x>0) continue;
if (t_value[i]<t_min) { t_min=t_value[i]; t_no=i; } }
t_topl.y=frustumAABB2D.maxPt.y; t_topl.x=-(t_frustumvertex[8].y-frustumAABB2D.maxPt.y)*tanf(acosf(t_value[t_no])); t_bottoml.y=frustumAABB2D.minPt.y; t_bottoml.x=-(t_frustumvertex[8].y-frustumAABB2D.minPt.y)*tanf(acosf(t_value[t_no]));
t_min=1.0f; for (int i=0;i<4;++i) { if (t_side[i].x<0) continue;
if (t_value[i]<t_min) { t_min=t_value[i]; t_no=i; } }
t_topr.y=frustumAABB2D.maxPt.y; t_topr.x=(t_frustumvertex[8].y-frustumAABB2D.maxPt.y)*tanf(acosf(t_value[t_no])); t_bottomr.y=frustumAABB2D.minPt.y; t_bottomr.x=(t_frustumvertex[8].y-frustumAABB2D.minPt.y)*tanf(acosf(t_value[t_no]));
// 将梯形四个顶点和两边的交点变换回Light's Post-Perspective Space D3DXMATRIX t_invtrans; D3DXMatrixInverse(&t_invtrans,NULL,&t_trans);
D3DXVec3TransformCoord(&topl,&t_topl,&t_trans); D3DXVec3TransformCoord(&topr,&t_topr,&t_trans); D3DXVec3TransformCoord(&bottoml,&t_bottoml,&t_trans); D3DXVec3TransformCoord(&bottomr,&t_bottomr,&t_trans); D3DXVec3TransformCoord(&intersection,&t_frustumvertex[8],&t_trans);
// return S_OK; };
参加讨论




上面图中右上角为Shadow Map.
使用TSM做Self-Shadow时需要注意ShadowMap保存和第二步用于比较的Depth不要转换到trapezoidal space中,只转换x和y就行了.
计算trapezoidal和LPPS->trapezoidal space的代码修正后为: HRESULT CTrapezoidalShadowMap::ComputeTrapezoidalMatrix(D3DXMATRIX& matrix,D3DXVECTOR3& topl,D3DXVECTOR3& topr,D3DXVECTOR3& bottoml,D3DXVECTOR3& bottomr,D3DXVECTOR3& intersection) { // 平移梯形使得两侧边交点到LightProjectSpace的中点 D3DXMatrixTranslation(&matrix,-intersection.x,-intersection.y,0);
// 旋转梯形使得TopLine和LightProjectSpace的x轴重合 D3DXVECTOR3 t_topline=(topl-topr); D3DXVec3Normalize(&t_topline,&t_topline);
float t_angle=D3DXVec3Dot(&t_topline,&D3DXVECTOR3(1,0,0));
D3DXMATRIX t_matrix;
if (t_topline.y>0) D3DXMatrixRotationZ(&t_matrix,-acosf(t_angle)); else D3DXMatrixRotationZ(&t_matrix,+acosf(t_angle));
matrix*=t_matrix;
// 变换使得成为等边梯形 D3DXVECTOR3 t_point1,t_point2; D3DXVec3TransformCoord(&t_point1,&topl,&matrix); D3DXVec3TransformCoord(&t_point2,&topr,&matrix);
t_point1+=t_point2;
D3DXMatrixIdentity(&t_matrix); t_matrix._21=-t_point1.x/t_point1.y;
matrix*=t_matrix;
// 变换使得两侧边成90度,TopLine的两点在[-1,1]和[1,1]上 D3DXVec3TransformCoord(&t_point1,&topr,&matrix);
D3DXMatrixScaling(&t_matrix,1.0f/t_point1.x,1.0f/t_point1.y,1.0f);
matrix*=t_matrix;
// 变换使得梯形变成矩形 t_matrix._11=t_matrix._22=t_matrix._33=1.0f; t_matrix._12=t_matrix._13=t_matrix._14=t_matrix._21=t_matrix._23=0.0f; t_matrix._31=t_matrix._32=t_matrix._34=t_matrix._41=t_matrix._43=t_matrix._44=0.0f;
t_matrix._42=1.0f; t_matrix._24=1.0f;
matrix*=t_matrix;
// 平移使得矩形的中心到LightProjectSpace的中点 D3DXVec3TransformCoord(&t_point1,&topl,&matrix); D3DXVec3TransformCoord(&t_point2,&bottomr,&matrix);
D3DXMatrixTranslation(&t_matrix,0,-(t_point1.y+t_point2.y)/2.0f,0);
matrix*=t_matrix;
// 拉伸矩形的Y方向,使得充满整个LightProjectSpace D3DXVECTOR4 t_point3; D3DXVec3Transform(&t_point3,&topl,&matrix);
D3DXMatrixIdentity(&t_matrix);
t_matrix._22=-t_point3.w/t_point3.y;
matrix*=t_matrix;
// return S_OK; };
HRESULT CTrapezoidalShadowMap::ComplteLightPostPerspectiveTrapezoidal(SFrustum& frustum,D3DXMATRIX& lightviewproj,D3DXVECTOR3& topl,D3DXVECTOR3& topr,D3DXVECTOR3& bottoml,D3DXVECTOR3& bottomr,D3DXVECTOR3& intersection) { D3DXVECTOR3 t_frustumvertex[9];
D3DXVec3TransformCoordArray( t_frustumvertex, sizeof(D3DXVECTOR3), frustum.m_Vertexs, sizeof(D3DXVECTOR3), &lightviewproj, sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3) );
for (int i=0;i<9;++i) { t_frustumvertex[i].z=0.0f; }
D3DXVECTOR3 t_topcenter =0.25*(t_frustumvertex[0]+t_frustumvertex[1]+t_frustumvertex[2]+t_frustumvertex[3]); D3DXVECTOR3 t_bottomcenter =0.25*(t_frustumvertex[4]+t_frustumvertex[5]+t_frustumvertex[6]+t_frustumvertex[7]);
D3DXVECTOR3 t_centerline = t_topcenter - t_bottomcenter; D3DXVec3Normalize(&t_centerline,&t_centerline);
D3DXMATRIX t_trans; D3DXMatrixTranslation(&t_trans,-0.5f*(t_topcenter.x+t_bottomcenter.x),-0.5f*(t_topcenter.y+t_bottomcenter.y),0);
D3DXMATRIX t_rotation; float t_angle=acosf(D3DXVec3Dot(&t_centerline,&D3DXVECTOR3(0,1,0)));
if (t_centerline.x>0) D3DXMatrixRotationZ(&t_rotation,+t_angle); else D3DXMatrixRotationZ(&t_rotation,-t_angle);
t_trans*=t_rotation;
D3DXVec3TransformCoordArray( t_frustumvertex, sizeof(D3DXVECTOR3), t_frustumvertex, sizeof(D3DXVECTOR3), &t_trans, sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3) );
BoundingBox frustumAABB2D( t_frustumvertex, (sizeof(t_frustumvertex)/sizeof(D3DXVECTOR3)-1) );
D3DXVECTOR3 t_topl,t_topr,t_bottoml,t_bottomr;
D3DXVECTOR3 t_side[4]; float t_value[4];
for (int i=0;i<4;++i) { t_side[i]=t_frustumvertex[i]-t_frustumvertex[i+4]; D3DXVec3Normalize(&t_side[i],&t_side[i]); t_value[i]=D3DXVec3Dot(&t_side[i],&D3DXVECTOR3(0,1,0)); }
float t_min=1.0f; int t_no; for (int i=0;i<4;++i) { if (t_side[i].x>0) continue;
if (t_value[i]<t_min) { t_min=t_value[i]; t_no=i; } }
t_topr.y=frustumAABB2D.maxPt.y; t_topr.x=(t_frustumvertex[8].y-frustumAABB2D.maxPt.y)*tanf(acosf(t_value[t_no])); t_topr.z=0.0f; t_bottomr.y=frustumAABB2D.minPt.y; t_bottomr.x=(t_frustumvertex[8].y-frustumAABB2D.minPt.y)*tanf(acosf(t_value[t_no])); t_bottomr.z=0.0f;
t_min=1.0f; for (int i=0;i<4;++i) { if (t_side[i].x<0) continue;
if (t_value[i]<t_min) { t_min=t_value[i]; t_no=i; } }
t_topl.y=frustumAABB2D.maxPt.y; t_topl.x=-(t_frustumvertex[8].y-frustumAABB2D.maxPt.y)*tanf(acosf(t_value[t_no])); t_topl.z=0.0f; t_bottoml.y=frustumAABB2D.minPt.y; t_bottoml.x=-(t_frustumvertex[8].y-frustumAABB2D.minPt.y)*tanf(acosf(t_value[t_no])); t_bottoml.z=0.0f;
D3DXMATRIX t_invtrans; D3DXMatrixInverse(&t_invtrans,NULL,&t_trans);
D3DXVec3TransformCoord(&topl,&t_topl,&t_invtrans); D3DXVec3TransformCoord(&topr,&t_topr,&t_invtrans); D3DXVec3TransformCoord(&bottoml,&t_bottoml,&t_invtrans); D3DXVec3TransformCoord(&bottomr,&t_bottomr,&t_invtrans); D3DXVec3TransformCoord(&intersection,&t_frustumvertex[8],&t_invtrans);
// return S_OK; }; | |