Oculus Rift Improvements

- Now requires OVR SDK 0.2.5
- New chromatic aberration correction shader.  Can be disabled by
setting $pref::OculusVR::UseChromaticAberrationCorrection to false prior
to enabling Rift display (such as for screen shots).
- FXAA on by default when using full screen on the Rift.
- Can now manually override IPD from script.  Otherwise value set in
profile is used.
- Raw sensor data now available through input events (set
$OculusVR::GenerateSensorRawEvents to true) and console methods.  The
raw data is acceleration, angular velocity, and magnetometer reading.
- Can determine if magnetometer calibration data is available using a
console method in order to notify the user.
This commit is contained in:
DavidWyand-GG 2013-10-19 00:46:39 -04:00
parent 8d2fcf2456
commit 85730dfb59
18 changed files with 985 additions and 20 deletions

View file

@ -42,6 +42,7 @@ IMPLEMENT_CONOBJECT(BarrelDistortionPostEffect);
BarrelDistortionPostEffect::BarrelDistortionPostEffect()
: PostEffect(),
mHmdWarpParamSC(NULL),
mHmdChromaAbSC(NULL),
mScaleSC(NULL),
mScaleInSC(NULL),
mLensCenterSC(NULL),
@ -85,23 +86,22 @@ void BarrelDistortionPostEffect::onRemove()
void BarrelDistortionPostEffect::_setupConstants( const SceneRenderState *state )
{
// Test if setup is required before calling the parent method as the parent method
// will set up the shader constants buffer for us.
bool setupRequired = mShaderConsts.isNull();
Parent::_setupConstants(state);
// Define the shader constants
if(!mHmdWarpParamSC)
if(setupRequired)
{
mHmdWarpParamSC = mShader->getShaderConstHandle( "$HmdWarpParam" );
if(!mScaleSC)
mHmdChromaAbSC = mShader->getShaderConstHandle( "$HmdChromaAbParam" );
mScaleSC = mShader->getShaderConstHandle( "$Scale" );
if(!mScaleInSC)
mScaleInSC = mShader->getShaderConstHandle( "$ScaleIn" );
if(!mLensCenterSC)
mLensCenterSC = mShader->getShaderConstHandle( "$LensCenter" );
if(!mScreenCenterSC)
mScreenCenterSC = mShader->getShaderConstHandle( "$ScreenCenter" );
}
const Point2I &resolution = GFX->getActiveRenderTarget()->getSize();
F32 widthScale = 0.5f;
@ -119,6 +119,12 @@ void BarrelDistortionPostEffect::_setupConstants( const SceneRenderState *state
mShaderConsts->set( mHmdWarpParamSC, distortion );
}
if(mHmdChromaAbSC->isValid())
{
const Point4F& correction = hmd->getChromaticAbCorrection();
mShaderConsts->set( mHmdChromaAbSC, correction );
}
if(mScaleSC->isValid())
{
F32 scaleFactor = hmd->getDistortionScale();
@ -149,6 +155,11 @@ void BarrelDistortionPostEffect::_setupConstants( const SceneRenderState *state
mShaderConsts->set( mHmdWarpParamSC, Point4F(0.0f, 0.0f, 0.0f, 0.0f) );
}
if(mHmdChromaAbSC->isValid())
{
mShaderConsts->set( mHmdChromaAbSC, Point4F(1.0f, 0.0f, 1.0f, 0.0f) );
}
if(mScaleSC->isValid())
{
mShaderConsts->set( mScaleSC, Point2F(1.0f, 1.0f) );

View file

@ -31,6 +31,7 @@ class BarrelDistortionPostEffect : public PostEffect
protected:
GFXShaderConstHandle *mHmdWarpParamSC;
GFXShaderConstHandle *mHmdChromaAbSC;
GFXShaderConstHandle *mScaleSC;
GFXShaderConstHandle *mScaleInSC;
GFXShaderConstHandle *mLensCenterSC;

View file

@ -60,12 +60,16 @@ bool OculusVRDevice::smEnableDevice = true;
bool OculusVRDevice::smSimulateHMD = true;
bool OculusVRDevice::smUseChromaticAberrationCorrection = true;
bool OculusVRDevice::smGenerateAngleAxisRotationEvents = true;
bool OculusVRDevice::smGenerateEulerRotationEvents = false;
bool OculusVRDevice::smGenerateRotationAsAxisEvents = false;
F32 OculusVRDevice::smMaximumAxisAngle = 25.0f;
bool OculusVRDevice::smGenerateSensorRawEvents = false;
bool OculusVRDevice::smGenerateWholeFrameEvents = false;
OculusVRDevice::OculusVRDevice()
@ -99,6 +103,10 @@ void OculusVRDevice::staticInit()
"@brief If true, the Oculus VR device will be enabled, if present.\n\n"
"@ingroup Game");
Con::addVariable("pref::OculusVR::UseChromaticAberrationCorrection", TypeBool, &smUseChromaticAberrationCorrection,
"@brief If true, Use the chromatic aberration correction version of the Oculus VR barrel distortion shader.\n\n"
"@ingroup Game");
Con::addVariable("OculusVR::GenerateAngleAxisRotationEvents", TypeBool, &smGenerateAngleAxisRotationEvents,
"@brief If true, broadcast sensor rotation events as angled axis.\n\n"
"@ingroup Game");
@ -114,6 +122,10 @@ void OculusVRDevice::staticInit()
"Should range from 0 to 90 degrees.\n\n"
"@ingroup Game");
Con::addVariable("OculusVR::GenerateSensorRawEvents", TypeBool, &smGenerateSensorRawEvents,
"@brief If ture, broadcast sensor raw data: acceleration, angular velocity, magnetometer reading.\n\n"
"@ingroup Game");
Con::addVariable("OculusVR::GenerateWholeFrameEvents", TypeBool, &smGenerateWholeFrameEvents,
"@brief Indicates that a whole frame event should be generated and frames should be buffered.\n\n"
"@ingroup Game");
@ -313,7 +325,7 @@ bool OculusVRDevice::process()
// Process each sensor
for(U32 i=0; i<mSensorDevices.size(); ++i)
{
mSensorDevices[i]->process(mDeviceType, smGenerateAngleAxisRotationEvents, smGenerateEulerRotationEvents, smGenerateRotationAsAxisEvents, maxAxisRadius);
mSensorDevices[i]->process(mDeviceType, smGenerateAngleAxisRotationEvents, smGenerateEulerRotationEvents, smGenerateRotationAsAxisEvents, maxAxisRadius, smGenerateSensorRawEvents);
}
return true;
@ -391,6 +403,22 @@ const OculusVRHMDDevice* OculusVRDevice::getHMDDevice(U32 index) const
return mHMDDevices[index];
}
F32 OculusVRDevice::getHMDCurrentIPD(U32 index)
{
if(index >= mHMDDevices.size())
return -1.0f;
return mHMDDevices[index]->getIPD();
}
void OculusVRDevice::setHMDCurrentIPD(U32 index, F32 ipd)
{
if(index >= mHMDDevices.size())
return;
return mHMDDevices[index]->setIPD(ipd, mScaleInputTexture);
}
//-----------------------------------------------------------------------------
const OculusVRSensorDevice* OculusVRDevice::getSensorDevice(U32 index) const
@ -409,6 +437,30 @@ EulerF OculusVRDevice::getSensorEulerRotation(U32 index)
return mSensorDevices[index]->getEulerRotation();
}
VectorF OculusVRDevice::getSensorAcceleration(U32 index)
{
if(index >= mSensorDevices.size())
return Point3F::Zero;
return mSensorDevices[index]->getAcceleration();
}
EulerF OculusVRDevice::getSensorAngularVelocity(U32 index)
{
if(index >= mSensorDevices.size())
return Point3F::Zero;
return mSensorDevices[index]->getAngularVelocity();
}
VectorF OculusVRDevice::getSensorMagnetometer(U32 index)
{
if(index >= mSensorDevices.size())
return Point3F::Zero;
return mSensorDevices[index]->getMagnetometer();
}
F32 OculusVRDevice::getSensorPredictionTime(U32 index)
{
const OculusVRSensorDevice* sensor = getSensorDevice(index);
@ -438,6 +490,57 @@ void OculusVRDevice::setAllSensorPredictionTime(F32 dt)
}
}
bool OculusVRDevice::getSensorGravityCorrection(U32 index)
{
const OculusVRSensorDevice* sensor = getSensorDevice(index);
if(!sensor || !sensor->isValid())
return false;
return sensor->getGravityCorrection();
}
void OculusVRDevice::setSensorGravityCorrection(U32 index, bool state)
{
if(index >= mSensorDevices.size())
return;
OculusVRSensorDevice* sensor = mSensorDevices[index];
if(!sensor->isValid())
return;
sensor->setGravityCorrection(state);
}
bool OculusVRDevice::getSensorYawCorrection(U32 index)
{
const OculusVRSensorDevice* sensor = getSensorDevice(index);
if(!sensor || !sensor->isValid())
return false;
return sensor->getYawCorrection();
}
void OculusVRDevice::setSensorYawCorrection(U32 index, bool state)
{
if(index >= mSensorDevices.size())
return;
OculusVRSensorDevice* sensor = mSensorDevices[index];
if(!sensor->isValid())
return;
sensor->setYawCorrection(state);
}
bool OculusVRDevice::getSensorMagnetometerCalibrated(U32 index)
{
const OculusVRSensorDevice* sensor = getSensorDevice(index);
if(!sensor || !sensor->isValid())
return false;
return sensor->getMagnetometerCalibrationAvailable();
}
void OculusVRDevice::resetAllSensors()
{
// Reset each sensor
@ -628,6 +731,46 @@ DefineEngineFunction(getOVRHMDDisplayDeviceName, const char*, (S32 index),,
return hmd->getDisplayDeviceName();
}
DefineEngineFunction(getOVRHMDDisplayDeviceId, S32, (S32 index),,
"@brief MacOS display ID.\n\n"
"@param index The HMD index.\n"
"@return The ID of the HMD display device, if any.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return -1;
}
const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
if(!hmd)
{
return -1;
}
return hmd->getDisplayDeviceId();
}
DefineEngineFunction(getOVRHMDDisplayDesktopPos, Point2I, (S32 index),,
"@brief Desktop coordinate position of the screen (can be negative; may not be present on all platforms).\n\n"
"@param index The HMD index.\n"
"@return Position of the screen.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return Point2I::Zero;
}
const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
if(!hmd)
{
return Point2I::Zero;
}
return hmd->getDesktopPosition();
}
DefineEngineFunction(getOVRHMDResolution, Point2I, (S32 index),,
"@brief Provides the OVR HMD screen resolution.\n\n"
"@param index The HMD index.\n"
@ -672,6 +815,78 @@ DefineEngineFunction(getOVRHMDDistortionCoefficients, String, (S32 index),,
return buf;
}
DefineEngineFunction(getOVRHMDChromaticAbCorrection, String, (S32 index),,
"@brief Provides the OVR HMD chromatic aberration correction values.\n\n"
"@param index The HMD index.\n"
"@return A four component string with the chromatic aberration correction values.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return "1 0 1 0";
}
const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
if(!hmd)
{
return "1 0 1 0";
}
const Point4F& c = hmd->getChromaticAbCorrection();
char buf[256];
dSprintf(buf, 256, "%g %g %g %g", c.x, c.y, c.z, c.w);
return buf;
}
DefineEngineFunction(getOVRHMDProfileIPD, F32, (S32 index),,
"@brief Physical distance between the user's eye centers as defined by the current profile.\n\n"
"@param index The HMD index.\n"
"@return The profile IPD.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return -1.0f;
}
const OculusVRHMDDevice* hmd = OCULUSVRDEV->getHMDDevice(index);
if(!hmd)
{
return -1.0f;
}
return hmd->getProfileIPD();
}
DefineEngineFunction(getOVRHMDCurrentIPD, F32, (S32 index),,
"@brief Physical distance between the user's eye centers.\n\n"
"@param index The HMD index.\n"
"@return The current IPD.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return -1.0f;
}
return OCULUSVRDEV->getHMDCurrentIPD(index);
}
DefineEngineFunction(setOVRHMDCurrentIPD, void, (S32 index, F32 ipd),,
"@brief Set the physical distance between the user's eye centers.\n\n"
"@param index The HMD index.\n"
"@param ipd The IPD to use.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return;
}
OCULUSVRDEV->setHMDCurrentIPD(index, ipd);
}
DefineEngineFunction(getOVRHMDEyeXOffsets, Point2F, (S32 index),,
"@brief Provides the OVR HMD eye x offsets in uv coordinates.\n\n"
"@param index The HMD index.\n"
@ -787,6 +1002,49 @@ DefineEngineFunction(getOVRSensorEulerRotation, Point3F, (S32 index),,
return Point3F(mRadToDeg(rot.x), mRadToDeg(rot.y), mRadToDeg(rot.z));
}
DefineEngineFunction(getOVRSensorAcceleration, Point3F, (S32 index),,
"@brief Get the acceleration values for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@return The acceleration values of the Oculus VR sensor, in m/s^2.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return Point3F::Zero;
}
return OCULUSVRDEV->getSensorAcceleration(index);
}
DefineEngineFunction(getOVRSensorAngVelocity, Point3F, (S32 index),,
"@brief Get the angular velocity values for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@return The angular velocity values of the Oculus VR sensor, in degrees/s.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return Point3F::Zero;
}
EulerF rot = OCULUSVRDEV->getSensorAngularVelocity(index);
return Point3F(mRadToDeg(rot.x), mRadToDeg(rot.y), mRadToDeg(rot.z));
}
DefineEngineFunction(getOVRSensorMagnetometer, Point3F, (S32 index),,
"@brief Get the magnetometer reading (direction and field strength) for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@return The magnetometer reading (direction and field strength) of the Oculus VR sensor, in Gauss.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return Point3F::Zero;
}
return OCULUSVRDEV->getSensorMagnetometer(index);
}
DefineEngineFunction(getOVRSensorPredictionTime, F32, (S32 index),,
"@brief Get the prediction time set for the given sensor index.\n\n"
"@param index The sensor index.\n"
@ -828,6 +1086,78 @@ DefineEngineFunction(setAllSensorPredictionTime, void, (F32 dt),,
OCULUSVRDEV->setAllSensorPredictionTime(dt);
}
DefineEngineFunction(getOVRSensorGravityCorrection, bool, (S32 index),,
"@brief Get the gravity correction state for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@return True if gravity correction (for pitch and roll) is active.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return false;
}
return OCULUSVRDEV->getSensorGravityCorrection(index);
}
DefineEngineFunction(setOVRSensorGravityCorrection, void, (S32 index, bool state),,
"@brief Set the gravity correction state for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@param state The gravity correction state to change to.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return;
}
OCULUSVRDEV->setSensorGravityCorrection(index, state);
}
DefineEngineFunction(getOVRSensorYawCorrection, bool, (S32 index),,
"@brief Get the yaw correction state for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@return True if yaw correction (using magnetometer calibration data) is active.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return false;
}
return OCULUSVRDEV->getSensorYawCorrection(index);
}
DefineEngineFunction(setOVRSensorYawCorrection, void, (S32 index, bool state),,
"@brief Set the yaw correction state for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@param state The yaw correction state to change to.\n"
"@note Yaw correction cannot be enabled if the user has disabled it through "
"the Oculus VR control panel.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return;
}
OCULUSVRDEV->setSensorYawCorrection(index, state);
}
DefineEngineFunction(getOVRSensorMagnetometerCalibrated, bool, (S32 index),,
"@brief Get the magnetometer calibrated data state for the given sensor index.\n\n"
"@param index The sensor index.\n"
"@return True if magnetometer calibration data is available.\n"
"@ingroup Game")
{
if(!ManagedSingleton<OculusVRDevice>::instanceOrNull())
{
return false;
}
return OCULUSVRDEV->getSensorMagnetometerCalibrated(index);
}
DefineEngineFunction(ovrResetAllSensors, void, (),,
"@brief Resets all Oculus VR sensors.\n\n"
"This resets all sensor orientations such that their 'normal' rotation "

View file

@ -44,6 +44,10 @@ public:
// 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 @@ public:
// 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 @@ public:
// 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:

View file

@ -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);
}

View file

@ -54,6 +54,12 @@ protected:
// 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 @@ protected:
// 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 @@ protected:
// 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 @@ public:
// 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 @@ public:
// 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; }

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -50,6 +50,10 @@ public:
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 @@ protected:
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 @@ public:
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,6 +116,26 @@ public:
// 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; }
@ -116,7 +143,24 @@ public:
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_

View file

@ -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);
}
}

View file

@ -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_

View file

@ -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);
}
//-----------------------------------------------------------------------------

View file

@ -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
//

View file

@ -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;
}

View file

@ -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);
}
//-----------------------------------------------------------------------------

View file

@ -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
//

View file

@ -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;
}