Skip to main content
Up and Coming
April 17, 2013

ps_2_0 barrel warp shader

In case anybody wants the D3D9 version of the shader from the OculusRoomTiny demo, here it is (tested, compiled, and ran under the "ps_2_0" target for shader model 2). It's functionally no different from the DirectX 10 one, but this one will work with your D3D9 projects:
// D3D9 version of the Rift barrel warp shader (ps_2_0 compatible)
sampler tex : register(s0);

float2 LensCenter : register(c0);
float2 ScreenCenter : register(c1);
float2 Scale : register(c2);
float2 ScaleIn : register(c3);
float4 HmdWarpParam : register(c4);

// 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 HmdWarp(float2 in01)
{
float2 theta = (in01 - 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);
return LensCenter + Scale * theta1;
}

// You should be able to compile this for the PS_2_0 target
float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,
in float2 oTexCoord : TEXCOORD0) : SV_Target
{
float2 tc = HmdWarp(oTexCoord);
if (any(clamp(tc, ScreenCenter - float2(0.25, 0.5), ScreenCenter + float2(0.25, 0.5) ) - tc) )
return 0;
return tex2D(tex, tc);
}

    9 replies

    Up and Coming
    April 17, 2013
    Hmm. Interesting choice. Although I guess a lot of DX 9 hardware is going to be old enough for that to matter.
    I guess using shader model 3 would be redundant if you don't need it though.

    I did wonder what the dependency on DirectX 10 in the SDK was about, given that nothing going on with the hardware or the demos actually seemed to require it, and indeed the unity demo runs perfectly fine on my Windows XP system with DirectX 9 hardware...

    Why the SDK had a dependency on DX 10 while Unity did not did make me wonder...
    Inspiring
    April 17, 2013
    Thanks for posting this.
    AMD Ryzen 7 1800X | MSI X370 Titanium | G.Skill 16GB DDR4 3200 | EVGA SuperNOVA 1000 | Corsair Hydro H110i Gigabyte RX Vega 64 x2 | Samsung 960 Evo M.2 500GB | Seagate FireCuda SSHD 2TB | Phanteks ENTHOO EVOLV
    tlopesAuthor
    Up and Coming
    April 18, 2013
    No problem. The reason I use D3D9 is because I don't want to expend the time to port my engine from D3D9 to D3D10/11. Plus, Windows XP users like to be able to play my game too :P
    Up and Coming
    April 18, 2013
    Yes... I was vaguely annoyed that I couldn't compile the SDK examples...
    (Not that I don't have directX 10/11 hardware, but all my coding tools are on an old laptop at the moment...)
    Up and Coming
    April 24, 2013
    I added tangential distortion correction to this awhile back, to allow for IPD adjustments. I have not tested or debugged this yet. I thought I might as well post it here after stumbling across it again. If somebody else tests (and debugs) this, please post your results. Thanks!

    // http://en.wikipedia.org/wiki/Distortion_%28optics%29#Software_correction
    // https://developer.oculusvr.com/forums/viewtopic.php?f=33&t=497
    // D3D9 version of the Rift barrel warp shader (ps_2_0 compatible)
    sampler tex : register(s0);

    float2 pC : register(c0); // distortion center
    float2 ScreenCenter : register(c1);
    float4 Kn : register(c4); // radial distortion coefficients
    float4 Pn : register(c4); // tangential distortion coefficients

    float K1=Kn.y, K2=Kn.z;

    // 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 HmdWarp(float2 pIn)
    {
    float xD,yD; // distored image point (not warped)
    float xU,yU; // undistored image point (warped)
    float xD2,yD2,r2; // radius squared
    float2 pOut; // undistored image point (warped)

    xD=pIn.x-pC.x; yD=pIn.y-pC.y;
    xD2=xD*xD; yD2=yD*yD; r2=x2+y2;
    xU=xD*(1+K1*r2+K2*r2*r2)+(P1*(r2+2*xD2)+2*P2*xD*yD)(1+P3*r2);
    yU=yD*(1+K1*r2+K2*r2*r2)+(P2*(r2+2*yD2)+2*P1*xD*yD)(1+P3*r2);
    pOut.x=xD; pOut.y=yD;
    return pC+pOut;
    }

    // You should be able to compile this for the PS_2_0 target
    float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,
    in float2 oTexCoord : TEXCOORD0) : SV_Target
    {
    float2 tc = HmdWarp(oTexCoord);
    if (any(clamp(tc, ScreenCenter - float2(0.25, 0.5), ScreenCenter + float2(0.25, 0.5) ) - tc) )
    return 0;
    return tex2D(tex, tc);
    }
    This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
    New Participant
    June 23, 2013
    Would be cool, when some one had a pixelshader, which could be dropped in MediaPlayer Classic.


    sampler s0;
    float4 main(float2 tex : TEXCOORD0) : COLOR {
    float4 s1 = float4 (tex2D(s0, tex).rgb, 0.0);
    return s1;
    }

    That way every media file would be easily viewable with the Oculus.

    So a shader with all parameters defined in the shader, in stead of programatically set them all.
    New Participant
    June 23, 2013
    Ok, I have tried it myself:




    This does look like the shader I need.
    // Texture is given SBS horizontally compressed
    #define SBSOffset float2(1,0)
    #define SBSFactor float2(2,1)

    // Stereo Lens center offset, (eye out of cente)
    #define StereoOffset float2(0.02,0.0);

    sampler s0;

    #define LensCenter float2(0.5f,0.5f)
    #define ScreenCenter float2(0.5,0.5)
    #define Scale float2(0.32,0.45) /*Complete image: 0.35,0.45*/
    #define ScaleIn float2(2,2)
    #define HmdWarpParam float4(1,0.22,0.24,0)

    // 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 HmdWarp(float2 in01)
    {
    float2 theta = (in01 - LensCenter) * ScaleIn; // Scales to [-1, 1]
    float rSq = length(theta);// * theta.x + theta.y * theta.y;
    float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq +
    HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);
    return LensCenter + Scale * theta1;
    }

    // You should be able to compile this for the PS_2_0 target
    float4 main(float2 tex : TEXCOORD0) : COLOR
    {
    //return float4(0.8,0.1,0.3,0.3);
    if( tex.x<0.5)
    {
    tex = (tex * SBSFactor) - float2(0.0,0.0) - StereoOffset;
    float2 tc = HmdWarp(tex);
    if (any(clamp(tc, ScreenCenter - float2(0.5, 0.5), ScreenCenter + float2(0.5, 0.5) ) - tc) ) return 0;
    tc = tc/ SBSFactor;
    return tex2D(s0, tc);
    }
    if( tex.x>0.5)
    {
    tex = (tex * SBSFactor) - SBSOffset + StereoOffset;
    float2 tc = HmdWarp(tex);
    if (any(clamp(tc, ScreenCenter - float2(0.5, 0.5), ScreenCenter + float2(0.5, 0.5) ) - tc) ) return 0;
    tc = float2(0.0,0)+ tc/ SBSFactor;
    return tex2D(s0, tc);
    }

    return float4(0.8,0.1,0.3,0.3);
    }
    Up and Coming
    June 23, 2013
    "eta76" wrote:
    Ok, I have tried it myself: ... This does look like the shader I need. ...

    That is totally awesome dude! Thanks! :D
    This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
    New Participant
    April 7, 2014
    Hi,

    This is really the thing I need thank you!
    But where do I get the 'float2' and 'float4' constant types? I get 'identifier undefined' and I can't seem to find them in the OVR SDK...

    Thanks!