0

我在一个非常简单的 DirectX11 渲染引擎上工作了一段时间。今天,我设法为我的 Oculus Rift 集成设置了立体渲染(将场景两次渲染到纹理中)。

[目前] 所以我目前基本上在做的是:

  • 我有一个 1280 x 800 的窗口
  • 将整个场景渲染到 RenderTargetViewLeft_ (1280 x 800)
  • 将 RenderTargetViewLeft_ 的内容渲染为“EyeWindow”(如教程中所示)到屏幕左侧 (640 x 800)
  • 将整个场景渲染到 RenderTargetViewRight_ (1280 x 800)
  • 将 RenderTargetViewRight_ 的内容渲染为“EyeWindow”(如教程中所示)到屏幕右侧 (640 x 800)

所以到目前为止所有这些工作,我将场景渲染两次到单独的纹理中,最终在分屏中结束。

[DirectX11 渲染循环]

bool GraphicsAPI::Render()
{
    bool result;

// [Left Eye] The first pass of our render is to a texture now. 
result = RenderToTexture(renderTextureLeft_);
if (!result)
{
    return false;
}

// Clear the buffers to begin the scene.
BeginScene(0.0f, 0.0f, 0.0f, 1.0f);

// Turn off the Z buffer to begin all 2D rendering.
TurnZBufferOff();

// Render The Eye Window orthogonal to the screen
RenderEyeWindow(eyeWindowLeft_, renderTextureLeft_);

// Turn the Z buffer back on now that all 2D rendering has completed.
TurnZBufferOn();


// [Right Eye]  ------------------------------------
result = RenderToTexture(renderTextureRight_);
if (!result)
{
    return false;
}

TurnZBufferOff();

RenderEyeWindow(eyeWindowRight_, renderTextureRight_);

TurnZBufferOn();

// [End] Present the rendered scene to the screen.
EndScene(); // calls Present

return true;
}

[我现在想做什么] 现在我正在尝试使用 Oculus SDK 实现桶形失真。目前我不关心第二张图像的不同虚拟相机,现在只想实现桶形失真。

我已阅读开发人员指南 [1] 并尝试查看 TinyRoom 演示,但我不完全了解现在在我已经工作的 DirectX 引擎中使用 SDK 实现失真的必要条件。

在 Developers Guide Render Texture Initialization中,他们展示了如何为 API 创建纹理。我想这意味着,我需要使用相应的 API 大小设置我的所有 RendertargetViews(渲染目标当前大小为 1280 x 800) - 甚至我猜也要更改 DepthStencilView 和 Backbuffer。

渲染循环看起来像这样:

ovrHmd_BeginFrame(hmd, 0);
BeginScene(0.0f, 0.0f, 0.0f, 1.0f);
...
// Render Loop as the Code above
...
ovrHmd_EndFrame(hmd, headPose, EyeTextures);
// EndScene(); // calls Present, not needed on Oculus Rendering

我觉得少了点什么,所以我确定我没有做对。

[更新] 所以,我使用 Oculus API 实现了用桶形失真渲染场景。虽然左右图像的多边形分离得太远,但这可能是由于使用我的默认 1280 x 800 纹理大小作为渲染目标造成的。移动 HMD 时,CameraStream 似乎也没有与屏幕正交。要做一些进一步的测试;)

[1] - Oculus 开发者指南:https ://developer.oculus.com/documentation/

4

1 回答 1

0

3d HMD Support 的关键点一般是对整个图形场景进行两次渲染。一次使用左侧虚拟相机,一次使用右侧虚拟相机 - 它们之间的“眼睛”距离各不相同,但大约为 65 毫米。

要存储场景,必须将图形场景渲染为纹理。我首先使用左侧虚拟相机将我的场景渲染到 RenderTextureLeft_ 中,然后我使用右侧虚拟相机将完全相同的场景渲染到 RenderTextureRight_ 中。这种技术称为“渲染到纹理”。这意味着我们将图像保存到单独的纹理中以进行进一步的后期处理,而不是将其直接渲染到后台缓冲区以在监视器上显示。

很好,但我们现在如何渲染到 Oculus Rift?首先设置一个 hmd 实例并正确配置它很重要。这在官方文档 [1] 中得到了很好的解释:https ://developer.oculus.com/documentation/pcsdk/latest/concepts/dg-render/

在两个 RenderTexture(左眼、右眼)都成功渲染为纹理并相应配置了 oculus 设备后,需要向 Oculus SDK 提供两个渲染纹理以将它们打印到 hmd 的监视器上并使用Oculus SDK(不是较新的 SDK 版本不再支持的客户端失真)。

在这里,我展示了我的 DirectX 代码,它为 oculus sdk 提供了我的两个渲染纹理,并且还进行了桶形失真:

bool OculusHMD::RenderDistortion()
{
    ovrD3D11Texture eyeTexture[2]; // Gather data for eye textures 
    Sizei size;
    size.w = RIFT_RESOLUTION_WIDTH; 
    size.h = RIFT_RESOLUTION_HEIGHT;

    ovrRecti eyeRenderViewport[2];
    eyeRenderViewport[0].Pos = Vector2i(0, 0);
    eyeRenderViewport[0].Size = size;
    eyeRenderViewport[1].Pos = Vector2i(0, 0);
    eyeRenderViewport[1].Size = size;

    eyeTexture[0].D3D11.Header.API = ovrRenderAPI_D3D11;
    eyeTexture[0].D3D11.Header.TextureSize = size;
    eyeTexture[0].D3D11.Header.RenderViewport = eyeRenderViewport[0];
    eyeTexture[0].D3D11.pTexture = graphicsAPI_->renderTextureLeft_->renderTargetTexture_;
    eyeTexture[0].D3D11.pSRView = graphicsAPI_->renderTextureLeft_->GetShaderResourceView();

    eyeTexture[1].D3D11.Header.API = ovrRenderAPI_D3D11;
    eyeTexture[1].D3D11.Header.TextureSize = size;
    eyeTexture[1].D3D11.Header.RenderViewport = eyeRenderViewport[1];
    eyeTexture[1].D3D11.pTexture = graphicsAPI_->renderTextureRight_->renderTargetTexture_;
    eyeTexture[1].D3D11.pSRView = graphicsAPI_->renderTextureRight_->GetShaderResourceView();

    ovrHmd_EndFrame(hmd_, eyeRenderPose_, &eyeTexture[0].Texture);

    return true;
}

包括桶形失真在内的立体图像作为一种后期处理效果的呈现最终通过这条线完成:

ovrHmd_EndFrame(hmd_, eyeRenderPose_, &eyeTexture[0].Texture);

希望代码可以帮助人们更好地理解管道。

于 2016-03-11T18:52:56.403 回答