void updateMatrices(const float *cameraView) { float bias = getBias(); if(shadowMap) properties.targetPos = shadowMap->pos; properties.resolutionX = 2 * SHADOW_WIDTH; properties.resolutionY = 2 * SHADOW_HEIGHT; properties.updateMatrices(cameraView, bias); camera.SetPosition(properties.position); camera.SetTarget(properties.position + properties.direction); camera.SetFieldOfView(D3DXToRadian(properties.fov)); camera.SetVisibilityRange(properties.range); }
void Storm3D_SpotlightShared::updateMatricesOffCenter(const D3DXMATRIX &cameraView, const VC2 &min, const VC2 &max, float height, Storm3D_Camera &camera) { // Position of the light in global coordinates // Y-axis is height D3DXVECTOR3 lightPosition(position.x, position.y, position.z); // Up vector (z-axis) D3DXVECTOR3 up(0.f, 0.f, 1.f); // Look direction D3DXVECTOR3 lookAt = lightPosition; lookAt.y -= 1.f; { // max and min define the extents of light area in local coordinates // Z-axis is height float zmin = 0.2f; //float zmax = std::max(range, height) * 1.4f; // height is light height from light properties float zmax = height; float factor = 1.5f * zmin / height; float xmin = min.x * factor; float xmax = max.x * factor; float ymin = min.y * factor; float ymax = max.y * factor; D3DXMatrixPerspectiveOffCenterLH(&lightProjection, xmin, xmax, ymin, ymax, zmin, zmax); // Calculate the extents of light area in global coordinates VC2 worldMin = min; worldMin.x += position.x; worldMin.y += position.z; VC2 worldMax = max; worldMax.x += position.x; worldMax.y += position.z; // Generate approximate camera for culling. // Calculate range of the camera. // Y-axis is height float planeY = position.y - height; // Calculate distances from light position to light plane edges VC3 p1 = VC3( worldMin.x, planeY, worldMin.y ) - position; VC3 p2 = VC3( worldMax.x, planeY, worldMin.y ) - position; VC3 p3 = VC3( worldMax.x, planeY, worldMax.y ) - position; VC3 p4 = VC3( worldMin.x, planeY, worldMax.y ) - position; float d1 = p1.GetLength(); float d2 = p2.GetLength(); float d3 = p3.GetLength(); float d4 = p4.GetLength(); float maxRange = 0.0f; maxRange = MAX( maxRange, d1 ); maxRange = MAX( maxRange, d2 ); maxRange = MAX( maxRange, d3 ); maxRange = MAX( maxRange, d4 ); //maxRange = sqrtf(maxRange); // Calculate FOV of the camera. VC3 planeCenter = VC3( (worldMin.x + worldMax.x) * 0.5f, planeY, (worldMin.y + worldMax.y) * 0.5f ); VC3 camVec = planeCenter - position; camVec.Normalize(); float minDot = 10000.0f; float t1 = camVec.GetDotWith( p1 ) / d1; float t2 = camVec.GetDotWith( p2 ) / d2; float t3 = camVec.GetDotWith( p3 ) / d3; float t4 = camVec.GetDotWith( p4 ) / d4; minDot = MIN( minDot, t1 ); minDot = MIN( minDot, t2 ); minDot = MIN( minDot, t3 ); minDot = MIN( minDot, t4 ); float maxAngle = acosf( minDot ); // Place camera to light position camera.SetPosition(position); camera.SetUpVec(VC3(0.f, 0.f, 1.f)); // Point camera at light plane center camera.SetTarget(planeCenter); camera.SetFieldOfView( maxAngle ); camera.SetVisibilityRange( maxRange ); } D3DXMATRIX cameraMatrix(cameraView); float det = D3DXMatrixDeterminant(&cameraMatrix); D3DXMatrixInverse(&cameraMatrix, &det, &cameraMatrix); unsigned int tweakRange = 1; float bias = 0.f; float currentBias = 0.f; for(int i = 0; i < 2; ++i) { D3DXMatrixLookAtLH(&lightView[i], &lightPosition, &lookAt, &up); if(i == 1) currentBias = 0; // Tweak matrix float soffsetX = 0.5f; float soffsetY = 0.5f; float scale = 0.5f; D3DXMATRIX shadowTweak( scale, 0.0f, 0.0f, 0.0f, 0.0f, -scale, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, soffsetX, soffsetY, currentBias, 1.0f ); D3DXMatrixMultiply(&shadowProjection[i], &lightProjection, &shadowTweak); D3DXMatrixMultiply(&shadowProjection[i], &lightView[i], &shadowProjection[i]); D3DXMatrixMultiply(&lightViewProjection[i], &lightView[i], &lightProjection); shaderProjection[i] = shadowProjection[i]; D3DXMatrixMultiply(&shadowProjection[i], &cameraMatrix, &shadowProjection[i]); } { float xf = (1.f / resolutionX * .5f); float yf = (1.f / resolutionY * .5f); float sX = soffsetX + (2 * targetPos.x * soffsetX) - xf; float sY = soffsetY + (2 * targetPos.y * soffsetY) - yf; D3DXMATRIX shadowTweak( scaleX, 0.0f, 0.0f, 0.0f, 0.0f, -scaleY, 0.0f, 0.0f, 0.0f, 0.0f, float(tweakRange), 0.0f, sX, sY, bias, 1.0f ); D3DXMatrixMultiply(&targetProjection, &lightProjection, &shadowTweak); D3DXMatrixMultiply(&targetProjection, &lightView[0], &targetProjection); } }