基于DX11的OculusVR 渲染接口实现

基于DX11的OculusVR 渲染接口实现

DX11绘制其实就是不断的刷新并提交,为了支持默认绘制模式和VR绘制模式,我们设计一个接口,供系统启动时默认加载,也运行在使用过程中进行切换。

1
2
3
4
5
6
7
public interface IDrawContext : IDisposable
{
void Init(Control target);
void BeginPass();
void DrawPass(Gaiaxis.Defines.Handler0 userrender);
void EndPass();
}

在主程序中使用渲染接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
public sealed partial class Root
{
private IDrawContext fCurrentRenderMode;
private MonoralDrawContext mMonoral;
private StereoDrawContext mStereo;

protected override void InitDevice(Control userControl)
{
this.fDrawContext = new DrawContext11T(this.fTargetControl);
this.fDrawContext.InitResource();

this.mMonoral = new MonoralDrawContext(this.fDrawContext);
this.mMonoral.Init(userControl);
this.fCurrentRenderMode = this.mMonoral;

if (VRMODE)
{
this.mStereo = new StereoDrawContext(this.fDrawContext);
this.mStereo.Init(userControl);
this.fCurrentRenderMode = this.mStereo;
}

Application.Idle += new EventHandler(OnApplicationIdle);
}
private void OnApplicationIdle(object sender, EventArgs e)
{
if(this.isShouldExit)
{
Application.Exit();
return;
}
while (NativeMethods.IsAppStillIdle)
{
if (this.m_isRenderDisabled || this.IsPause)
{
return;
}
try
{
float timeSinceStart = (float)(DateTime.Now - fStartTime).TotalSeconds;
this.BeginFrameRender();

this.UpdateThread();
this.fDrawContext.BeginFrame(this.fFrameData);
if (this.fCurrentRenderMode != null)
{
this.Render?.BeginDraw(this.fFrameData.ElapsedSecondTime);
this.fCurrentRenderMode.BeginPass();
this.fCurrentRenderMode.DrawPass(this.DrawFrame);

if (this.Render != null)
{
this.fDrawContext.SetBlend(EBlendMode.NonPremultiplied);
this.fDrawContext.SetDepthStencil(EZWEnableMode.ZRDisable);
this.fDrawContext.SetRasterizerCullNoneScissor();
this.Render.Present();
this.fDrawContext.SetRasterizerCullNone();
}
this.fCurrentRenderMode.EndPass();
}
}
catch (Exception caught)
{
Logger.Instance.RecordOperation(caught, LoggingLevel.CreateDebugFile);
}
finally
{
this.EndFrameRender();
}
}
}
}

默认绘制方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MonoralDrawContext : IDrawContext
{
private Gaiaxis.DirectX11.DrawContext11T fDrawContext;
public MonoralDrawContext(Gaiaxis.DirectX11.DrawContext11T drawContext)
{
this.fDrawContext = drawContext;
}
public void Init(Control target)
{
}
public void BeginPass()
{
this.fDrawContext.SetBackBufferRenderTarget();
this.fDrawContext.ClearBackBuffer(Color.Black);
}
public void DrawPass(Gaiaxis.Defines.Handler0 userrender)
{
userrender();
}
public void EndPass()
{
this.fDrawContext.Present(Root.Instance.WorldSettings.EnableVsync);
}
}

Oculus的绘制实现类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
public class StereoDrawContext : IDrawContext
{
public class HandlerController
{
private BasicModel model;
private float modelscale = 0.75f;
private Matrix MatrixofXinvert = Matrix.Identity;
private OculusW.HandType handType = HandType.Left;

private SharpDX.Direct3D11.ShaderResourceView handtexture;
public HandlerController(BasicModel model, OculusW.HandType tp, Matrix invert)
{
this.model = model;
this.handType = tp;
this.MatrixofXinvert = invert;
this.handtexture = Gaiaxis.DirectX11.Resources.Textures["Lightning-Beam-psd42615.png"].Object;
}

public void DrawModel(Gaiaxis.DirectX11.DrawContext11T dc, Posef handler, Matrix v, Matrix p)
{
SharpDX.Direct3D11.DeviceContext drawcontext = dc.ImmediateContext;
Matrix world = SharpDXHelpers.FromQuad(handler.Orientation);
world.Transpose();
world.TranslationVector = handler.Position.ToVector3();

//fxBasicalShader.Instance.BeginDrawNormalColored(this.fDrawContext.ImmediateContext, wvp, ne Color4(0.5f, 0.5f, 0.5f, 0.5f));
//this.mLeftModel.Begin(this.fDrawContext.ImmediateContext);
//for (int m = 0; m < this.mLeftModel.SubsetCount; m++)
//{
// this.mLeftModel.DrawSubset(this.fDrawContext.ImmediateContext, m);
//}
//fxBasicalShader.Instance.EndDraw(this.fDrawContext.ImmediateContext);

if (this.model != null)
{
SharpDX.Vector3 cen = (this.model.Max + this.model.Min) * 0.5f;
var refcenter = Matrix.Translation(-cen);
fxModelBoxShader.Instance.BeginDrawFixedModel(drawcontext, v, p, Matrix.Identity, Vector4.Zero, Vector3.UnitZ, Color4.Black, 0.0001f, false);
this.model.Begin(drawcontext);
for (int m = 0; m < this.model.MeshesToDraw.Count; m++)
{
MeshDrawCall drawParams = this.model.MeshesToDraw[m];
Matrix w = drawParams.World * refcenter * this.MatrixofXinvert * world;
int i = drawParams.MeshPartIndex;
var pa = this.model.Subsets[i];
var material = pa.MaterialT;

fxModelBoxShader.Instance.UpdateModelMaterial(drawcontext, w, material, Color.DarkGray, 0.25f, false);
fxModelBoxShader.Instance.SetFixedModelShader(drawcontext, material.DiffuseTextureView);
this.model.DrawSubset(drawcontext, i);
}
}
dc.SetRasterizerCullNone();
fxBasicalShader.Instance.BeginDrawTextured(dc.ImmediateContext, Matrix.Scaling(0.02f, 0.02f, -1000f) * world, v * p, this.handtexture, this.handtexture, Color.Lime, EColorTextureMode.ColoredTexturedGray);
SharpMeshGenerator.Instance.DrawXZBottomQuad(dc);
fxBasicalShader.Instance.EndDraw(dc.ImmediateContext);
}
}
private IntPtr sessionPtr;
private EyeTexture[] eyeTextures = null;
private Texture2D mirrorTextureD3D = null;
private MirrorTexture mirrorTexture = null;
private Ab3d.OculusWrap.Result result;
private OvrWrap OVR;
private LayerEyeFov layerEyeFov;
private HmdDesc hmdDesc;

private readonly Vector3f UpVector = new Vector3f(0.0f, 1.0f, 0.0f);
private readonly Vector3f ForwardVector = new Vector3f(0.0f, 0.0f, -1.0f); // -1 because HMD looks along -Z at identity orientation

private Gaiaxis.DirectX11.DrawContext11T fDrawContext;


private BasicModel mLeftModel;
private const string fModelStringpath = @"Data\Model\oculusTouchLeftModel.obj";

private HandlerController LeftController;
private HandlerController RightController;

private Posef[] eyePoses = new Posef[2];
private InputState inputstate = new InputState();
private TrackingState trackingState = new TrackingState ();


public StereoDrawContext(Gaiaxis.DirectX11.DrawContext11T drawContext)
{
this.fDrawContext = drawContext;
}

public void Dispose()
{
SharpDX.Utilities.Dispose(ref mirrorTextureD3D);
SharpDX.Utilities.Dispose(ref mirrorTexture);
SharpDX.Utilities.Dispose(ref eyeTextures[0]);
SharpDX.Utilities.Dispose(ref eyeTextures[1]);

// Disposing the device, before the hmd, will cause the hmd to fail when disposing.
// Disposing the device, after the hmd, will cause the dispose of the device to fail.
// It looks as if the hmd steals ownership of the device and destroys it, when it's shutting down.
// device.Dispose();
OVR.Destroy(sessionPtr);
}

public void Init(Control target)
{
this.mLeftModel = SharpBasicModelGenerator.CreateNormalMappedFromObj(this.fDrawContext.Device, fModelStringpath);
this.LeftController = new HandlerController(this.mLeftModel, HandType.Left, Matrix.Scaling(1));
this.RightController = new HandlerController(this.mLeftModel, HandType.Right, Matrix.Scaling(-1, 1, 1));

Guid textureInterfaceId = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); // Interface ID of the Direct3D Texture2D interface.

OVR = OvrWrap.Create();
// Define initialization parameters with debug flag.
InitParams initializationParameters = new InitParams();
initializationParameters.Flags = InitFlags.Debug | InitFlags.RequestVersion;
initializationParameters.RequestedMinorVersion = 17;
// Initialize the Oculus runtime.
string errorReason = null;
try
{
result = OVR.Initialize(initializationParameters);
if (result < Ab3d.OculusWrap.Result.Success)
errorReason = result.ToString();
}
catch (Exception ex)
{
errorReason = ex.Message;
}

if (errorReason != null)
{
MessageBox.Show("Failed to initialize the Oculus runtime library:\r\n" + errorReason, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

// Use the head mounted display.
sessionPtr = IntPtr.Zero;
var graphicsLuid = new GraphicsLuid();
result = OVR.Create(ref sessionPtr, ref graphicsLuid);
if (result < Ab3d.OculusWrap.Result.Success)
{
MessageBox.Show("The HMD is not enabled: " + result.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
OVR.SetTrackingOriginType(this.sessionPtr, TrackingOrigin.FloorLevel);
hmdDesc = OVR.GetHmdDesc(sessionPtr);

// Create a set of layers to submit.
eyeTextures = new EyeTexture[2];
var viewport = new ViewportF(0, 0, hmdDesc.Resolution.Width, hmdDesc.Resolution.Height, 0.0f, 1.0f);
var des = String.Format("VRResolution: w:{0} h:{1}", viewport.Width.ToString(), viewport.Height.ToString());
Gaiaxis.Consoles.Logger.Instance.RecordOperation(des, LoggingLevel.LogListData);
fDrawContext.SetScreenViewPort(viewport);

layerEyeFov = new LayerEyeFov();
layerEyeFov.Header.Type = LayerType.EyeFov;
layerEyeFov.Header.Flags = LayerFlags.None;

for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++)
{
EyeType eye = (EyeType)eyeIndex;
var eyeTexture = new EyeTexture();
eyeTextures[eyeIndex] = eyeTexture;

// Retrieve size and position of the texture for the current eye.
eyeTexture.FieldOfView = hmdDesc.DefaultEyeFov[eyeIndex];
eyeTexture.TextureSize = OVR.GetFovTextureSize(sessionPtr, eye, hmdDesc.DefaultEyeFov[eyeIndex], 1.0f);
//eyeTexture.RenderDescription = hmd.GetRenderDesc(eye, hmd.DefaultEyeFov[eyeIndex]);
eyeTexture.HmdToEyeViewOffset = eyeTexture.RenderDescription.HmdToEyePose.Position;
eyeTexture.ViewportSize.Position = new Vector2i(0, 0);
eyeTexture.ViewportSize.Size = eyeTexture.TextureSize;
eyeTexture.Viewport = new Viewport(0, 0, eyeTexture.TextureSize.Width, eyeTexture.TextureSize.Height, 0.0f, 1.0f);

// Define a texture at the size recommended for the eye texture.
eyeTexture.Texture2DDescription = new Texture2DDescription();
eyeTexture.Texture2DDescription.Width = eyeTexture.TextureSize.Width;
eyeTexture.Texture2DDescription.Height = eyeTexture.TextureSize.Height;
eyeTexture.Texture2DDescription.ArraySize = 1;
eyeTexture.Texture2DDescription.MipLevels = 1;
eyeTexture.Texture2DDescription.Format = Format.R8G8B8A8_UNorm_SRgb;
eyeTexture.Texture2DDescription.SampleDescription = new SampleDescription(1, 0);
eyeTexture.Texture2DDescription.Usage = ResourceUsage.Default;
eyeTexture.Texture2DDescription.CpuAccessFlags = CpuAccessFlags.None;
eyeTexture.Texture2DDescription.BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget;

// Convert the SharpDX texture description to the Oculus texture swap chain description.
TextureSwapChainDesc textureSwapChainDesc = SharpDXHelpers.CreateTextureSwapChainDescription(eyeTexture.Texture2DDescription);

// Create a texture swap chain, which will contain the textures to render to, for the current eye.
IntPtr textureSwapChainPtr;

result = OVR.CreateTextureSwapChainDX(sessionPtr, fDrawContext.Device.NativePointer, ref textureSwapChainDesc, out textureSwapChainPtr);
WriteErrorDetails(OVR, result, "Failed to create swap chain.");

eyeTexture.SwapTextureSet = new TextureSwapChain(OVR, sessionPtr, textureSwapChainPtr);

// Retrieve the number of buffers of the created swap chain.
int textureSwapChainBufferCount;
result = eyeTexture.SwapTextureSet.GetLength(out textureSwapChainBufferCount);
WriteErrorDetails(OVR, result, "Failed to retrieve the number of buffers of the created swap chain.");

// Create room for each DirectX texture in the SwapTextureSet.
eyeTexture.Textures = new Texture2D[textureSwapChainBufferCount];
eyeTexture.RenderTargetViews = new RenderTargetView[textureSwapChainBufferCount];

// Create a texture 2D and a render target view, for each unmanaged texture contained in the SwapTextureSet.
for (int textureIndex = 0; textureIndex < textureSwapChainBufferCount; textureIndex++)
{
// Retrieve the Direct3D texture contained in the Oculus TextureSwapChainBuffer.
IntPtr swapChainTextureComPtr = IntPtr.Zero;
result = eyeTexture.SwapTextureSet.GetBufferDX(textureIndex, textureInterfaceId, out swapChainTextureComPtr);
WriteErrorDetails(OVR, result, "Failed to retrieve a texture from the created swap chain.");
// Create a managed Texture2D, based on the unmanaged texture pointer.
eyeTexture.Textures[textureIndex] = new Texture2D(swapChainTextureComPtr);
// Create a render target view for the current Texture2D.
eyeTexture.RenderTargetViews[textureIndex] = new RenderTargetView(fDrawContext.Device, eyeTexture.Textures[textureIndex]);
}

// Define the depth buffer, at the size recommended for the eye texture.
eyeTexture.DepthBufferDescription = new Texture2DDescription();
eyeTexture.DepthBufferDescription.Format = Format.D32_Float;
eyeTexture.DepthBufferDescription.Width = eyeTexture.TextureSize.Width;
eyeTexture.DepthBufferDescription.Height = eyeTexture.TextureSize.Height;
eyeTexture.DepthBufferDescription.ArraySize = 1;
eyeTexture.DepthBufferDescription.MipLevels = 1;
eyeTexture.DepthBufferDescription.SampleDescription = new SampleDescription(1, 0);
eyeTexture.DepthBufferDescription.Usage = ResourceUsage.Default;
eyeTexture.DepthBufferDescription.BindFlags = BindFlags.DepthStencil;
eyeTexture.DepthBufferDescription.CpuAccessFlags = CpuAccessFlags.None;
eyeTexture.DepthBufferDescription.OptionFlags = ResourceOptionFlags.None;

// Create the depth buffer.
eyeTexture.DepthBuffer = new Texture2D(fDrawContext.Device, eyeTexture.DepthBufferDescription);
eyeTexture.DepthStencilView = new DepthStencilView(fDrawContext.Device, eyeTexture.DepthBuffer);

// Specify the texture to show on the HMD.
if (eyeIndex == 0)
{
layerEyeFov.ColorTextureLeft = eyeTexture.SwapTextureSet.TextureSwapChainPtr;
layerEyeFov.ViewportLeft.Position = new Vector2i(0, 0);
layerEyeFov.ViewportLeft.Size = eyeTexture.TextureSize;
layerEyeFov.FovLeft = eyeTexture.FieldOfView;
}
else
{
layerEyeFov.ColorTextureRight = eyeTexture.SwapTextureSet.TextureSwapChainPtr;
layerEyeFov.ViewportRight.Position = new Vector2i(0, 0);
layerEyeFov.ViewportRight.Size = eyeTexture.TextureSize;
layerEyeFov.FovRight = eyeTexture.FieldOfView;
}
}

MirrorTextureDesc mirrorTextureDescription = new MirrorTextureDesc();
mirrorTextureDescription.Format = TextureFormat.R8G8B8A8_UNorm_SRgb;
mirrorTextureDescription.Width = target.Width;
mirrorTextureDescription.Height = target.Height;
mirrorTextureDescription.MiscFlags = TextureMiscFlags.None;

// Create the texture used to display the rendered result on the computer monitor.
IntPtr mirrorTexturePtr;
result = OVR.CreateMirrorTextureDX(sessionPtr, fDrawContext.Device.NativePointer, ref mirrorTextureDescription, out mirrorTexturePtr);
WriteErrorDetails(OVR, result, "Failed to create mirror texture.");

mirrorTexture = new MirrorTexture(OVR, sessionPtr, mirrorTexturePtr);


// Retrieve the Direct3D texture contained in the Oculus MirrorTexture.
IntPtr mirrorTextureComPtr = IntPtr.Zero;
result = mirrorTexture.GetBufferDX(textureInterfaceId, out mirrorTextureComPtr);
WriteErrorDetails(OVR, result, "Failed to retrieve the texture from the created mirror texture buffer.");

// Create a managed Texture2D, based on the unmanaged texture pointer.
mirrorTextureD3D = new Texture2D(mirrorTextureComPtr);
}

public void BeginPass()
{
this.fDrawContext.ClearBackBuffer(Color.Black);
}

public void DrawPass(Gaiaxis.Defines.Handler0 userrender)
{
try
{
double displayMidpoint = OVR.GetPredictedDisplayTime(sessionPtr, 0);
this.trackingState = OVR.GetTrackingState(sessionPtr, displayMidpoint, true);

var leppost = trackingState.HandPoses[(int)OculusW.HandType.Left].ThePose;
var rigpose = trackingState.HandPoses[(int)OculusW.HandType.Right].ThePose;

var ConnectedControllerTypes = OVR.GetConnectedControllerTypes(this.sessionPtr);
var result = OVR.GetInputState(sessionPtr, ControllerType.Touch, ref this.inputstate);
if (result == OculusW.Result.Success)
{
if (inputstate.Buttons != 0)
{
}
if ((inputstate.Buttons & (uint)OculusW.Button.A) == (uint)OculusW.Button.A)
{
OVR.RecenterTrackingOrigin(this.sessionPtr);
}
if ((inputstate.Buttons & (uint)OculusW.Button.B) == (uint)OculusW.Button.B)
{
OVR.RecenterTrackingOrigin(this.sessionPtr);
}

if ((inputstate.Buttons & (uint)OculusW.Button.X) == (uint)OculusW.Button.X)
{
OVR.RecenterTrackingOrigin(this.sessionPtr);
}
if ((inputstate.Buttons & (uint)OculusW.Button.Y) == (uint)OculusW.Button.Y)
{
OVR.RecenterTrackingOrigin(this.sessionPtr);
}
if ((inputstate.Buttons & (uint)OculusW.Button.Enter) == (uint)OculusW.Button.Enter)
{
}

if (Root.Instance.CurrentGame is IEnableVRController)
{
IEnableVRController cc = (Root.Instance.CurrentGame as IEnableVRController);
var left = inputstate.ThumbstickRaw[(int)OculusW.HandType.Left];
var right = inputstate.ThumbstickRaw[(int)OculusW.HandType.Right];
cc.DoLeftMoveTrggie(left.X, left.Y);
cc.DoRightMoveTrggie(right.X, right.Y);

var leftht = inputstate.HandTrigger[(int)OculusW.HandType.Left];
var rightht = inputstate.HandTrigger[(int)OculusW.HandType.Right];

if (leftht > 0.5f)
{
cc.DoZoomTriggle(-1, 1.05f);
}
if (rightht > 0.5f)
{
cc.DoZoomTriggle(1, 1.05f);
}
if (inputstate.IndexTrigger[(int)OculusW.HandType.Left] > 0.5f)
{

}
if (inputstate.IndexTrigger[(int)OculusW.HandType.Right] > 0.5f)
{
cc.DoShoot();
}
}
}


Vector3f[] hmdToEyeViewOffsets = { eyeTextures[0].HmdToEyeViewOffset, eyeTextures[1].HmdToEyeViewOffset };
// Calculate the position and orientation of each eye.
OVR.CalcEyePoses(trackingState.HeadPose.ThePose, hmdToEyeViewOffsets, ref eyePoses);

for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++)
{
EyeType eye = (EyeType)eyeIndex;
EyeTexture eyeTexture = eyeTextures[eyeIndex];

if (eyeIndex == 0)
layerEyeFov.RenderPoseLeft = eyePoses[0];
else
layerEyeFov.RenderPoseRight = eyePoses[1];

// Update the render description at each frame, as the HmdToEyeOffset can change at runtime.
eyeTexture.RenderDescription = OVR.GetRenderDesc(sessionPtr, eye, hmdDesc.DefaultEyeFov[eyeIndex]);

// Retrieve the index of the active texture
int textureIndex;
result = eyeTexture.SwapTextureSet.GetCurrentIndex(out textureIndex);
WriteErrorDetails(OVR, result, "Failed to retrieve texture swap chain current index.");

this.fDrawContext.SetOffscreenRenderTargets(eyeTexture.RenderTargetViews[textureIndex], eyeTexture.DepthStencilView, eyeTexture.Viewport.Width, eyeTexture.Viewport.Height);
this.fDrawContext.ClearBackBuffer(Color.Black);
this.fDrawContext.SetBlend(EBlendMode.Add);
this.fDrawContext.SetDepthStencil(EZWEnableMode.ZWDisable);
//this.fDrawContext.ImmediateContext.OutputMerger.SetRenderTargets();
//this.fDrawContext.DisplayViewPort = eyeTexture.Viewport;
//this.fDrawContext.ImmediateContext.ClearRenderTargetView(eyeTexture.RenderTargetViews[textureIndex], Color.Black);
//this.fDrawContext.ImmediateContext.ClearDepthStencilView(eyeTexture.DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);

Matrix projectionMatrix = OVR.Matrix4f_Projection(eyeTexture.FieldOfView, 1f, 10000000.0f, ProjectionModifier.LeftHanded).ToMatrix();
projectionMatrix.Transpose();
this.fDrawContext.ProjectT = projectionMatrix;

Quaternion rotationQuaternion = SharpDXHelpers.ToQuaternion(eyePoses[eyeIndex].Orientation);
Matrix rotationMatrix = Matrix.RotationQuaternion(rotationQuaternion);

this.fDrawContext.HeadletsRotation = rotationMatrix.ToMatrix4d();
this.fDrawContext.EysposesOffset = eyePoses[eyeIndex].Position.ToVector3D();

userrender();
this.fDrawContext.DisplayViewPort = eyeTexture.Viewport;

var viewmatrix = this.CaculaterFromPoses(eyePoses[eyeIndex]);

Matrix projectionMatrix2 = OVR.Matrix4f_Projection(eyeTexture.FieldOfView, 0.00f, 1000000.0f, ProjectionModifier.None).ToMatrix();
projectionMatrix2.Transpose();

this.fDrawContext.SetBlend(EBlendMode.Alpha);
this.fDrawContext.SetDepthStencil(EZWEnableMode.ZWDisable);
this.fDrawContext.SetRasterizerCullNone();
if ((ConnectedControllerTypes & ControllerType.LTouch) == ControllerType.LTouch)
{
this.LeftController.DrawModel(this.fDrawContext, leppost, viewmatrix, projectionMatrix2);
}
if ((ConnectedControllerTypes & ControllerType.RTouch) == ControllerType.RTouch)
{
this.RightController.DrawModel(this.fDrawContext, rigpose, viewmatrix, projectionMatrix2);
}
// Commits any pending changes to the TextureSwapChain, and advances its current index
result = eyeTexture.SwapTextureSet.Commit();
WriteErrorDetails(OVR, result, "Failed to commit the swap chain texture.");
}

result = OVR.SubmitFrame(sessionPtr, 0L, IntPtr.Zero, ref layerEyeFov);
WriteErrorDetails(OVR, result, "Failed to submit the frame of the current layers.");
}
catch
{ }
finally
{
}
}

public void EndPass()
{
this.fDrawContext.Present(false);
}

private Matrix CaculaterFromPoses(Posef posef)
{
Vector3 up = posef.Orientation.Rotate(UpVector).ToVector3();
Vector3 forward = posef.Orientation.Rotate(ForwardVector).ToVector3();
Vector3 viewPos = posef.Position.ToVector3();
var m1 = Matrix.LookAtRH(viewPos, viewPos + forward, up);
return m1;
}
/// <summary>
/// Write out any error details received from the Oculus SDK, into the debug output window.
///
/// Please note that writing text to the debug output window is a slow operation and will affect performance,
/// if too many messages are written in a short timespan.
/// </summary>
/// <param name="OVR">OvrWrap object for which the error occurred.</param>
/// <param name="result">Error code to write in the debug text.</param>
/// <param name="message">Error message to include in the debug text.</param>
private void WriteErrorDetails(OvrWrap OVR, OculusW.Result result, string message)
{
if (result >= OculusW.Result.Success)
return;

// Retrieve the error message from the last occurring error.
ErrorInfo errorInformation = OVR.GetLastErrorInfo();

string formattedMessage = string.Format("{0}. \nMessage: {1} (Error code={2})", message, errorInformation.ErrorString, errorInformation.Result);
Trace.WriteLine(formattedMessage);
MessageBox.Show(formattedMessage, message);

throw new Exception(formattedMessage);
}
}