I have spent several days trying to wrap my head around shaders in DBPro, but have concluded I'm not very good at it and haven't gotten anywhere.
What I'm trying to do is migrate the barrel distortion shader provided by Oculus to create the side-by-side stereoscopic effect as required to view 3D in the headset. The end result should ideally look like:
(Just getting the basic side-by-side down without distortion would be a good start too).
I've found a
DirectX 9 (shader model 2) conversion from the original DX10+ which should be easier to translate to what DBP supports.
// 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);
}
I also found an
OcculusRift.fx file that may be even easier to migrate.
// Combines two images into one warped Side-by-Side image
sampler2D TexMap0;
sampler2D TexMap1;
float2 LensCenter;
float2 LensShift;
float2 ScreenCenter;
float2 Scale;
float2 ScaleIn;
float4 HmdWarpParam;
float2 HmdWarp(float2 in01)
{
float2 theta = (in01 - LensCenter) * ScaleIn;
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;
}
float4 SBSRift(float2 Tex : TEXCOORD0) : COLOR
{
float2 newPos = Tex;
float2 tc;
float4 tColor;
float2 theta;
if(newPos.x < 0.5f) {
tc = HmdWarp(newPos);
tc.x = (tc.x - (LensCenter.x+LensShift.x -0.25f)) * 2.0f; //offset for ipd
tColor = tex2D(TexMap0,tc);
} else {
newPos.x = (1.0f - newPos.x); // mirror
tc = HmdWarp(newPos);
tc.x = (tc.x - (LensCenter.x+LensShift.x -0.25f)) * 2.0f; //offset for ipd
tc.x = 1.0f -tc.x; // unmirror
tColor = tex2D(TexMap1,tc);
}
tc.x = tc.x / 2.0f;
if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc)){
return 0;
// tColor[0] = 1.0f;
// tColor[1] = 1.0f;
// tColor[2] = 1.0f;
}
return tColor;
}
technique ViewShader
{
pass P0
{
VertexShader = null;
PixelShader = compile ps_2_0 SBSRift();
}
}
Any help would be much appreciated, as I think it'd be very cool to develop Rift-capable apps in DBP. Of course, getting proper 3D display is only a small piece of the puzzle and adding actual head tracking is probably the bigger undertaking. DBP already has some support for an older headtracking device and stereoscopics so maybe that wouldn't be all that hard, I don't know. In either case just being able to view DBP apps in 3D with the Rift headset would be very cool.
The actual SDK documentation from Oculus that describes the formula in detail starting on page 16 is at
https://developer.oculusvr.com/documents/Oculus_SDK_Overview_0.2.1.pdf