Here is the new method to update the projection matrices for both left/right eye:
(please post if you find anything dubious here)
Code: Select all
/**
* 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);
// 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)
// ALL stated in meters here !
const float nearClippingPlaneDistance = 1; // < TODO !! Assumption here : near clipping plane distance = 1 meter
float frustumAsymmetryInMeters = ((ipd/2) * nearClippingPlaneDistance) / convergence;
// divide the frustum asymmetry by the assumed physical size of the physical screen
const float physicalScreenSizeInMeters = 1; // < TODO !! Assumption here : physical screen size = 1 meter
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);
}
That means, if convergence is set to 3.0f, the neutral plane is 3 meters ahead. Here is a video of Left4Dead anaglyph rendering using the new driver architecture : (In this case i did set convergence to 3.0f - 3 meters, world scale is set game-specific to 4.15f - so our view is focused to 3 meters ahead)
[youtube-hd]http://www.youtube.com/watch?v=yTQXFPwE ... e=youtu.be[/youtube-hd]