Forum Discussion

🚨 This forum is archived and read-only. To submit a forum post, please visit our new Developer Forum. 🚨
tlopes's avatar
tlopes
Honored Guest
12 years ago

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

  • 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...
  • tlopes's avatar
    tlopes
    Honored Guest
    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
  • 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...)
  • 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);
    }
  • eta76's avatar
    eta76
    Honored Guest
    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.
  • eta76's avatar
    eta76
    Honored Guest
    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);
    }
  • "eta76" wrote:
    Ok, I have tried it myself: ... This does look like the shader I need. ...

    That is totally awesome dude! Thanks! :D
  • ggeasy's avatar
    ggeasy
    Honored Guest
    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!