Large diffs are not rendered by default.

@@ -44,6 +44,10 @@ class OculusVRDevice : public IInputDevice, public IDisplayDevice
// If no HMD is present simulate it being available
static bool smSimulateHMD;

// Use the chromatic aberration correction version of the barrel
// distortion shader.
static bool smUseChromaticAberrationCorrection;

// Type of rotation events to broadcast
static bool smGenerateAngleAxisRotationEvents;
static bool smGenerateEulerRotationEvents;
@@ -55,6 +59,9 @@ class OculusVRDevice : public IInputDevice, public IDisplayDevice
// as measured from a vector pointing straight up (in degrees)
static F32 smMaximumAxisAngle;

// Broadcast sensor raw data: acceleration, angular velocity, magnetometer reading
static bool smGenerateSensorRawEvents;

// Indicates that a whole frame event should be generated and frames
// should be buffered.
static bool smGenerateWholeFrameEvents;
@@ -131,14 +138,24 @@ class OculusVRDevice : public IInputDevice, public IDisplayDevice
// HMDs
U32 getHMDCount() const { return mHMDDevices.size(); }
const OculusVRHMDDevice* getHMDDevice(U32 index) const;
F32 getHMDCurrentIPD(U32 index);
void setHMDCurrentIPD(U32 index, F32 ipd);

// Sensors
U32 getSensorCount() const { return mSensorDevices.size(); }
const OculusVRSensorDevice* getSensorDevice(U32 index) const;
EulerF getSensorEulerRotation(U32 index);
VectorF getSensorAcceleration(U32 index);
EulerF getSensorAngularVelocity(U32 index);
VectorF getSensorMagnetometer(U32 index);
F32 getSensorPredictionTime(U32 index);
void setSensorPredictionTime(U32 index, F32 dt);
void setAllSensorPredictionTime(F32 dt);
bool getSensorGravityCorrection(U32 index);
void setSensorGravityCorrection(U32 index, bool state);
bool getSensorYawCorrection(U32 index);
void setSensorYawCorrection(U32 index, bool state);
bool getSensorMagnetometerCalibrated(U32 index);
void resetAllSensors();

public:
@@ -58,6 +58,10 @@ void OculusVRHMDDevice::set(OVR::HMDDevice* hmd, OVR::HMDInfo& info, bool calcul
mVersion = info.Version;

mDisplayDeviceName = info.DisplayDeviceName;
mDisplayId = info.DisplayId;

mDesktopPosition.x = info.DesktopX;
mDesktopPosition.y = info.DesktopY;

mResolution.x = info.HResolution;
mResolution.y = info.VResolution;
@@ -68,13 +72,19 @@ void OculusVRHMDDevice::set(OVR::HMDDevice* hmd, OVR::HMDInfo& info, bool calcul
mVerticalEyeCenter = info.VScreenCenter;
mEyeToScreen = info.EyeToScreenDistance;
mLensSeparation = info.LensSeparationDistance;
mInterpupillaryDistance = info.InterpupillaryDistance;
mProfileInterpupillaryDistance = info.InterpupillaryDistance;
mInterpupillaryDistance = mProfileInterpupillaryDistance;

mKDistortion.x = info.DistortionK[0];
mKDistortion.y = info.DistortionK[1];
mKDistortion.z = info.DistortionK[2];
mKDistortion.w = info.DistortionK[3];

mChromaticAbCorrection.x = info.ChromaAbCorrection[0];
mChromaticAbCorrection.y = info.ChromaAbCorrection[1];
mChromaticAbCorrection.z = info.ChromaAbCorrection[2];
mChromaticAbCorrection.w = info.ChromaAbCorrection[3];

// Calculated values
calculateValues(calculateDistortionScale);

@@ -109,13 +119,27 @@ void OculusVRHMDDevice::createSimulatedPreviewRift(bool calculateDistortionScale
mVerticalEyeCenter = 0.046799999f;
mEyeToScreen = 0.041000001f;
mLensSeparation = 0.064000003f;
mInterpupillaryDistance = 0.064000003f;
mProfileInterpupillaryDistance = 0.064000003f;
mInterpupillaryDistance = mProfileInterpupillaryDistance;

mKDistortion.x = 1.0000000f;
mKDistortion.y = 0.22000000f;
mKDistortion.z = 0.23999999f;
mKDistortion.w = 0.00000000f;

mChromaticAbCorrection.x = 0.995999f;
mChromaticAbCorrection.y = -0.004f;
mChromaticAbCorrection.z = 1.014f;
mChromaticAbCorrection.z = 0.0f;

calculateValues(calculateDistortionScale);
}

void OculusVRHMDDevice::setIPD(F32 ipd, bool calculateDistortionScale)
{
mInterpupillaryDistance = ipd;

// Recalculate as some values rely on the IPD
calculateValues(calculateDistortionScale);
}

@@ -54,6 +54,12 @@ class OculusVRHMDDevice
// Windows display device name used in EnumDisplaySettings/CreateDC
String mDisplayDeviceName;

// MacOS display ID
S32 mDisplayId;

// Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
Point2I mDesktopPosition;

// Whole screen resolution
Point2I mResolution;

@@ -70,6 +76,9 @@ class OculusVRHMDDevice
// Physical distance between lens centers, in meters
F32 mLensSeparation;

// Physical distance between the user's eye centers as defined in the current profile
F32 mProfileInterpupillaryDistance;

// Physical distance between the user's eye centers
F32 mInterpupillaryDistance;

@@ -79,6 +88,9 @@ class OculusVRHMDDevice
// Radial distortion correction coefficients used by the barrel distortion shader
Point4F mKDistortion;

// Chromatic aberration correction coefficients
Point4F mChromaticAbCorrection;

// Calculated values of eye x offset from center in normalized (uv) coordinates
// where each eye is 0..1. Used for the mono to stereo postFX to simulate an
// eye offset of the camera. The x component is the left eye, the y component
@@ -137,6 +149,12 @@ class OculusVRHMDDevice
// Windows display device name used in EnumDisplaySettings/CreateDC
const char* getDisplayDeviceName() const { return mDisplayDeviceName.c_str(); }

// MacOS display ID
S32 getDisplayDeviceId() const { return mDisplayId; }

// Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
const Point2I& getDesktopPosition() const { return mDesktopPosition; }

// Whole screen resolution
const Point2I& getResolution() const { return mResolution; }

@@ -153,15 +171,24 @@ class OculusVRHMDDevice
// Physical distance between lens centers, in meters
F32 getLensSeparation() const { return mLensSeparation; }

// Physical distance between the user's eye centers as defined by the current profile
F32 getProfileIPD() const { return mProfileInterpupillaryDistance; }

// Physical distance between the user's eye centers
F32 getIPD() const { return mInterpupillaryDistance; }

// Set a new physical distance between the user's eye centers
void setIPD(F32 ipd, bool calculateDistortionScale);

// Provides the IPD of one eye as a Point3F
const Point3F& getEyeWorldOffset() const { return mEyeWorldOffset; }

// Radial distortion correction coefficients used by the barrel distortion shader
const Point4F& getKDistortion() const { return mKDistortion; }

// Chromatic aberration correction coefficients used by the barrel distortion shader
const Point4F& getChromaticAbCorrection() const { return mChromaticAbCorrection; }

// Calculated values of eye x offset from center in normalized (uv) coordinates.
const Point2F& getEyeUVOffset() const { return mEyeUVOffset; }

@@ -56,6 +56,24 @@ void OculusVRSensorData::setData(OVR::SensorFusion& data, const F32& maxAxisRadi
// Sensor rotation as axis
OculusVRUtil::calculateAxisRotation(mRot, maxAxisRadius, mRotAxis);

// Sensor raw values
OVR::Vector3f accel = data.GetAcceleration();
OculusVRUtil::convertAcceleration(accel, mAcceleration);

OVR::Vector3f angVel = data.GetAngularVelocity();
OculusVRUtil::convertAngularVelocity(angVel, mAngVelocity);

OVR::Vector3f mag;
if(data.HasMagCalibration() && data.IsYawCorrectionEnabled())
{
mag = data.GetCalibratedMagnetometer();
}
else
{
mag = data.GetMagnetometer();
}
OculusVRUtil::convertMagnetometer(mag, mMagnetometer);

mDataSet = true;
}

@@ -69,6 +87,11 @@ void OculusVRSensorData::simulateData(const F32& maxAxisRadius)
// Sensor rotation as axis
OculusVRUtil::calculateAxisRotation(mRot, maxAxisRadius, mRotAxis);

// Sensor raw values
mAcceleration.zero();
mAngVelocity.zero();
mMagnetometer.zero();

mDataSet = true;
}

@@ -92,5 +115,19 @@ U32 OculusVRSensorData::compare(OculusVRSensorData* other)
result |= DIFF_ROTAXISY;
}

// Check raw values
if(mAcceleration.x != other->mAcceleration.x || mAcceleration.y != other->mAcceleration.y || mAcceleration.z != other->mAcceleration.z || !mDataSet)
{
result |= DIFF_ACCEL;
}
if(mAngVelocity.x != other->mAngVelocity.x || mAngVelocity.y != other->mAngVelocity.y || mAngVelocity.z != other->mAngVelocity.z || !mDataSet)
{
result |= DIFF_ANGVEL;
}
if(mMagnetometer.x != other->mMagnetometer.x || mMagnetometer.y != other->mMagnetometer.y || mMagnetometer.z != other->mMagnetometer.z || !mDataSet)
{
result |= DIFF_MAG;
}

return result;
}
@@ -36,8 +36,12 @@ struct OculusVRSensorData
DIFF_ROT = (1<<0),
DIFF_ROTAXISX = (1<<1),
DIFF_ROTAXISY = (1<<2),
DIFF_ACCEL = (1<<3),
DIFF_ANGVEL = (1<<4),
DIFF_MAG = (1<<5),

DIFF_ROTAXIS = (DIFF_ROTAXISX | DIFF_ROTAXISY),
DIFF_RAW = (DIFF_ACCEL | DIFF_ANGVEL | DIFF_MAG),
};

bool mDataSet;
@@ -50,6 +54,11 @@ struct OculusVRSensorData
// Controller rotation as axis x, y
Point2F mRotAxis;

// Raw values
VectorF mAcceleration;
EulerF mAngVelocity;
VectorF mMagnetometer;

OculusVRSensorData();

/// Reset the data
@@ -29,6 +29,9 @@ U32 OculusVRSensorDevice::OVR_SENSORROT[OculusVRConstants::MaxSensors] = {0};
U32 OculusVRSensorDevice::OVR_SENSORROTANG[OculusVRConstants::MaxSensors] = {0};
U32 OculusVRSensorDevice::OVR_SENSORROTAXISX[OculusVRConstants::MaxSensors] = {0};
U32 OculusVRSensorDevice::OVR_SENSORROTAXISY[OculusVRConstants::MaxSensors] = {0};
U32 OculusVRSensorDevice::OVR_SENSORACCELERATION[OculusVRConstants::MaxSensors] = {0};
U32 OculusVRSensorDevice::OVR_SENSORANGVEL[OculusVRConstants::MaxSensors] = {0};
U32 OculusVRSensorDevice::OVR_SENSORMAGNETOMETER[OculusVRConstants::MaxSensors] = {0};

OculusVRSensorDevice::OculusVRSensorDevice()
{
@@ -74,6 +77,7 @@ void OculusVRSensorDevice::set(OVR::SensorDevice* sensor, OVR::SensorInfo& info,

mDevice = sensor;
mSensorFusion.AttachToSensor(sensor);
mYawCorrectionDisabled = !mSensorFusion.IsYawCorrectionEnabled();

// DeviceInfo
mProductName = info.ProductName;
@@ -110,6 +114,7 @@ void OculusVRSensorDevice::createSimulatedPreviewRift(S32 actionCodeIndex)
{
mIsValid = false;
mIsSimulation = true;
mYawCorrectionDisabled = true;

// DeviceInfo
mProductName = "Tracker DK";
@@ -145,6 +150,10 @@ void OculusVRSensorDevice::buildCodeTable()

OVR_SENSORROTAXISX[i] = INPUTMGR->getNextDeviceCode();
OVR_SENSORROTAXISY[i] = INPUTMGR->getNextDeviceCode();

OVR_SENSORACCELERATION[i] = INPUTMGR->getNextDeviceCode();
OVR_SENSORANGVEL[i] = INPUTMGR->getNextDeviceCode();
OVR_SENSORMAGNETOMETER[i] = INPUTMGR->getNextDeviceCode();
}

// Build out the virtual map
@@ -155,16 +164,27 @@ void OculusVRSensorDevice::buildCodeTable()
INPUTMGR->addVirtualMap( buffer, SI_ROT, OVR_SENSORROT[i] );

dSprintf(buffer, 64, "ovr_sensorrotang%d", i);
INPUTMGR->addVirtualMap( buffer, SI_ROT, OVR_SENSORROTANG[i] );
INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORROTANG[i] );

dSprintf(buffer, 64, "ovr_sensorrotaxisx%d", i);
INPUTMGR->addVirtualMap( buffer, SI_AXIS, OVR_SENSORROTAXISX[i] );
dSprintf(buffer, 64, "ovr_sensorrotaxisy%d", i);
INPUTMGR->addVirtualMap( buffer, SI_AXIS, OVR_SENSORROTAXISY[i] );

dSprintf(buffer, 64, "ovr_sensoracceleration%d", i);
INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORACCELERATION[i] );

dSprintf(buffer, 64, "ovr_sensorangvel%d", i);
INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORANGVEL[i] );

dSprintf(buffer, 64, "ovr_sensormagnetometer%d", i);
INPUTMGR->addVirtualMap( buffer, SI_POS, OVR_SENSORMAGNETOMETER[i] );
}
}

bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius)
//-----------------------------------------------------------------------------

bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius, bool generateRawSensor)
{
if(!mIsValid)
return false;
@@ -215,9 +235,32 @@ bool OculusVRSensorDevice::process(U32 deviceType, bool generateRotAsAngAxis, bo
INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_AXIS, OVR_SENSORROTAXISY[mActionCodeIndex], SI_MOVE, currentBuffer->mRotAxis.y);
}

// Raw sensor event
if(generateRawSensor && diff & OculusVRSensorData::DIFF_RAW)
{
if(diff & OculusVRSensorData::DIFF_ACCEL)
INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_POS, OVR_SENSORACCELERATION[mActionCodeIndex], SI_MOVE, currentBuffer->mAcceleration);

if(diff & OculusVRSensorData::DIFF_ANGVEL)
{
// Convert angles to degrees
VectorF angles;
for(U32 i=0; i<3; ++i)
{
angles[i] = mRadToDeg(currentBuffer->mAngVelocity[i]);
}
INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_POS, OVR_SENSORANGVEL[mActionCodeIndex], SI_MOVE, angles);
}

if(diff & OculusVRSensorData::DIFF_MAG)
INPUTMGR->buildInputEvent(deviceType, OculusVRConstants::DefaultOVRBase, SI_POS, OVR_SENSORMAGNETOMETER[mActionCodeIndex], SI_MOVE, currentBuffer->mMagnetometer);
}

return true;
}

//-----------------------------------------------------------------------------

void OculusVRSensorDevice::reset()
{
if(!mIsValid)
@@ -242,6 +285,51 @@ void OculusVRSensorDevice::setPredictionTime(F32 dt)
mSensorFusion.SetPrediction(dt);
}

bool OculusVRSensorDevice::getGravityCorrection() const
{
if(!mIsValid)
return false;

return mSensorFusion.IsGravityEnabled();
}

void OculusVRSensorDevice::setGravityCorrection(bool state)
{
if(!mIsValid)
return;

mSensorFusion.SetGravityEnabled(state);
}

bool OculusVRSensorDevice::getYawCorrection() const
{
if(!mIsValid)
return false;

return mSensorFusion.IsYawCorrectionEnabled();
}

void OculusVRSensorDevice::setYawCorrection(bool state)
{
if(!mIsValid)
return;

if(mYawCorrectionDisabled || !mSensorFusion.HasMagCalibration())
return;

mSensorFusion.SetYawCorrectionEnabled(state);
}

bool OculusVRSensorDevice::getMagnetometerCalibrationAvailable() const
{
if(!mIsValid)
return false;

return mSensorFusion.HasMagCalibration();
}

//-----------------------------------------------------------------------------

EulerF OculusVRSensorDevice::getEulerRotation()
{
if(!mIsValid)
@@ -263,3 +351,82 @@ EulerF OculusVRSensorDevice::getEulerRotation()

return rot;
}

EulerF OculusVRSensorDevice::getRawEulerRotation()
{
if(!mIsValid)
return Point3F::Zero;

OVR::Quatf orientation;
orientation = mSensorFusion.GetOrientation();

// Sensor rotation in Euler format
EulerF rot;
OculusVRUtil::convertRotation(orientation, rot);

return rot;
}

VectorF OculusVRSensorDevice::getAcceleration()
{
if(!mIsValid)
return VectorF::Zero;

OVR::Vector3f a = mSensorFusion.GetAcceleration();

// Sensor acceleration in VectorF format
VectorF acceleration;
OculusVRUtil::convertAcceleration(a, acceleration);

return acceleration;
}

EulerF OculusVRSensorDevice::getAngularVelocity()
{
if(!mIsValid)
return EulerF::Zero;

OVR::Vector3f v = mSensorFusion.GetAngularVelocity();

// Sensor angular velocity in EulerF format
EulerF vel;
OculusVRUtil::convertAngularVelocity(v, vel);

return vel;
}

VectorF OculusVRSensorDevice::getMagnetometer()
{
if(!mIsValid)
return VectorF::Zero;

OVR::Vector3f m;
if(mSensorFusion.HasMagCalibration() && mSensorFusion.IsYawCorrectionEnabled())
{
m = mSensorFusion.GetCalibratedMagnetometer();
}
else
{
m = mSensorFusion.GetMagnetometer();
}

// Sensor magnetometer reading in VectorF format
VectorF mag;
OculusVRUtil::convertMagnetometer(m, mag);

return mag;
}

VectorF OculusVRSensorDevice::getRawMagnetometer()
{
if(!mIsValid)
return VectorF::Zero;

OVR::Vector3f m = mSensorFusion.GetMagnetometer();

// Sensor magnetometer reading in VectorF format
VectorF mag;
OculusVRUtil::convertMagnetometer(m, mag);

return mag;
}
@@ -50,6 +50,10 @@ class OculusVRSensorDevice
static U32 OVR_SENSORROTAXISX[OculusVRConstants::MaxSensors]; // SI_AXIS
static U32 OVR_SENSORROTAXISY[OculusVRConstants::MaxSensors];

static U32 OVR_SENSORACCELERATION[OculusVRConstants::MaxSensors]; // SI_POS
static U32 OVR_SENSORANGVEL[OculusVRConstants::MaxSensors]; // SI_POS but is EulerF
static U32 OVR_SENSORMAGNETOMETER[OculusVRConstants::MaxSensors]; // SI_POS

protected:
bool mIsValid;

@@ -69,6 +73,9 @@ class OculusVRSensorDevice
U16 mProductId;
String mSerialNumber;

// Has yaw correction been disabled by the control panel
bool mYawCorrectionDisabled;

// Assigned by the OculusVRDevice
S32 mActionCodeIndex;

@@ -99,7 +106,7 @@ class OculusVRSensorDevice
bool isValid() const {return mIsValid;}
bool isSimulated() {return mIsSimulation;}

bool process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius);
bool process(U32 deviceType, bool generateRotAsAngAxis, bool generateRotAsEuler, bool generateRotationAsAxisEvents, F32 maxAxisRadius, bool generateRawSensor);

void reset();

@@ -109,14 +116,51 @@ class OculusVRSensorDevice
// Set the prediction time for the sensor fusion. The time is in seconds.
void setPredictionTime(F32 dt);

// Is gravity correction enabled for pitch and roll
bool getGravityCorrection() const;

// Set the pitch and roll gravity correction
void setGravityCorrection(bool state);

// Has yaw correction been disabled using the control panel
bool getYawCorrectionUserDisabled() const { return mYawCorrectionDisabled; }

// Is yaw correction enabled
bool getYawCorrection() const;

// Set the yaw correction. Note: if magnetometer calibration data is not present,
// or user has disabled yaw correction in the control panel, this method will
// not enable it.
void setYawCorrection(bool state);

// Is magnetometer calibration data available for this sensor
bool getMagnetometerCalibrationAvailable() const;

const char* getProductName() { return mProductName.c_str(); }
const char* getManufacturer() { return mManufacturer.c_str(); }
U32 getVersion() { return mVersion; }
U16 getVendorId() { return mVendorId; }
U16 getProductId() { return mProductId; }
const char* getSerialNumber() { return mSerialNumber; }

// Get the current rotation of the sensor. Uses prediction if set.
EulerF getEulerRotation();

// Get the current rotation of the sensor.
EulerF getRawEulerRotation();

// Get the current absolute acceleration reading, in m/s^2
VectorF getAcceleration();

// Get the current angular velocity reading, in rad/s
EulerF getAngularVelocity();

// Get the current magnetometer reading (direction and field strength), in Gauss.
// Uses magnetometer calibration if set.
VectorF getMagnetometer();

// Get the current raw magnetometer reading (direction and field strength), in Gauss
VectorF getRawMagnetometer();
};

#endif // _OCULUSVRSENSORDEVICE_H_
@@ -73,4 +73,19 @@ void calculateAxisRotation(const MatrixF& inRotation, const F32& maxAxisRadius,
outRotation.y = axis.y;
}

}
void convertAcceleration(OVR::Vector3f& inAcceleration, VectorF& outAcceleration)
{
outAcceleration.set(inAcceleration.x, -inAcceleration.z, inAcceleration.y);
}

void convertAngularVelocity(OVR::Vector3f& inAngVel, EulerF& outAngVel)
{
outAngVel.set(-inAngVel.x, inAngVel.z, -inAngVel.y);
}

void convertMagnetometer(OVR::Vector3f& inMagnetometer, VectorF& outMagnetometer)
{
outMagnetometer.set(inMagnetometer.x, -inMagnetometer.z, inMagnetometer.y);
}

}
@@ -37,6 +37,15 @@ namespace OculusVRUtil

/// Calcualte a sensor's rotation as if it were a thumb stick axis
void calculateAxisRotation(const MatrixF& inRotation, const F32& maxAxisRadius, Point2F& outRotation);

/// Convert an OVR sensor's acceleration to Torque 3D vector (in m/s^2)
void convertAcceleration(OVR::Vector3f& inAcceleration, VectorF& outAcceleration);

/// Convert OVR sensor's angular velocity to Torque 3D Euler angles (in radians/s)
void convertAngularVelocity(OVR::Vector3f& inAngVel, EulerF& outAngVel);

/// Convert an OVR sensor's magnetometer reading (direction and field strength) to Torque 3D vector (in Gauss)
void convertMagnetometer(OVR::Vector3f& inMagnetometer, VectorF& outMagnetometer);
}

#endif // _OCULUSVRUTIL_H_
@@ -63,7 +63,14 @@ function enableOculusVRDisplay(%gameConnection, %trueStereoRendering)

if(%trueStereoRendering)
{
OVRBarrelDistortionPostFX.isEnabled = true;
if($pref::OculusVR::UseChromaticAberrationCorrection)
{
OVRBarrelDistortionChromaPostFX.isEnabled = true;
}
else
{
OVRBarrelDistortionPostFX.isEnabled = true;
}
}
else
{
@@ -81,6 +88,7 @@ function disableOculusVRDisplay(%gameConnection)
%gameConnection.clearDisplayDevice();
PlayGui.renderStyle = "standard";
OVRBarrelDistortionPostFX.isEnabled = false;
OVRBarrelDistortionChromaPostFX.isEnabled = false;
OVRBarrelDistortionMonoPostFX.isEnabled = false;
}

@@ -112,7 +120,7 @@ function setStandardOculusVRControlScheme(%gameConnection)
function setVideoModeForOculusVRDisplay(%fullscreen)
{
%res = getOVRHMDResolution(0);
Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 0);
Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 4);
}

//-----------------------------------------------------------------------------
@@ -44,6 +44,14 @@ singleton ShaderData( OVRBarrelDistortionShader )
pixVersion = 2.0;
};

singleton ShaderData( OVRBarrelDistortionChromaShader )
{
DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
DXPixelShaderFile = "shaders/common/postFx/oculusvr/barrelDistortionChromaP.hlsl";

pixVersion = 2.0;
};

//-----------------------------------------------------------------------------
// GFX state blocks
//-----------------------------------------------------------------------------
@@ -78,6 +86,32 @@ singleton BarrelDistortionPostEffect( OVRBarrelDistortionPostFX )
scaleOutput = 1.25;
};

//-----------------------------------------------------------------------------
// Barrel Distortion with Chromatic Aberration Correction PostFx
//
// To be used with the Oculus Rift.
// Expects a stereo pair to exist on the back buffer and then applies the
// appropriate barrel distortion.
// This version applies a chromatic aberration correction during the
// barrel distortion.
//-----------------------------------------------------------------------------
singleton BarrelDistortionPostEffect( OVRBarrelDistortionChromaPostFX )
{
isEnabled = false;
allowReflectPass = false;

renderTime = "PFXAfterDiffuse";
renderPriority = 100;

// The barrel distortion
shader = OVRBarrelDistortionChromaShader;
stateBlock = OVRBarrelDistortionStateBlock;

texture[0] = "$backBuffer";

scaleOutput = 1.25;
};

//-----------------------------------------------------------------------------
// Barrel Distortion Mono PostFx
//
@@ -0,0 +1,95 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "shadergen:/autogenConditioners.h"
#include "../postFx.hlsl"
#include "../../torque.hlsl"

uniform sampler2D backBuffer : register(S0);

uniform float3 LensCenter; // x=Left X, y=Right X, z=Y
uniform float2 ScreenCenter;
uniform float2 Scale;
uniform float2 ScaleIn;
uniform float4 HmdWarpParam;
uniform float4 HmdChromaAbParam; // Chromatic aberration correction

float4 main( PFXVertToPix IN ) : COLOR0
{
float2 texCoord;
float xOffset;
float2 lensCenter;
lensCenter.y = LensCenter.z;
if(IN.uv0.x < 0.5)
{
texCoord.x = IN.uv0.x;
texCoord.y = IN.uv0.y;
xOffset = 0.0;
lensCenter.x = LensCenter.x;
}
else
{
texCoord.x = IN.uv0.x - 0.5;
texCoord.y = IN.uv0.y;
xOffset = 0.5;
lensCenter.x = LensCenter.y;
}

// Scales input texture coordinates for distortion.
// ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
// larger due to aspect ratio.
float2 theta = (texCoord - lensCenter) * ScaleIn; // Scales to [-1, 1]
float rSq = theta.x * theta.x + theta.y * theta.y;
float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);

// Detect whether blue texture coordinates are out of range
// since these will scaled out the furthest.
float2 thetaBlue = theta1 * (HmdChromaAbParam.z + HmdChromaAbParam.w * rSq);
float2 tcBlue = lensCenter + Scale * thetaBlue;

float4 color;
if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))
{
color = float4(0,0,0,0);
}
else
{
// Now do blue texture lookup.
tcBlue.x += xOffset;
float blue = tex2D(backBuffer, tcBlue).b;

// Do green lookup (no scaling).
float2 tcGreen = lensCenter + Scale * theta1;
tcGreen.x += xOffset;
float green = tex2D(backBuffer, tcGreen).g;

// Do red scale and lookup.
float2 thetaRed = theta1 * (HmdChromaAbParam.x + HmdChromaAbParam.y * rSq);
float2 tcRed = lensCenter + Scale * thetaRed;
tcRed.x += xOffset;
float red = tex2D(backBuffer, tcRed).r;

color = float4(red, green, blue, 1);
}

return color;
}
@@ -63,7 +63,14 @@ function enableOculusVRDisplay(%gameConnection, %trueStereoRendering)

if(%trueStereoRendering)
{
OVRBarrelDistortionPostFX.isEnabled = true;
if($pref::OculusVR::UseChromaticAberrationCorrection)
{
OVRBarrelDistortionChromaPostFX.isEnabled = true;
}
else
{
OVRBarrelDistortionPostFX.isEnabled = true;
}
}
else
{
@@ -81,6 +88,7 @@ function disableOculusVRDisplay(%gameConnection)
%gameConnection.clearDisplayDevice();
PlayGui.renderStyle = "standard";
OVRBarrelDistortionPostFX.isEnabled = false;
OVRBarrelDistortionChromaPostFX.isEnabled = false;
OVRBarrelDistortionMonoPostFX.isEnabled = false;
}

@@ -112,7 +120,7 @@ function setStandardOculusVRControlScheme(%gameConnection)
function setVideoModeForOculusVRDisplay(%fullscreen)
{
%res = getOVRHMDResolution(0);
Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 0);
Canvas.setVideoMode(%res.x, %res.y, %fullscreen, 32, 4);
}

//-----------------------------------------------------------------------------
@@ -44,6 +44,14 @@ singleton ShaderData( OVRBarrelDistortionShader )
pixVersion = 2.0;
};

singleton ShaderData( OVRBarrelDistortionChromaShader )
{
DXVertexShaderFile = "shaders/common/postFx/postFxV.hlsl";
DXPixelShaderFile = "shaders/common/postFx/oculusvr/barrelDistortionChromaP.hlsl";

pixVersion = 2.0;
};

//-----------------------------------------------------------------------------
// GFX state blocks
//-----------------------------------------------------------------------------
@@ -78,6 +86,32 @@ singleton BarrelDistortionPostEffect( OVRBarrelDistortionPostFX )
scaleOutput = 1.25;
};

//-----------------------------------------------------------------------------
// Barrel Distortion with Chromatic Aberration Correction PostFx
//
// To be used with the Oculus Rift.
// Expects a stereo pair to exist on the back buffer and then applies the
// appropriate barrel distortion.
// This version applies a chromatic aberration correction during the
// barrel distortion.
//-----------------------------------------------------------------------------
singleton BarrelDistortionPostEffect( OVRBarrelDistortionChromaPostFX )
{
isEnabled = false;
allowReflectPass = false;

renderTime = "PFXAfterDiffuse";
renderPriority = 100;

// The barrel distortion
shader = OVRBarrelDistortionChromaShader;
stateBlock = OVRBarrelDistortionStateBlock;

texture[0] = "$backBuffer";

scaleOutput = 1.25;
};

//-----------------------------------------------------------------------------
// Barrel Distortion Mono PostFx
//
@@ -0,0 +1,95 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "shadergen:/autogenConditioners.h"
#include "../postFx.hlsl"
#include "../../torque.hlsl"

uniform sampler2D backBuffer : register(S0);

uniform float3 LensCenter; // x=Left X, y=Right X, z=Y
uniform float2 ScreenCenter;
uniform float2 Scale;
uniform float2 ScaleIn;
uniform float4 HmdWarpParam;
uniform float4 HmdChromaAbParam; // Chromatic aberration correction

float4 main( PFXVertToPix IN ) : COLOR0
{
float2 texCoord;
float xOffset;
float2 lensCenter;
lensCenter.y = LensCenter.z;
if(IN.uv0.x < 0.5)
{
texCoord.x = IN.uv0.x;
texCoord.y = IN.uv0.y;
xOffset = 0.0;
lensCenter.x = LensCenter.x;
}
else
{
texCoord.x = IN.uv0.x - 0.5;
texCoord.y = IN.uv0.y;
xOffset = 0.5;
lensCenter.x = LensCenter.y;
}

// Scales input texture coordinates for distortion.
// ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
// larger due to aspect ratio.
float2 theta = (texCoord - lensCenter) * ScaleIn; // Scales to [-1, 1]
float rSq = theta.x * theta.x + theta.y * theta.y;
float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);

// Detect whether blue texture coordinates are out of range
// since these will scaled out the furthest.
float2 thetaBlue = theta1 * (HmdChromaAbParam.z + HmdChromaAbParam.w * rSq);
float2 tcBlue = lensCenter + Scale * thetaBlue;

float4 color;
if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))
{
color = float4(0,0,0,0);
}
else
{
// Now do blue texture lookup.
tcBlue.x += xOffset;
float blue = tex2D(backBuffer, tcBlue).b;

// Do green lookup (no scaling).
float2 tcGreen = lensCenter + Scale * theta1;
tcGreen.x += xOffset;
float green = tex2D(backBuffer, tcGreen).g;

// Do red scale and lookup.
float2 thetaRed = theta1 * (HmdChromaAbParam.x + HmdChromaAbParam.y * rSq);
float2 tcRed = lensCenter + Scale * thetaRed;
tcRed.x += xOffset;
float red = tex2D(backBuffer, tcRed).r;

color = float4(red, green, blue, 1);
}

return color;
}