/** * Updates left and right projection matrices. * Now, the convergence point is specified in real, physical meters, since the IPD is also specified * in physical meters. That means, if the game-specific world scale is set correctly, a convergence * value of 3.0f would mean that the virtual screen, neutral point or convergence point is 3 meters * ahead of us. * @param aspectRation The aspect ratio for the projection matrix. ***/ void ViewAdjustment::UpdateProjectionMatrices(float aspectRatio) { t = 0.5f / aspectRatio; b = -0.5f / aspectRatio; D3DXMatrixPerspectiveOffCenterLH(&matProjection, l, r, b, t, n, f); D3DXMatrixInverse(&matProjectionInv, 0, &matProjection); // ALL stated in meters here ! screen size = horizontal size float nearClippingPlaneDistance = hmdInfo.eyeToScreenDistance; float physicalScreenSizeInMeters = hmdInfo.physicalScreenSize.first / 2; // if not HMD, set values to fullscreen defaults if ((stereoType != 26) && // != StereoView::StereoTypes::OCULUS_RIFT (stereoType != 27) && // != StereoView::StereoTypes::OCULUS_RIFT_CROPPED (stereoType != 25)) // != StereoView::StereoTypes::DIY_RIFT)) { // assumption here : // end user is placed 1 meter away from screen // end user screen is 1 meter in horizontal size nearClippingPlaneDistance = 1; physicalScreenSizeInMeters = 1; } // convergence frustum adjustment, based on NVidia explanations // // It is evident that the ratio of frustum shift to the near clipping plane is equal to the ratio of // IOD/2 to the distance from the screenplane. (IOD=IPD) // frustumAsymmetryInMeters = ((IPD/2) * nearClippingPlaneDistance) / convergence // <http://www.orthostereo.com/geometryopengl.html> // // (near clipping plane distance = physical screen distance) // (convergence = virtual screen distance) if (convergence <= nearClippingPlaneDistance) convergence = nearClippingPlaneDistance + 0.001f; float frustumAsymmetryInMeters = ((ipd/2) * nearClippingPlaneDistance) / convergence; // divide the frustum asymmetry by the assumed physical size of the physical screen float frustumAsymmetryLeftInMeters = (frustumAsymmetryInMeters * LEFT_CONSTANT) / physicalScreenSizeInMeters; float frustumAsymmetryRightInMeters = (frustumAsymmetryInMeters * RIGHT_CONSTANT) / physicalScreenSizeInMeters; // get the horizontal screen space size and compute screen space adjustment float screenSpaceXSize = abs(l)+abs(r); float multiplier = screenSpaceXSize/1; // = 1 meter float frustumAsymmetryLeft = frustumAsymmetryLeftInMeters * multiplier; float frustumAsymmetryRight = frustumAsymmetryRightInMeters * multiplier; // now, create the re-projection matrices for both eyes using this frustum asymmetry D3DXMatrixPerspectiveOffCenterLH(&projectLeft, l+frustumAsymmetryLeft, r+frustumAsymmetryLeft, b, t, n, f); D3DXMatrixPerspectiveOffCenterLH(&projectRight, l+frustumAsymmetryRight, r+frustumAsymmetryRight, b, t, n, f); }
void Window::setProjection(vrj::ProjectionPtr proj) { if (!mWindowIsOpen) { return; } const std::vector<float>& frust = proj->getFrustum().getValues(); D3DXMATRIX proj_matrix; ZeroMemory( &proj_matrix, sizeof( D3DXMATRIX ) ); D3DXMatrixPerspectiveOffCenterLH(&proj_matrix, frust[Frustum::VJ_LEFT], frust[Frustum::VJ_RIGHT], frust[Frustum::VJ_BOTTOM], frust[Frustum::VJ_TOP], frust[Frustum::VJ_NEAR], frust[Frustum::VJ_FAR]); mRenderDevice->SetTransform( D3DTS_PROJECTION, &proj_matrix ); #ifdef USE_PROJECTION_MATRIX mRenderDevice->MultiplyTransform( D3DTS_PROJECTION, (const D3DMATRIX*)&proj->getViewMatrix().mData); #endif #ifndef USE_PROJECTION_MATRIX D3DXMATRIX view_matrix; D3DXMatrixIdentity(view_matrix); mRenderDevice->SetTransform(D3DTS_VIEW, &view_matrix); mRenderDevice->MultiplyTransform( D3DTS_VIEW, &proj->getViewMatrix().mData); #endif }
void D3DProxyDeviceAdv::adjustEyeOffsetAndViewFrustum(D3DXMATRIX &outMatrix, D3DXMATRIX &inMatrix) { D3DXMATRIX transform; D3DXMatrixTranslation(&transform, separation*eyeShutter*10.0f+offset*10.0f, 0, 0); float adjustedFrustumOffset = convergence*eyeShutter*0.1f; D3DXMATRIX reProject; D3DXMatrixPerspectiveOffCenterLH(&reProject, l+adjustedFrustumOffset, r+adjustedFrustumOffset, b, t, n, f); if(trackerInitialized && tracker->isAvailable()) { D3DXMATRIX rollMatrix; D3DXMatrixRotationZ(&rollMatrix, tracker->currentRoll); D3DXMatrixMultiply(&transform, &transform, &rollMatrix); } outMatrix = inMatrix * invertProjection * transform * reProject; }
//-- Render ------------------------------------------------------------------- // Called once per frame. Do all rendering here. //----------------------------------------------------------------------------- extern "C" void Render() { bool configured = true; //FALSE; g_device->SetRenderState(D3DRS_SRCBLEND , D3DBLEND_ONE); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); g_device->SetRenderState(D3DRS_AMBIENT, 0xffffffff); g_device->SetRenderState(D3DRS_LIGHTING, FALSE); g_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); g_device->SetRenderState(D3DRS_ZENABLE, TRUE); g_device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); g_device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS); g_device->SetRenderState(D3DRS_FILLMODE, g_mode); g_device->SetFVF(VERTEX_FORMAT); g_device->SetPixelShader(NULL); g_device->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0); D3DXMATRIX matProjection; D3DXMatrixPerspectiveOffCenterLH(&matProjection, -1.0f, 1.0f, -1.0f, 1.0f, 1.5f, 10.0f); g_device->SetTransform(D3DTS_PROJECTION, &matProjection); D3DXMATRIX matView; D3DXMatrixIdentity(&matView); g_device->SetTransform(D3DTS_VIEW, &matView); if(configured) { x_angle += x_speed; if(x_angle >= 360.0f) x_angle -= 360.0f; y_angle += y_speed; if(y_angle >= 360.0f) y_angle -= 360.0f; z_angle += z_speed; if(z_angle >= 360.0f) z_angle -= 360.0f; draw_bars(); } }
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); } }