首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Oculus0.8SDK黑屏

Oculus0.8SDK黑屏
EN

Stack Overflow用户
提问于 2016-02-15 01:45:04
回答 1查看 707关注 0票数 1

我正在尝试制作一个非常基本的示例,使用Oculus的SDKV0.8向Oculus呈现。我所要做的就是为两只眼睛渲染一种坚实的颜色。当我运行这个程序时,一切似乎都正确地初始化了。Oculus显示健康警告信息,但我看到的只有一个黑色屏幕,一旦健康警告信息消失。我在这里做错什么了?

代码语言:javascript
复制
#define GLEW_STATIC
#include <GL/glew.h>
#define OVR_OS_WIN32
#include <OVR_CAPI_GL.h>
#include <SDL.h>
#include <iostream>

int main(int argc, char *argv[])
{

    SDL_Init(SDL_INIT_VIDEO);   
    SDL_Window* window = SDL_CreateWindow("OpenGL", 100, 100, 800, 600, SDL_WINDOW_OPENGL);
    SDL_GLContext context = SDL_GL_CreateContext(window);

    //Initialize GLEW
    glewExperimental = GL_TRUE;
    glewInit();

    // Initialize Oculus context
    ovrResult result = ovr_Initialize(nullptr);
    if (OVR_FAILURE(result))
    {
        std::cout << "ERROR: Failed to initialize libOVR" << std::endl;
        SDL_Quit();
        return -1;
    }

    // Connect to the Oculus headset
    ovrSession hmd;
    ovrGraphicsLuid luid;
    result = ovr_Create(&hmd, &luid);
    if (OVR_FAILURE(result))
    {
        std::cout << "ERROR: Oculus Rift not detected" << std::endl;
        SDL_Quit();
        return 0;
    }

    ovrHmdDesc desc = ovr_GetHmdDesc(hmd);

    std::cout << "Found " << desc.ProductName << "connected Rift device" << std::endl;

    ovrSizei recommenedTex0Size = ovr_GetFovTextureSize(hmd, ovrEyeType(0), desc.DefaultEyeFov[0], 1.0f);
    ovrSizei bufferSize;
    bufferSize.w = recommenedTex0Size.w;
    bufferSize.h = recommenedTex0Size.h;

    std::cout << "Buffer Size: " << bufferSize.w << ", " << bufferSize.h << std::endl;

    // Generate FBO for oculus
    GLuint oculusFbo = 0;
    glGenFramebuffers(1, &oculusFbo);

    // Create swap texture
    ovrSwapTextureSet* pTextureSet = nullptr;
    if (ovr_CreateSwapTextureSetGL(hmd, GL_SRGB8_ALPHA8, bufferSize.w, bufferSize.h,&pTextureSet) == ovrSuccess)
    {
        ovrGLTexture* tex = (ovrGLTexture*)&pTextureSet->Textures[0];
        glBindTexture(GL_TEXTURE_2D, tex->OGL.TexId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }


    // Create ovrLayerHeader

    ovrEyeRenderDesc eyeRenderDesc[2];
    eyeRenderDesc[0] = ovr_GetRenderDesc(hmd, ovrEye_Left, desc.DefaultEyeFov[0]);
    eyeRenderDesc[1] = ovr_GetRenderDesc(hmd, ovrEye_Right, desc.DefaultEyeFov[1]);

    ovrLayerEyeFov layer;

    layer.Header.Type = ovrLayerType_EyeFov;
    layer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HeadLocked;
    layer.ColorTexture[0] = pTextureSet;
    layer.ColorTexture[1] = pTextureSet;
    layer.Fov[0] = eyeRenderDesc[0].Fov;
    layer.Fov[1] = eyeRenderDesc[1].Fov;

    ovrVector2i posVec;
    posVec.x = 0;
    posVec.y = 0;

    ovrSizei sizeVec;
    sizeVec.w = bufferSize.w;
    sizeVec.h = bufferSize.h;

    ovrRecti rec;
    rec.Pos = posVec;
    rec.Size = sizeVec;

    layer.Viewport[0] = rec;
    layer.Viewport[1] = rec;

    ovrLayerHeader* layers = &layer.Header;


    SDL_Event windowEvent;
    while (true)
    {
        if (SDL_PollEvent(&windowEvent))
        {
            if (windowEvent.type == SDL_QUIT) break;
        }
        ovrGLTexture* tex = (ovrGLTexture*)&pTextureSet->Textures[0];
        glBindFramebuffer(GL_FRAMEBUFFER, oculusFbo);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->OGL.TexId, 0);
        glViewport(0, 0, bufferSize.w, bufferSize.h);
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        ovr_SubmitFrame(hmd, 0, nullptr, &layers, 1);

        SDL_GL_SwapWindow(window);
    }

    SDL_GL_DeleteContext(context);
    SDL_Quit();
    return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-15 20:27:25

这里有很多问题

  • 未初始化ovrLayerEyeFov.RenderPose
  • 未正确使用ovrSwapTextureSet
  • SDL_GL_SwapWindow的无用调用会导致口吃
  • 在纹理尚未绘制的情况下读取纹理时可能存在的未定义行为

未初始化ovrLayerEyeFov.RenderPose

您的主要问题是没有设置ovrLayerEyeFov结构的ovrLayerEyeFov成员。这个成员告诉SDK您呈现的是什么姿态,因此它应该如何根据当前的头部姿态(在呈现后可能已经更改)应用时间翘曲。通过不设置这个值,您基本上是给SDK一个随机的头部姿态,这几乎肯定不是一个有效的头部姿态。

此外,您的层类型不需要ovrLayerFlag_HeadLocked。它使Oculus将结果图像显示在相对于头部的固定位置上。它可以做您想做的事情,但前提是您用正确的值正确地初始化layer.RenderPose成员(我不确定在ovrLayerEyeFov的情况下,这些值是什么,因为我只是结合使用了ovrLayerQuad标记)。

您应该做的是在layer声明之后添加以下内容,以正确初始化它:

代码语言:javascript
复制
memset(&layer, 0, sizeof(ovrLayerEyeFov));

然后,在render循环中,应该在检查退出事件之后添加以下内容:

代码语言:javascript
复制
ovrTrackingState tracking = ovr_GetTrackingState(hmd, 0, true);
layer.RenderPose[0] = tracking.HeadPose.ThePose;
layer.RenderPose[1] = tracking.HeadPose.ThePose;

这告诉SDK,这个图像是从当前头部的位置呈现的。

未正确使用ovrSwapTextureSet

代码中的另一个问题是您不正确地使用纹理集。文档指定在使用纹理集时,需要使用ovrSwapTextureSet.CurrentIndex指向的纹理。

代码语言:javascript
复制
ovrGLTexture* tex = (ovrGLTexture*)(&(pTextureSet->Textures[pTextureSet->CurrentIndex]));

...and,然后在每次调用ovr_SubmitFrame之后,您需要增加ovrSwapTextureSet.CurrentIndex,然后按ovrSwapTextureSet.TextureCount修改值,如下所示

代码语言:javascript
复制
pTextureSet->CurrentIndex = (pTextureSet->CurrentIndex + 1) % pTextureSet->TextureCount;

SDL_GL_SwapWindow 的无用调用将导致口吃

SDL_GL_SwapWindow(window);调用是不必要的,没有意义,因为您还没有将任何东西绘制到默认的框架缓冲区中。一旦你离开了绘制一个纯色,这个调用最终会导致抖动,因为它会阻塞直到v同步(通常在60赫兹),导致你有时错过了Oculus显示的引用。现在,这将是无形的,因为你的场景只是一个坚实的颜色,但后来当你渲染物体的3D,它将造成令人无法容忍的抖动。

如果您可以使用SDL_GL_SwapWindow

  • 确保禁用v同步。
  • 有可用的镜像纹理可绘制到窗口。(请参阅ovr_CreateMirrorTextureGL文档)

可能存在的帧缓冲区问题

我不太确定这个问题是否是一个严重的问题,但我也建议在将它发送到ovr_SubmitFrame()之前先解除框架缓冲区的绑定并分离Oculus提供的纹理,因为我不确定当从当前绑定到绘图的框架缓冲区的纹理读取时,行为是否定义良好。它似乎对我的本地系统没有影响,但未定义并不意味着不工作,它只是意味着您不能依赖它来工作。

我更新了示例代码,并将其放在这里中。作为一项奖励,我修改了它,使它在左眼上画一种颜色,在右眼上画一种不同的颜色,并设置缓冲器,为每只眼睛提供一半的缓冲器。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35400308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档