Created
January 8, 2020 19:01
-
-
Save native-m/ddc11bef1e48b3b597b65055e4f7acb4 to your computer and use it in GitHub Desktop.
GTA: SA Stuff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void | |
UpdateShadowMatrix() | |
{ | |
DirectX::XMMATRIX camInv; | |
DirectX::XMMATRIX shadowView; | |
RwCamera* rwcam = Scene.camera; | |
float minDist = RwCameraGetNearClipPlane(rwcam); | |
float maxDist = RwCameraGetFarClipPlane(rwcam); | |
CVector sunPos; | |
CVector camPos; | |
camInv = DirectX::XMMatrixInverse(nullptr, *(DirectX::XMMATRIX*)&viewTransform); | |
GetSunPos(&sunPos, *(float*)0xB7C4F0); | |
camPos = TheCamera.GetPosition(); | |
DirectX::XMVECTOR p = DirectX::XMVectorSet(camPos.x - sunPos.x, camPos.y - sunPos.y, camPos.z - sunPos.z, 0.0f); | |
DirectX::XMVECTOR d = DirectX::XMVectorSet(camPos.x, camPos.y, camPos.z, 0.0f); | |
shadowView = DirectX::XMMatrixLookAtLH(p, d, DirectX::XMVectorSet(0.0f, 0.0f, 1.0f, 1.0f)); | |
float aspectRatio = (float)rwcam->frameBuffer->width / (float)rwcam->frameBuffer->height; | |
float fov = atanf(1.f / projTransform.m[1][1]) * 2.f * (180.0 / M_PI); | |
float tanHalfHFov = tanf(DirectX::XMConvertToRadians(fov / 2.0f)); | |
float tanHalfVFov = tanf(DirectX::XMConvertToRadians((fov * aspectRatio) / 2.0f)); | |
for (int i = 0; i < MAX_SHADOW_MAP; i++) | |
{ | |
float xNear = shadowSplit[i] * tanHalfHFov; | |
float xFar = shadowSplit[i + 1] * tanHalfHFov; | |
float yNear = shadowSplit[i] * tanHalfVFov; | |
float yFar = shadowSplit[i + 1] * tanHalfVFov; | |
DirectX::XMVECTOR frustum[8] = { | |
{ xNear, yNear, shadowSplit[i], 1.0f }, | |
{ -xNear, yNear, shadowSplit[i], 1.0f }, | |
{ xNear, -yNear, shadowSplit[i], 1.0f }, | |
{ -xNear, -yNear, shadowSplit[i], 1.0f }, | |
{ xFar, yFar, shadowSplit[i + 1], 1.0f }, | |
{ -xFar, yFar, shadowSplit[i + 1], 1.0f }, | |
{ xFar, -yFar, shadowSplit[i + 1], 1.0f }, | |
{ -xFar, -yFar, shadowSplit[i + 1], 1.0f }, | |
}; | |
DirectX::XMVECTOR frustumLight[8]; | |
float minX = FLT_MAX; | |
float maxX = FLT_MIN; | |
float minY = FLT_MAX; | |
float maxY = FLT_MIN; | |
float minZ = FLT_MAX; | |
float maxZ = FLT_MIN; | |
DirectX::XMVECTOR frustumCenter = DirectX::g_XMZero; | |
for (int j = 0; j < 8; j++) | |
{ | |
DirectX::XMVECTOR vw = DirectX::XMVector4Transform(frustum[j], camInv); | |
frustum[j] = vw; | |
frustumCenter = DirectX::XMVectorAdd(frustumCenter, vw); | |
} | |
frustumCenter = DirectX::XMVectorScale(frustumCenter, 1.f / 8.f); | |
DirectX::XMMATRIX lView = DirectX::XMMatrixLookAtLH( | |
DirectX::XMVectorSet(frustumCenter.m128_f32[0] - sunPos.x, frustumCenter.m128_f32[1] - sunPos.y, frustumCenter.m128_f32[2] - sunPos.z, 0.0f), | |
frustumCenter, | |
DirectX::XMVectorSet(0.0f, 0.0f, 1.0f, 1.0f)); | |
for (int j = 0; j < 8; j++) | |
{ | |
frustumLight[j] = DirectX::XMVector4Transform(frustum[j], lView); | |
minX = min(frustumLight[j].m128_f32[0], minX); | |
maxX = max(frustumLight[j].m128_f32[0], maxX); | |
minY = min(frustumLight[j].m128_f32[1], minY); | |
maxY = max(frustumLight[j].m128_f32[1], maxY); | |
minZ = min(frustumLight[j].m128_f32[2], minZ); | |
maxZ = max(frustumLight[j].m128_f32[2], maxZ); | |
} | |
DirectX::XMVECTOR vmin = DirectX::XMVectorSet(minX, minY, 1.0f, 1.0f); | |
DirectX::XMVECTOR vmax = DirectX::XMVectorSet(maxX, maxY, 1.0f, 1.0f); | |
DirectX::XMVECTOR longestDiagonal = DirectX::XMVectorSet( | |
frustumLight[0].m128_f32[0] - frustumLight[6].m128_f32[0], | |
frustumLight[0].m128_f32[1] - frustumLight[6].m128_f32[1], | |
frustumLight[0].m128_f32[2] - frustumLight[6].m128_f32[2], | |
1.0f | |
); | |
float diagonalLength = DirectX::XMVector3Length(longestDiagonal).m128_f32[0]; | |
longestDiagonal = DirectX::XMVectorReplicate(diagonalLength); | |
DirectX::XMVECTOR borderOffset = DirectX::XMVectorScale(DirectX::XMVectorSubtract(longestDiagonal, DirectX::XMVectorSubtract(vmax, vmin)), 0.5f); | |
borderOffset.m128_f32[2] = 0.0f; | |
borderOffset.m128_f32[3] = 0.0f; | |
vmin = DirectX::XMVectorSubtract(vmin, borderOffset); | |
vmax = DirectX::XMVectorAdd(vmax, borderOffset); | |
DirectX::XMVECTOR worldUnitsPerTexel = DirectX::XMVectorReplicate(diagonalLength / (float)SHADOW_MAP_SIZE); | |
worldUnitsPerTexel.m128_f32[2] = 1.0f; | |
worldUnitsPerTexel.m128_f32[3] = 1.0f; | |
vmin = DirectX::XMVectorDivide(vmin, worldUnitsPerTexel); | |
vmin = DirectX::XMVectorFloor(vmin); | |
vmin = DirectX::XMVectorMultiply(vmin, worldUnitsPerTexel); | |
vmax = DirectX::XMVectorDivide(vmax, worldUnitsPerTexel); | |
vmax = DirectX::XMVectorFloor(vmax); | |
vmax = DirectX::XMVectorMultiply(vmax, worldUnitsPerTexel); | |
DirectX::XMMATRIX lOrtho = DirectX::XMMatrixOrthographicOffCenterLH( | |
vmin.m128_f32[0], | |
vmax.m128_f32[0], | |
vmin.m128_f32[1], | |
vmax.m128_f32[1], | |
minZ, | |
maxZ + SHADOW_MAX_DIST); | |
DirectX::XMMATRIX shadowMatrix = DirectX::XMMatrixMultiply(lOrtho, shadowView); | |
DirectX::XMVECTOR origin = { 0.0f, 0.0f, 0.0f, 1.0f }; | |
origin = DirectX::XMVector3Transform(origin, shadowMatrix); | |
origin = DirectX::XMVectorScale(origin, (float)SHADOW_MAP_SIZE / 2.0f); | |
DirectX::XMVECTOR roundedOrigin = DirectX::XMVectorRound(origin); | |
DirectX::XMVECTOR roundOffset = DirectX::XMVectorSubtract(roundedOrigin, origin); | |
roundOffset = DirectX::XMVectorScale(roundOffset, 2.0f / (float)SHADOW_MAP_SIZE); | |
roundOffset.m128_f32[2] = 0.f; | |
roundOffset.m128_f32[3] = 0.f; | |
lOrtho.r[3] = DirectX::XMVectorAdd(lOrtho.r[3], roundOffset); | |
shadowZInfo[i].x = minZ; | |
shadowZInfo[i].y = maxZ; | |
shadowMat[i] = DirectX::XMMatrixMultiply( | |
DirectX::XMMatrixTranspose(lOrtho), | |
DirectX::XMMatrixTranspose(lView)); | |
DirectX::XMVECTOR v = { 0.0f, 0.0f, shadowSplit[i + 1], 1.0f }; | |
v = DirectX::XMVector4Transform(v, *(DirectX::XMMATRIX*)&projTransform); | |
shadowZInfo[i].z = v.m128_f32[2]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment