port from perforce
This commit is contained in:
156
evoke-64k/trunk/ev10/PSSM.cpp
Normal file
156
evoke-64k/trunk/ev10/PSSM.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "defines.h"
|
||||
|
||||
#include "PSSM.h"
|
||||
|
||||
#include "shader.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include "intrin.h"
|
||||
|
||||
void PSSM::Init()
|
||||
{
|
||||
m_iSplitCount = -1;
|
||||
m_fRange = 0.0f;
|
||||
}
|
||||
|
||||
void PSSM::UpdateSplits(const D3DXVECTOR3 &vLightDir, const D3DXMATRIX &mView, const D3DXMATRIX &mProj)
|
||||
{
|
||||
assert( m_iSplitCount >= 0 && m_iSplitCount <= MaxSplitCount );
|
||||
assert( m_fRange >= 0.0f );
|
||||
|
||||
// Extract cam data
|
||||
D3DXVECTOR3 vCamPos(
|
||||
-(mView._11 * mView._41 + mView._12 * mView._42 + mView._13 * mView._43),
|
||||
-(mView._21 * mView._41 + mView._22 * mView._42 + mView._23 * mView._43),
|
||||
-(mView._31 * mView._41 + mView._32 * mView._42 + mView._33 * mView._43) );
|
||||
D3DXVECTOR3 vCamRight(mView._11, mView._21, mView._31);
|
||||
D3DXVECTOR3 vCamUp(mView._12, mView._22, mView._32);
|
||||
D3DXVECTOR3 vCamLook(mView._13, mView._23, mView._33);
|
||||
|
||||
// Extract plane distances
|
||||
float fNearPlane = mProj._43 / -mProj._33;
|
||||
float fFarPlane = mProj._43 / (1.0f - mProj._33);
|
||||
|
||||
// Extract FOV
|
||||
float fTanHalfFOVX = 1.0f / mProj._11;
|
||||
float fTanHalfFOVY = 1.0f / mProj._22;
|
||||
|
||||
// Compute maximum shadow split clip plane
|
||||
float fMaxClipPlane = max( fFarPlane,
|
||||
max(2.0f * fTanHalfFOVX * fFarPlane, 2.0f * fTanHalfFOVY * fFarPlane) );
|
||||
|
||||
// Adjust range
|
||||
if(fFarPlane - fNearPlane > m_fRange)
|
||||
fFarPlane = fNearPlane + m_fRange;
|
||||
|
||||
// Compute frustum depth
|
||||
float fFrustumDepth = fFarPlane - fNearPlane;
|
||||
|
||||
// Complete light vector set
|
||||
D3DXVECTOR3 vLightUp(0.0f, 1.0f, 0.0f), vLightRight;
|
||||
if(abs(D3DXVec3Dot(&vLightUp, &vLightDir)) > 0.95f)
|
||||
vLightUp = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
|
||||
D3DXVec3Cross(&vLightRight, &vLightUp, &vLightDir);
|
||||
D3DXVec3Normalize(&vLightRight, &vLightRight);
|
||||
D3DXVec3Cross(&vLightUp, &vLightDir, &vLightRight);
|
||||
D3DXVec3Normalize(&vLightUp, &vLightUp);
|
||||
|
||||
// Loop over splits
|
||||
for(int iSplit = 0; iSplit < m_iSplitCount; iSplit++)
|
||||
{
|
||||
// Compute both uniform and logarithmic split distribution
|
||||
float fUniformSplitNear = fNearPlane + fFrustumDepth * ((float)iSplit / m_iSplitCount);
|
||||
float fUniformSplitFar = fNearPlane + fFrustumDepth * ((float)(iSplit + 1) / m_iSplitCount);
|
||||
float fLogSplitNear = fNearPlane * mypow(fFarPlane / fNearPlane, (float)iSplit / m_iSplitCount);
|
||||
float fLogSplitFar = fNearPlane * mypow(fFarPlane / fNearPlane, (float)(iSplit + 1) / m_iSplitCount);
|
||||
|
||||
// Take average of both distributions
|
||||
float fSplitNear = (fUniformSplitNear + fLogSplitNear) / 2.0f;
|
||||
float fSplitFar = (fUniformSplitFar + fLogSplitFar) / 2.0f;
|
||||
|
||||
// Center
|
||||
D3DXVECTOR3 vSplitCenter = vCamPos + (fSplitNear + fSplitFar) / 2.0f * vCamLook;
|
||||
|
||||
// Compute split view matrix
|
||||
D3DXMatrixIdentity(&m_ViewMatrices[iSplit]);
|
||||
memcpy(&m_ViewMatrices[iSplit]._11, &vLightRight, sizeof(float) * 3);
|
||||
memcpy(&m_ViewMatrices[iSplit]._21, &vLightUp, sizeof(float) * 3);
|
||||
memcpy(&m_ViewMatrices[iSplit]._31, &vLightDir, sizeof(float) * 3);
|
||||
D3DXMatrixTranspose(&m_ViewMatrices[iSplit], &m_ViewMatrices[iSplit]);
|
||||
m_ViewMatrices[iSplit]._41 = -D3DXVec3Dot(&vSplitCenter, &vLightRight);
|
||||
m_ViewMatrices[iSplit]._42 = -D3DXVec3Dot(&vSplitCenter, &vLightUp);
|
||||
m_ViewMatrices[iSplit]._43 = -D3DXVec3Dot(&vSplitCenter, &vLightDir);
|
||||
|
||||
// Update split view
|
||||
m_ViewPos[iSplit] = vSplitCenter;
|
||||
m_ViewDir[iSplit] = vLightDir;
|
||||
|
||||
D3DXVECTOR3 splitCorners[8];
|
||||
|
||||
// Compute all eight frustum split corner points
|
||||
ComputeCornerPoints(splitCorners, fSplitNear, fSplitFar, fTanHalfFOVX, fTanHalfFOVY,
|
||||
vCamPos, vCamRight, vCamUp, vCamLook, 0.1f);
|
||||
|
||||
float fMinX = FLT_MAX, fMaxX = FLT_MIN;
|
||||
float fMinY = FLT_MAX, fMaxY = FLT_MIN;
|
||||
float fMinZ = FLT_MAX, fMaxZ = FLT_MIN;
|
||||
|
||||
// Loop over corner points
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
// Transform corner to view space
|
||||
D3DXVECTOR4 vViewSpaceCorner;
|
||||
D3DXVec3Transform(&vViewSpaceCorner, &splitCorners[i], &m_ViewMatrices[iSplit]);
|
||||
|
||||
// Find min and max values
|
||||
if(vViewSpaceCorner.x > fMaxX) fMaxX = vViewSpaceCorner.x;
|
||||
if(vViewSpaceCorner.x < fMinX) fMinX = vViewSpaceCorner.x;
|
||||
if(vViewSpaceCorner.y > fMaxY) fMaxY = vViewSpaceCorner.y;
|
||||
if(vViewSpaceCorner.y < fMinY) fMinY = vViewSpaceCorner.y;
|
||||
if(vViewSpaceCorner.z > fMaxZ) fMaxZ = vViewSpaceCorner.z;
|
||||
if(vViewSpaceCorner.z < fMinZ) fMinZ = vViewSpaceCorner.z;
|
||||
}
|
||||
|
||||
// Bias
|
||||
fMinX -= 2.0f; fMinY -= 2.0f; fMinZ -= 2.0f;
|
||||
fMaxX += 2.0f; fMaxY += 2.0f; fMaxZ += 2.0f;
|
||||
|
||||
// Compute split projection matrix
|
||||
D3DXMatrixOrthoOffCenterLH(&m_ProjMatrices[iSplit],
|
||||
fMinX, fMaxX,
|
||||
fMinY, fMaxY,
|
||||
fMinZ - fMaxClipPlane, fMaxZ + fMaxClipPlane);
|
||||
}
|
||||
}
|
||||
|
||||
void PSSM::ComputeCornerPoints(D3DXVECTOR3 *pCorners,
|
||||
float fNear, float fFar, float fTanHalfFOVX, float fTanHalfFOVY,
|
||||
const D3DXVECTOR3 &vCamPos, const D3DXVECTOR3 &vCamRight,
|
||||
const D3DXVECTOR3 &vCamUp, const D3DXVECTOR3 &vCamLook,
|
||||
float fOverlap)
|
||||
{
|
||||
float fNearHalfWidth = fTanHalfFOVX * fNear;
|
||||
float fNearHalfHeight = fTanHalfFOVY * fNear;
|
||||
float fFarHalfWidth = fTanHalfFOVX * fFar;
|
||||
float fFarHalfHeight = fTanHalfFOVY * fFar;
|
||||
|
||||
D3DXVECTOR3 vNearCenter = vCamPos + fNear * vCamLook;
|
||||
D3DXVECTOR3 vFarCenter = vCamPos + fFar * vCamLook;
|
||||
|
||||
// Compute eight frustum split corner points
|
||||
pCorners[0] = vNearCenter + fNearHalfWidth * vCamRight + fNearHalfHeight * vCamUp;
|
||||
pCorners[1] = vNearCenter + fNearHalfWidth * vCamRight - fNearHalfHeight * vCamUp;
|
||||
pCorners[2] = vNearCenter - fNearHalfWidth * vCamRight + fNearHalfHeight * vCamUp;
|
||||
pCorners[3] = vNearCenter - fNearHalfWidth * vCamRight - fNearHalfHeight * vCamUp;
|
||||
|
||||
pCorners[4] = vFarCenter + fFarHalfWidth * vCamRight + fFarHalfHeight * vCamUp;
|
||||
pCorners[5] = vFarCenter + fFarHalfWidth * vCamRight - fFarHalfHeight * vCamUp;
|
||||
pCorners[6] = vFarCenter - fFarHalfWidth * vCamRight + fFarHalfHeight * vCamUp;
|
||||
pCorners[7] = vFarCenter - fFarHalfWidth * vCamRight - fFarHalfHeight * vCamUp;
|
||||
|
||||
D3DXVECTOR3 vCenter = (vNearCenter + vFarCenter) / 2.0f;
|
||||
|
||||
// Apply split overlap scaling
|
||||
for(int i = 0; i < 8; i++)
|
||||
pCorners[i] += (pCorners[i] - vCenter) * fOverlap;
|
||||
}
|
||||
Reference in New Issue
Block a user