Forum Discussion

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

Oculus SDK 0.3.1 XNA Distortion Mesh Not Working

So I updated RiftDotNet to use the new Oculus SDK 0.3.1 at https://github.com/vogelvision/RiftDotNet. I've been trying to get it working with XNA 4.0 but am unable to get the Distortion Mesh shader working correctly. For some reason the screen is always black with it tries to render the Distortion mesh. I know the render target is getting set correctly for the scene as I can draw it directly using a sprite batch. I've uploaded my full code to https://dl.dropboxusercontent.com/u/1856355/OVR_031_XNA4_Test.zip. I'm using the client rendering setup as defined in the documentation for the SDK. My render target is 2222 x 1553 pixels and I'm using the following fx file for my pixel and vertex shader:
// pixel shader params
Texture2D Texture : register(t0);
SamplerState Linear : register(s0);
uniform extern int timeWarpEnabled = 0;

// vertex shader params
float2 EyeToSourceUVScale;
float2 EyeToSourceUVOffset;
float4x4 EyeRotationStart;
float4x4 EyeRotationEnd;

float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,
in float2 oTexCoord0 : TEXCOORD0, in float2 oTexCoord1 : TEXCOORD1,
in float2 oTexCoord2 : TEXCOORD2) : SV_Target
{
// 3 samples for fixing chromatic aberrations
float ResultR = Texture.Sample(Linear, oTexCoord0.xy).r;
float ResultG = Texture.Sample(Linear, oTexCoord1.xy).g;
float ResultB = Texture.Sample(Linear, oTexCoord2.xy).b;
return float4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0);
}


float2 TimewarpTexCoord(float2 TexCoord, float4x4 rotMat)
{
// Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic
// aberration and distortion). These are now real world vectors in direction (x,y,1)
// relative to the eye of the HMD. Apply the 3x3 timewarp rotation to these vectors.
float3 transformed = float3( mul ( rotMat, float4(TexCoord.xy, 1, 1) ).xyz);
// Project them back onto the Z=1 plane of the rendered images.
float2 flattened = (transformed.xy / transformed.z);
// Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye)
return(EyeToSourceUVScale * flattened + EyeToSourceUVOffset);
}

void vmain(in float2 Position : POSITION, in float4 Color : COLOR0,
in float2 TexCoord0 : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1,
in float2 TexCoord2 : TEXCOORD2,
out float4 oPosition : SV_Position, out float4 oColor : COLOR,
out float2 oTexCoord0 : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1,
out float2 oTexCoord2 : TEXCOORD2)
{
if(timeWarpEnabled == 1)
{
float timewarpLerpFactor = Color.a;
float4x4 lerpedEyeRot = lerp(EyeRotationStart, EyeRotationEnd, timewarpLerpFactor);
oTexCoord0 = TimewarpTexCoord(TexCoord0,lerpedEyeRot);
oTexCoord1 = TimewarpTexCoord(TexCoord1,lerpedEyeRot);
oTexCoord2 = TimewarpTexCoord(TexCoord2,lerpedEyeRot);
oPosition = float4(Position.xy, 0.5, 1.0);
oColor = Color.r; /*For vignette fade*/
}
else
{
// Scale them into ([0,0.5],[0,1]) or ([0.5,0],[0,1]) UV lookup space (depending on eye)
oTexCoord0 = EyeToSourceUVScale * TexCoord0 + EyeToSourceUVOffset;
oTexCoord1 = EyeToSourceUVScale * TexCoord1 + EyeToSourceUVOffset;
oTexCoord2 = EyeToSourceUVScale * TexCoord2 + EyeToSourceUVOffset;
oPosition = float4(Position.xy, 0.5, 1.0);
oColor = Color.r; /*For vignette fade*/
}
};

technique Technique1
{
pass Pass1
{
PixelShader = compile ps_3_0 main();
VertexShader = compile vs_3_0 vmain();
}
}


The CreateDistortionData method loads up the distortion mesh settings via the SDK:
  private void CreateDistortionData(IEyeDesc[] eyeSettings)
{
// initialize distortion mesh
for (int i = 0; i < (int)EyeType.ovrEye_Count; i++)
{
// create distortion mesh per eye
IDistortionMesh meshData;
var uv = new SharpDX.Vector2[2];
vrDevice.CreatDistortionMesh(eyeSettings[i], timeWarp, out uv, out meshData);
var v = new DistortionVertexDesc[meshData.VertextCount];
distortionData.UvScaleOffsets[i] = new Vector2[2];

for (int k = 0; k < uv.Length; k++)
{
distortionData.UvScaleOffsets[i][k] = MapVector2(uv[k]);
}

for (int j = 0; j < meshData.VertextCount; j++)
{
v[j].Pos = MapVector2(meshData.VertextData[j].Pos);
v[j].TexR = MapVector2(meshData.VertextData[j].TexR);
v[j].TexG = MapVector2(meshData.VertextData[j].TexG);
v[j].TexB = MapVector2(meshData.VertextData[j].TexB);
v[j].Col.R = v[j].Col.G = v[j].Col.B = (byte)(meshData.VertextData[j].VignetteFactor * 255.99f);
v[j].Col.A = (byte)(meshData.VertextData[j].TimeWarpFactor * 255.99f);
}

distortionData.VertexBuffers[i] = new VertexBuffer(GraphicsDevice, typeof(DistortionVertexDesc),
(int)meshData.VertextCount, BufferUsage.None);
distortionData.VertexBuffers[i].SetData(v, 0, (int)meshData.VertextCount);

distortionData.IndexBuffers[i] = new IndexBuffer(GraphicsDevice, typeof(int), (int)meshData.IndexCount,
BufferUsage.None);
int[] indexData = new int[meshData.IndexCount];
meshData.IndexData.CopyTo(indexData, 0);
distortionData.IndexBuffers[i].SetData(indexData);
}
}


And the DistortioMeshRender method tries to render the distortion mesh to the screen:
  private void DistortioMeshRender(double timewarpTime, IPosef[] eyeRenderPoses)
{
if (timeWarp)
{
// wait time time-warp time to reduce latency
vrDevice.WaitTillTime(timewarpTime);
}

// clear the screen
GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Viewport = new Viewport(0, 0, resolutionX, resolutionY);

GraphicsDevice.Clear(Color.Black);
// disable depth field test and culling for distortion mesh rendering....
//GraphicsDevice.RasterizerState = RasterizerState.CullNone;
//GraphicsDevice.DepthStencilState = DepthStencilState.None;

graphics.GraphicsDevice.Textures[0] = renderTarget;

// setup shader
for (int i = 0; i < (int)EyeType.ovrEye_Count; i++)
{
meshShader.CurrentTechnique = meshShader.Techniques[0];
meshShader.Parameters["Texture"].SetValue(renderTarget);
meshShader.Parameters["EyeToSourceUVScale"].SetValue(distortionData.UvScaleOffsets[i][0]);
meshShader.Parameters["EyeToSourceUVOffset"].SetValue(distortionData.UvScaleOffsets[i][1]);
meshShader.Parameters["timeWarpEnabled"].SetValue(0);

if (timeWarp)
{
// timewarp settings
var timeWarpMatrices = vrDevice.GetEyeTimewarpMatrices((EyeType)i, eyeRenderPoses[i]);
meshShader.Parameters["timeWarpEnabled"].SetValue(1);
meshShader.Parameters["EyeRotationStart"].SetValue(Matrix.Transpose(MapMatrix(timeWarpMatrices[0])));
meshShader.Parameters["EyeRotationEnd"].SetValue(Matrix.Transpose(MapMatrix(timeWarpMatrices[1])));
}

GraphicsDevice.Indices = distortionData.IndexBuffers[i];
GraphicsDevice.SetVertexBuffer(distortionData.VertexBuffers[i]);

// render eye with distortion
foreach (var pass in meshShader.CurrentTechnique.Passes)
{
pass.Apply();
//GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, distortionData.IndexBuffers[i].IndexCount/3);

GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, distortionData.VertexBuffers[i].VertexCount,
0, distortionData.IndexBuffers[i].IndexCount / 3);
}
}

GraphicsDevice.SetRenderTarget(null);

// renable render states
//GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
//GraphicsDevice.DepthStencilState = DepthStencilState.Default;
}


I'm using a custom class named DistortionVertexDesc for the Vertex Declaration type that should match up with the vertex shader above:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace OVRTestV3
{
public struct DistortionVertexDesc : IVertexType
{
public Vector2 Pos;
public Vector2 TexR;
public Vector2 TexG;
public Vector2 TexB;
public Color Col;

public VertexDeclaration VertexDeclaration
{
get
{
return
new VertexDeclaration(
new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0),
new VertexElement(8, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
new VertexElement(16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 1),
new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 2),
new VertexElement(32, VertexElementFormat.Color, VertexElementUsage.Color, 0)
);
}
}
};
}


Any help is appreciated, thank you!

3 Replies

  • I created a .NET wrapper for 0.3.1 but used SDK rendering rather than creating a distortion mesh. It is also what they recommend to do for future versions of the SDK. I plan to release my wrapper as a NuGet at some point if people are interested.
  • Guygodin, what graphics library are you using in .NET (SharpDX/XNA/MonoGame)?
    I've tried to get the SDK rendering to work in MonoGame in Desktop OpenGL but I'm getting an access violation error when it tries to render my 3D model on the second pass.
  • I'm using SharpDX and P/Invoking the C API (I've compiled libOVR as a dll).