Trapezoidal Shadow Map(3)

Trapezoidal Shadow Map(3)_第1张图片
Trapezoidal Shadow Map(3)_第2张图片

Trapezoidal Shadow Map(3)_第3张图片

Trapezoidal Shadow Map(3)_第4张图片上面图中右上角为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;
};

你可能感兴趣的:(Trapezoidal Shadow Map(3))