Major Rendering Problem - OpenGL and the Oculus Rift

Started by
1 comment, last by tmason 9 years, 11 months ago

Hello,

While attempting to create a program for the Oculus Rift the simple code below produces the resulting image.

Here is the image:

One_Eye_Off_Version2.png

And here is the code:


// GLFWOculusRiftTest
// (c) cThrough 2014 (Christopher Koeber)
// Version 2014050100

#include <Windows.h>
#include <GL/glew.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#include <GLFW/glfw3.h>
#include <GLFW/glfw3native.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <OVR_CAPI.h>
#include <OVR_CAPI_GL.h>
#include <OVR.h>

const bool l_FullScreen = false;

ovrHmd l_Hmd;
ovrHmdDesc l_HmdDesc;
ovrEyeDesc l_Eyes[2];
ovrGLConfig l_Cfg;

GLfloat l_VAPoints[] =
{
    0.5f, 0.5f, 0.5f,
   -0.5f, 0.5f, 0.5f,
   -0.5f,-0.5f, 0.5f,
    0.5f,-0.5f, 0.5f,
   -0.5f,-0.5f,-0.5f,
   -0.5f, 0.5f,-0.5f,
    0.5f, 0.5f,-0.5f,
    0.5f,-0.5f,-0.5f,
    0.5f, 0.5f, 0.5f,
    0.5f, 0.5f,-0.5f,
   -0.5f, 0.5f,-0.5f,
   -0.5f, 0.5f, 0.5f,
   -0.5f,-0.5f,-0.5f,
    0.5f,-0.5f,-0.5f,
    0.5f,-0.5f, 0.5f,
   -0.5f,-0.5f, 0.5f,
    0.5f, 0.5f, 0.5f,
    0.5f,-0.5f, 0.5f,
    0.5f,-0.5f,-0.5f,
    0.5f, 0.5f,-0.5f,
   -0.5f,-0.5f,-0.5f,
   -0.5f,-0.5f, 0.5f,
   -0.5f, 0.5f, 0.5f,
   -0.5f, 0.5f,-0.5f
};

GLfloat l_VANormals[] =
{
   0.0f, 0.0f, 1.0f,
   0.0f, 0.0f, 1.0f,
   0.0f, 0.0f, 1.0f,
   0.0f, 0.0f, 1.0f,
   0.0f, 0.0f,-1.0f,
   0.0f, 0.0f,-1.0f,
   0.0f, 0.0f,-1.0f,
   0.0f, 0.0f,-1.0f,
   0.0f, 1.0f, 0.0f,
   0.0f, 1.0f, 0.0f,
   0.0f, 1.0f, 0.0f,
   0.0f, 1.0f, 0.0f,
   0.0f,-1.0f, 0.0f,
   0.0f,-1.0f, 0.0f,
   0.0f,-1.0f, 0.0f,
   0.0f,-1.0f, 0.0f,
   1.0f, 0.0f, 0.0f,
   1.0f, 0.0f, 0.0f,
   1.0f, 0.0f, 0.0f,
   1.0f, 0.0f, 0.0f,
   -1.0f, 0.0f, 0.0f,
   -1.0f, 0.0f, 0.0f,
   -1.0f, 0.0f, 0.0f,
   -1.0f, 0.0f, 0.0f
};

GLuint l_VAIndici[] =
{
   0, 1, 2, 3,
   4, 5, 6, 7,
   8, 9, 10, 11,
   12, 13, 14, 15,
   16, 17, 18, 19,
   20, 21, 22, 23
};

// =============================================================================

static void ErrorCallback(int p_Error, const char* p_Description)
{
   fputs(p_Description, stderr);
}

// =============================================================================

static void KeyCallback(GLFWwindow* p_Window, int p_Key, int p_Scancode, int p_Action, int p_Mods)
{
   if (p_Key == GLFW_KEY_ESCAPE && p_Action == GLFW_PRESS)
      glfwSetWindowShouldClose(p_Window, GL_TRUE);
}

// =============================================================================

static void WindowSizeCallback(GLFWwindow* p_Window, int p_Width, int p_Height)
{
   l_Cfg.OGL.Header.RTSize.w = p_Width;
   l_Cfg.OGL.Header.RTSize.h = p_Height;

   int l_RenderCaps = 0;
   int l_DistortionCaps = ovrDistortion_Chromatic | ovrDistortion_TimeWarp;
   ovrEyeRenderDesc l_EyeRenderDesc[2];
   ovrHmd_ConfigureRendering(l_Hmd, &l_Cfg.Config, l_RenderCaps, l_DistortionCaps, l_Eyes, l_EyeRenderDesc);
}

// =============================================================================

static void RenderCubeFixedFunction(void)
{
   glBegin(GL_QUADS);
      glNormal3f( 0.0f, 0.0f, 1.0f);
      glVertex3f( 0.5f, 0.5f, 0.5f);
      glVertex3f(-0.5f, 0.5f, 0.5f);
      glVertex3f(-0.5f,-0.5f, 0.5f);
      glVertex3f( 0.5f,-0.5f, 0.5f);
   glEnd();

   glBegin(GL_QUADS);
      glNormal3f( 0.0f, 0.0f,-1.0f);
      glVertex3f(-0.5f,-0.5f,-0.5f);
      glVertex3f(-0.5f, 0.5f,-0.5f);
      glVertex3f( 0.5f, 0.5f,-0.5f);
      glVertex3f( 0.5f,-0.5f,-0.5f);
   glEnd();

   glBegin(GL_QUADS);
      glNormal3f( 0.0f, 1.0f, 0.0f);
      glVertex3f( 0.5f, 0.5f, 0.5f);
      glVertex3f( 0.5f, 0.5f,-0.5f);
      glVertex3f(-0.5f, 0.5f,-0.5f);
      glVertex3f(-0.5f, 0.5f, 0.5f);
   glEnd();

   glBegin(GL_QUADS);
      glNormal3f( 0.0f,-1.0f, 0.0f);
      glVertex3f(-0.5f,-0.5f,-0.5f);
      glVertex3f( 0.5f,-0.5f,-0.5f);
      glVertex3f( 0.5f,-0.5f, 0.5f);
      glVertex3f(-0.5f,-0.5f, 0.5f);
   glEnd();

   glBegin(GL_QUADS);
      glNormal3f( 1.0f, 0.0f, 0.0f);
      glVertex3f( 0.5f, 0.5f, 0.5f);
      glVertex3f( 0.5f,-0.5f, 0.5f);
      glVertex3f( 0.5f,-0.5f,-0.5f);
      glVertex3f( 0.5f, 0.5f,-0.5f);
   glEnd();

   glBegin(GL_QUADS);
      glNormal3f(-1.0f, 0.0f, 0.0f);
      glVertex3f(-0.5f,-0.5f,-0.5f);
      glVertex3f(-0.5f,-0.5f, 0.5f);
      glVertex3f(-0.5f, 0.5f, 0.5f);
      glVertex3f(-0.5f, 0.5f,-0.5f);
   glEnd();
}

// ============================================================================

void RenderCubeVertexArrays(void)
{
   glEnableClientState(GL_VERTEX_ARRAY);
   glVertexPointer(3, GL_FLOAT, 0, l_VAPoints);
   glEnableClientState(GL_NORMAL_ARRAY);
   glNormalPointer(GL_FLOAT, 0, l_VANormals);
   glDrawElements(GL_QUADS, 6*4, GL_UNSIGNED_INT, l_VAIndici);
   glDisableClientState(GL_NORMAL_ARRAY);
   glDisableClientState(GL_VERTEX_ARRAY);
}

// ============================================================================

static void SetOpenGLState(void)
{
   // Some state...
   glEnable(GL_CULL_FACE);
   glEnable(GL_LIGHTING);
   glDisable(GL_TEXTURE_2D);
   glEnable(GL_DEPTH_TEST);
   glShadeModel(GL_SMOOTH);
   glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
       
   // Some (stationary) lights...
   GLfloat l_Light0Position[] = { 5.0f, 6.0f, 3.0f, 0.0f };
   GLfloat l_Light0Diffuse[] = { 1.0f, 0.8f, 0.6f, 1.0f };
   glLightfv(GL_LIGHT0, GL_POSITION, l_Light0Position);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, l_Light0Diffuse);
   glEnable(GL_LIGHT0);
   
   GLfloat l_Light1Position[] = { -5.0f, -6.0f, 5.0f, 0.0f };
   GLfloat l_Light1Diffuse[] = { 0.6f, 0.8f, 1.0f, 1.0f };
   glLightfv(GL_LIGHT1, GL_POSITION, l_Light1Position);
   glLightfv(GL_LIGHT1, GL_DIFFUSE, l_Light1Diffuse);
   glEnable(GL_LIGHT1);
   
   // Material...
   GLfloat l_MaterialSpecular[] = { 0.3f, 0.3f, 0.3f, 1.0f };
   GLfloat l_MaterialShininess[] = { 10.0f };
   glMaterialfv(GL_FRONT, GL_SPECULAR, l_MaterialSpecular);
   glMaterialfv(GL_FRONT, GL_SHININESS, l_MaterialShininess);
}

// =============================================================================

int main(void)
{
   // Initialize LibOVR...
   ovr_Initialize();

   l_Hmd = ovrHmd_Create(0);
   if (!l_Hmd) l_Hmd = ovrHmd_CreateDebug(ovrHmd_DK1);

   ovrHmd_GetDesc(l_Hmd, &l_HmdDesc);

   ovrHmd_StartSensor(l_Hmd, ovrHmdCap_Orientation, 0);

   GLFWwindow* l_Window;

   glfwSetErrorCallback(ErrorCallback);

   if (!glfwInit()) exit(EXIT_FAILURE);

   ovrSizei l_ClientSize;
   if (l_FullScreen)
   {
      l_ClientSize.w = l_HmdDesc.Resolution.w; // 1280 for DK1...
      l_ClientSize.h = l_HmdDesc.Resolution.h; // 800 for DK1...
      // Create a fullscreen window with the Oculus Rift resolution...
      l_Window = glfwCreateWindow(l_ClientSize.w, l_ClientSize.h, "GLFW Oculus Rift Test", glfwGetPrimaryMonitor(), NULL);
   }
   else
   {
      l_ClientSize.w = 640;
      l_ClientSize.h = 480;
      // Create a window with the size of your likings...
      l_Window = glfwCreateWindow(l_ClientSize.w, l_ClientSize.h, "GLFW Oculus Rift Test", NULL, NULL);
   }

   if (!l_Window)
   {
      glfwTerminate();
      exit(EXIT_FAILURE);
   }

   // Print the OpenGL version we are using...
   int l_Major = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MAJOR);
   int l_Minor = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MINOR);
   int l_Profile = glfwGetWindowAttrib(l_Window, GLFW_OPENGL_PROFILE);
   printf("OpenGL: %d.%d ", l_Major, l_Minor);
   if (l_Profile==GLFW_OPENGL_COMPAT_PROFILE) printf("GLFW_OPENGL_COMPAT_PROFILE\n"); else printf("GLFW_OPENGL_CORE_PROFILE\n");

   // Make the context current for this window...
   glfwMakeContextCurrent(l_Window);

   // Create some lights, materials, etc...
   SetOpenGLState();

   // Don't forget to initialize Glew...
   GLenum l_Result = glewInit();
   if (l_Result!=GLEW_OK)   
   {
      printf("glewInit() error.\n");
      exit(EXIT_FAILURE);
   }

   // We will do some offscreen rendering, setup FBO...
   ovrSizei l_TextureSizeLeft = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Left, l_HmdDesc.DefaultEyeFov[0], 1.0f);
   ovrSizei l_TextureSizeRight = ovrHmd_GetFovTextureSize(l_Hmd, ovrEye_Right, l_HmdDesc.DefaultEyeFov[1], 1.0f);
   ovrSizei l_TextureSize;
   l_TextureSize.w = l_TextureSizeLeft.w + l_TextureSizeRight.w;
   l_TextureSize.h = (l_TextureSizeLeft.h>l_TextureSizeRight.h ? l_TextureSizeLeft.h : l_TextureSizeRight.h);

   // Create FBO...
   GLuint l_FBOId;
   glGenFramebuffers(1, &l_FBOId);
   glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);

   // The texture we're going to render to...
   GLuint l_TextureId;
   glGenTextures(1, &l_TextureId);
   // "Bind" the newly created texture : all future texture functions will modify this texture...
   glBindTexture(GL_TEXTURE_2D, l_TextureId);
   // Give an empty image to OpenGL (the last "0")
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, l_TextureSize.w, l_TextureSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
   // Linear filtering...
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

   // Create Depth Buffer...
   GLuint l_DepthBufferId;
   glGenRenderbuffers(1, &l_DepthBufferId);
   glBindRenderbuffer(GL_RENDERBUFFER, l_DepthBufferId);
   glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, l_TextureSize.w, l_TextureSize.h);
   glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, l_DepthBufferId);

   // Set the texture as our colour attachment #0...
   glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, l_TextureId, 0);

   // Set the list of draw buffers...
   GLenum l_GLDrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
   glDrawBuffers(1, l_GLDrawBuffers); // "1" is the size of DrawBuffers

   // Check if everything is OK...
   GLenum l_Check = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
   if (l_Check!=GL_FRAMEBUFFER_COMPLETE)
   {
      printf("There is a problem with the FBO.\n");
      exit(EXIT_FAILURE);
   }

   // Unbind...
   glBindRenderbuffer(GL_RENDERBUFFER, 0);
   glBindTexture(GL_TEXTURE_2D, 0);
   glBindFramebuffer(GL_FRAMEBUFFER, 0);

   // Oculus Rift eye configurations...
   l_Eyes[0].Eye = ovrEye_Left;
   l_Eyes[1].Eye = ovrEye_Right;
   l_Eyes[0].Fov = l_HmdDesc.DefaultEyeFov[0];
   l_Eyes[1].Fov = l_HmdDesc.DefaultEyeFov[1];
   l_Eyes[0].TextureSize.w = l_TextureSize.w;
   l_Eyes[0].TextureSize.h = l_TextureSize.h;
   l_Eyes[1].TextureSize.w = l_TextureSize.w;
   l_Eyes[1].TextureSize.h = l_TextureSize.h;
   l_Eyes[0].RenderViewport.Pos.x = 0;
   l_Eyes[0].RenderViewport.Pos.y = 0;
   l_Eyes[1].RenderViewport.Pos.x = (l_TextureSize.w+1)/2;
   l_Eyes[1].RenderViewport.Pos.y = 0;
   l_Eyes[0].RenderViewport.Size.w = l_TextureSize.w/2;
   l_Eyes[0].RenderViewport.Size.h = l_TextureSize.h;
   l_Eyes[1].RenderViewport.Size.w = l_Eyes[0].RenderViewport.Size.w;
   l_Eyes[1].RenderViewport.Size.h = l_Eyes[0].RenderViewport.Size.h;

   l_Cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
   l_Cfg.OGL.Header.Multisample = 0;
   l_Cfg.OGL.Header.RTSize.w = l_ClientSize.w;
   l_Cfg.OGL.Header.RTSize.h = l_ClientSize.h;
   l_Cfg.OGL.WglContext = glfwGetWGLContext(l_Window);
   l_Cfg.OGL.Window = glfwGetWin32Window(l_Window);
   l_Cfg.OGL.GdiDc = GetDC(l_Cfg.OGL.Window);

   int l_RenderCaps = 0;
   int l_DistortionCaps = ovrDistortion_Chromatic | ovrDistortion_TimeWarp;
   ovrEyeRenderDesc l_EyeRenderDesc[2];
   ovrHmd_ConfigureRendering(l_Hmd, &l_Cfg.Config, l_RenderCaps, l_DistortionCaps, l_Eyes, l_EyeRenderDesc);

   ovrGLTexture l_EyeTexture[2];
   l_EyeTexture[0].OGL.Header.API = ovrRenderAPI_OpenGL;
   l_EyeTexture[0].OGL.Header.TextureSize.w = l_TextureSize.w;
   l_EyeTexture[0].OGL.Header.TextureSize.h = l_TextureSize.h;
   l_EyeTexture[0].OGL.Header.RenderViewport = l_Eyes[0].RenderViewport;
   l_EyeTexture[0].OGL.TexId = l_TextureId;

   // Right eye uses the same texture, but a different rendering viewport...
   l_EyeTexture[1] = l_EyeTexture[0];
   l_EyeTexture[1].OGL.Header.RenderViewport = l_Eyes[1].RenderViewport;   

   glfwSetKeyCallback(l_Window, KeyCallback);
   glfwSetWindowSizeCallback(l_Window, WindowSizeCallback);

   GLfloat l_SpinX;
   GLfloat l_SpinY;

   while (!glfwWindowShouldClose(l_Window))
   {
      l_SpinX = (GLfloat) fmod(glfwGetTime()*17.0, 360.0);
      l_SpinY = (GLfloat) fmod(glfwGetTime()*23.0, 360.0);

      ovrFrameTiming m_HmdFrameTiming = ovrHmd_BeginFrame(l_Hmd, 0);

      // Bind the FBO...
      glBindFramebuffer(GL_FRAMEBUFFER, l_FBOId);
      // Clear...
      glClearColor(0.2f, 0.3f, 0.4f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      for (int l_EyeIndex=0; l_EyeIndex<ovrEye_Count; l_EyeIndex++)
      {
         ovrEyeType l_Eye = l_HmdDesc.EyeRenderOrder[l_EyeIndex];
         ovrPosef l_EyePose = ovrHmd_BeginEyeRender(l_Hmd, l_Eye);

         glViewport(l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Pos.x,   // StartX
                  l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Pos.y,   // StartY
                  l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Size.w,   // Width
                  l_EyeRenderDesc[l_Eye].Desc.RenderViewport.Size.h   // Height
                 );

         // Get Projection and ModelView matrici from the device...
         OVR::Matrix4f l_ProjectionMatrix = ovrMatrix4f_Projection(
            l_EyeRenderDesc[l_Eye].Desc.Fov, 0.3f, 100.0f, true);
         OVR::Quatf l_Orientation = OVR::Quatf(l_EyePose.Orientation);
         OVR::Matrix4f l_ModelViewMatrix = OVR::Matrix4f(l_Orientation.Inverted());

         // Pass matrici on to OpenGL...
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         glMultMatrixf(&(l_ProjectionMatrix.Transposed().M[0][0]));
         glMatrixMode(GL_MODELVIEW);
         glLoadIdentity();
         // Translate for specific eye based on IPD...
         glTranslatef(l_EyeRenderDesc[l_Eye].ViewAdjust.x,
                   l_EyeRenderDesc[l_Eye].ViewAdjust.y,
                   l_EyeRenderDesc[l_Eye].ViewAdjust.z);
         // Multiply with orientation retrieved from sensor...
         glMultMatrixf(&(l_ModelViewMatrix.Transposed().M[0][0]));
         // Move back a bit to show scene in front of us...
         glTranslatef(0.0f, 0.0f, -2.0f);
         // Make the cube spin...
         glRotatef(l_SpinX, 1.0f, 0.0f, 0.0f);
         glRotatef(l_SpinY, 0.0f, 1.0f, 0.0f);

         // Render...
         // RenderCubeFixedFunction();
         RenderCubeVertexArrays();

         ovrHmd_EndEyeRender(l_Hmd, l_Eye, l_EyePose, &l_EyeTexture[l_Eye].Texture);
      }

      // Unbind the FBO, back to normal drawing...
      glBindFramebuffer(GL_FRAMEBUFFER, 0);

      glDisable(GL_CULL_FACE); // Oculus wants CW orientations, avoid the problem by turning of culling...
      glDisable(GL_DEPTH_TEST); // Nothing is drawn with depth test on...
      ovrHmd_EndFrame(l_Hmd);
      glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind GL_ARRAY_BUFFER for my vertex arrays own to work...
      glEnable(GL_CULL_FACE); // Turn back on...
      glEnable(GL_DEPTH_TEST); // Turn back on...
      glClearDepth(1); // Oculus set this to 0 (the near plane), return to normal...
      glUseProgramObjectARB(0); // Oculus shader is still active, turn it off...

      glfwPollEvents();
   }

   glfwDestroyWindow(l_Window);

   glfwTerminate();

   ovrHmd_Destroy(l_Hmd);
   ovr_Shutdown();

   exit(EXIT_SUCCESS);
}

Any ideas as to why one eye is OK but the other is jacked?

Thank you.

Advertisement

I just took a glimpse into the code, first thing that attracted me was


int l_Major = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MAJOR);
int l_Minor = glfwGetWindowAttrib(l_Window, GLFW_CONTEXT_VERSION_MINOR);
int l_Profile = glfwGetWindowAttrib(l_Window, GLFW_OPENGL_PROFILE);
printf("OpenGL: %d.%d ", l_Major, l_Minor);

followed by:


glBegin(GL_QUADS);
     ......
glEnd();

According to the screenshot you are initializing glfw with opengl 4.4 (or glfw does that for you, look into "glfwWindoHint (GLFW_CONTEXT_VERSION_MAJOR /GLFW_CONTEX_VERSION_MINOR, x)" to set it manually), but "glBegin(GL_QUADS)" is removed since 3.3. I am not completly sure why it display something at all. But I would try to either a OpenGL Version where glBegin is not deprecated or removed or alter the program so that it is written in an OpenGL 3.3 (or newer) way.

Another thing is


if (l_Profile==GLFW_OPENGL_COMPAT_PROFILE) printf("GLFW_OPENGL_COMPAT_PROFILE\n"); else printf("GLFW_OPENGL_CORE_PROFILE\n");

I think there might be one ";" too many
the else case is not evaluated at all, otherwise you should have either one of those prints in your console. And it shows that the profile is not "GLFW_OPENGL_COMPAT_PROFILE".

I am not sure that this is the main problem but it is worth to give it a try.
Hope that this helps a little bit, otherwise please ask.

Thanks for the help, MightyTower2!

I believe this may be a problem with the Oculus Rift SDK; I will go ahead and pursue that avenue first and then update this post when I get an answer from the Oculus folks.

This topic is closed to new replies.

Advertisement