2016-02-15 3 views
1

Я пытаюсь сделать очень простой пример рендеринга Oculus, используя их SDK v0.8. Все, что я пытаюсь сделать, это сделать сплошной цвет для обоих глаз. Когда я запускаю это, все кажется правильно инициализированным. Окулус показывает предупреждение о состоянии здоровья, но все, что я вижу, это черный экран, когда сообщение о предупреждении о болезни уходит. Что я здесь делаю неправильно?Oculus 0.8 SDK Black Screen

#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; 
} 
+0

После некоторых дополнительных испытаний, я думаю, это связано с моим использованием ovrLayerEyeFov. Использование типа прямого слоя (ovrLayerDirect) позволяет мне видеть текстуру на окуле. – angrycrab

+0

ovrLayerDirect в основном просто смещает вашу текстуру на экран без каких-либо искажений. Теперь это может сработать для вас, но это будет практически бесполезно в будущем. Это прежде всего инструмент для тестирования вывода на дисплей и искажения объективов ... после того, как вы перейдете к рендерингу сплошного цвета, это вам не поможет. – Jherico

ответ

2

Есть целый ряд проблем здесь

  • Не инициализируется ovrLayerEyeFov.RenderPose
  • Не используя ovrSwapTextureSet правильно
  • бесполезные звонки в SDL_GL_SwapWindow вызовет прерывисто
  • Возможные неопределенное поведение при чтении текстуры пока он все еще связан для рисования

Не инициализируется ovrLayerEyeFov.RenderPose

Вы Основная проблема заключается в том, что вы не устанавливая RenderPose член ovrLayerEyeFov структуры. Этот член сообщает SDK, какую позу вы оказываете, и, следовательно, как он должен применять timewarp на основе текущей позы головы (которая могла бы измениться с момента рендеринга). Не устанавливая это значение, вы в основном предоставляете SDK случайную позу головы, что почти наверняка не является хорошей позой для головы.

Кроме того, ovrLayerFlag_HeadLocked не нужен для вашего типа слоя. Это заставляет Oculus отображать полученное изображение в фиксированном положении относительно вашей головы. Он может делать то, что вы хотите, но только, если вы правильно инициализируете членов layer.RenderPose с правильными значениями (я не уверен, что это было бы в случае ovrLayerEyeFov, так как я использовал флаг только в сочетании с ovrLayerQuad).

Что вы должны сделать, это добавить следующее право после объявления слоя, чтобы правильно инициализировать его:

memset(&layer, 0, sizeof(ovrLayerEyeFov)); 

Затем внутри визуализацию цикла следует добавить следующее сразу после проверки на отказе от курения события:

ovrTrackingState tracking = ovr_GetTrackingState(hmd, 0, true); 
layer.RenderPose[0] = tracking.HeadPose.ThePose; 
layer.RenderPose[1] = tracking.HeadPose.ThePose; 

Это сообщает SDK, что это изображение было визуализировано с точки зрения, где сейчас находится голова.

Не используя ovrSwapTextureSet правильно

Другая проблема в коде, что вы неправильно используете набор текстур. В документации указано, что при использовании набора текстур, вам нужно использовать текстуру, на которую указывает ovrSwapTextureSet.CurrentIndex:

ovrGLTexture* tex = (ovrGLTexture*)(&(pTextureSet->Textures[pTextureSet->CurrentIndex])); 

...а затем после каждого вызова ovr_SubmitFrame необходимо увеличивать ovrSwapTextureSet.CurrentIndex то мода значение по ovrSwapTextureSet.TextureCount как так

pTextureSet->CurrentIndex = (pTextureSet->CurrentIndex + 1) % pTextureSet->TextureCount; 

бесполезных вызовов SDL_GL_SwapWindow будет вызывать заикание

SDL_GL_SwapWindow(window); вызов является ненужным и бессмысленным, так как у вас нет 't нарисовал что-нибудь для фреймбуфера по умолчанию. После того, как вы уйдете от рисования сплошного цвета, этот вызов приведет к тому, что он приведет к дрожанию, так как он будет блокироваться до v-sync (обычно на 60 Гц), заставляя вас иногда пропускать ссылки на дисплей Oculus. Прямо сейчас это будет невидимо, потому что ваша сцена - это сплошной цвет, но позже, когда вы рендерите объекты в 3D, это вызовет невыносимый износ.

Вы можете использовать SDL_GL_SwapWindow если вы

  • Обеспечение v-синхронизация отключена
  • Есть текстуры зеркала доступны для рисования в окно. (Смотрите документацию по ovr_CreateMirrorTextureGL)

Возможные фреймбуфера вопросы

я менее уверен, об этом один из них является серьезной проблемой, но я хотел бы также предложить отменяя фреймбуфером и отсоединение Oculus при условии текстуры до, отправляя его в ovr_SubmitFrame(), так как я не уверен, что поведение хорошо определено при чтении из текстуры, прикрепленной к фреймбуферу, которая в настоящее время привязана для рисования. Кажется, это не влияет на мою локальную систему, но неопределенное не означает, что не работает, это просто означает, что вы не можете полагаться на это, чтобы работать.

Я обновил образец кода и поместил его here. В качестве бонуса я изменил его, чтобы он рисовал один цвет на левом глазу и другой цвет на правом глазу, а также настраивал буфер, чтобы обеспечить рендеринг одной половины буфера для каждого глаза.

+1

Вау, это было больше, чем я ожидал от кого-то. Спасибо за тонну за помощь! – angrycrab

+0

Не инициализировать ovrLayerEyeFov.RenderPose и не использовать ovrSwapTextureSet правильно определенно проблема. Наконец, я получил треугольник треугольника «hello world», который появится на oculus :) Еще раз спасибо. – angrycrab