Created
January 8, 2020 19:01
-
-
Save native-m/ddc11bef1e48b3b597b65055e4f7acb4 to your computer and use it in GitHub Desktop.
Revisions
-
native-m created this gist
Jan 8, 2020 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,141 @@ 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]; } }