2

I have a program that reads a 360 mono panorama and reads an IMU, drawing the correct part of the panorama based on the head location.

I am creating two windows, one per display, and do not want to rely on GLUT_STEREO. The draw() calls for each display are therefore independent, but right now they render the same thing, which is a gluSphere to represent the panorama. To draw the correct part of the sphere, IMU data (quaternion) becomes a rotation matrix, and that matrix is multiplied with the projection.

I wish to create a little bit of overlap with the two images, as shown with the following image: overlapped

For example, the red rectangle is my left display and the blue rectangle is my right display, but there is some overlap in the middle.

I was reading some article about stereo rendering, and I thought the solution would be to replace the call from gluPerspective() to glFrustum(), and simply modify both the left and right parameter at the same time. I thought subtracting some value to left/right parameter of glFrustum() on the display and adding some value to the left/right parameter of glFrustum() would do the trick. I modified the glutReshapeFunc() callback's projection matrix to do just that:

void resize(int width, int height)
{
  glViewport(0, 0, width, height);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  GLdouble near = 0.1;
  GLdouble far = 100.0;

  GLdouble aspect = (double) width / (double) height;
  GLdouble top = tan(FOVY / 360 * M_PI) * near;
  GLdouble bottom = -top;
  GLdouble right = top * aspect;
  GLdouble left = -right;

  // TODO: Canned value for testing
  left += 0.5;
  right += 0.5;

  glFrustum(left, right, bottom, top, near, far);
  //  gluPerspective(FOVY, aspect, near, far);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

Unfortunately, this does not do what I expect (and I am really not sure why). I would think modifying both left and right parameter of glFrustum() would keep the same horizontal FOV but move it to the left or right. It seems to either stretch the image in or out.

I have played around with glTranslatef() on the ModelView or glLookAt(), but there place are not clear to me. Why is glFrustum() not having the right behavior please, and what am I missing?

4

1 回答 1

1

修改截头体相机。

您需要两个不同的相机矩阵来模拟眼睛分离和稍微不同的截锥体来消除前束。

使用 OpenGL(和 GLUT)进行 3D 立体渲染

/* Misc stuff */
ratio  = camera.screenwidth / (double)camera.screenheight;
radians = DTOR * camera.aperture / 2;
wd2     = near * tan(radians);
ndfl    = near / camera.focallength;

/* Derive the two eye positions */
CROSSPROD(camera.vd,camera.vu,r);
Normalise(&r);
r.x *= camera.eyesep / 2.0;
r.y *= camera.eyesep / 2.0;
r.z *= camera.eyesep / 2.0;

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
left  = - ratio * wd2 - 0.5 * camera.eyesep * ndfl;
right =   ratio * wd2 - 0.5 * camera.eyesep * ndfl;
top    =   wd2;
bottom = - wd2;
glFrustum(left,right,bottom,top,near,far);

glMatrixMode(GL_MODELVIEW);
glDrawBuffer(GL_BACK_RIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(camera.vp.x + r.x,camera.vp.y + r.y,camera.vp.z + r.z,
          camera.vp.x + r.x + camera.vd.x,
          camera.vp.y + r.y + camera.vd.y,
          camera.vp.z + r.z + camera.vd.z,
          camera.vu.x,camera.vu.y,camera.vu.z);
MakeLighting();
MakeGeometry();

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
left  = - ratio * wd2 + 0.5 * camera.eyesep * ndfl;
right =   ratio * wd2 + 0.5 * camera.eyesep * ndfl;
top    =   wd2;
bottom = - wd2;
glFrustum(left,right,bottom,top,near,far);

glMatrixMode(GL_MODELVIEW);
glDrawBuffer(GL_BACK_LEFT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(camera.vp.x - r.x,camera.vp.y - r.y,camera.vp.z - r.z,
          camera.vp.x - r.x + camera.vd.x,
          camera.vp.y - r.y + camera.vd.y,
          camera.vp.z - r.z + camera.vd.z,
          camera.vu.x,camera.vu.y,camera.vu.z);
MakeLighting();
MakeGeometry();

glutSwapBuffers();

用适当的 FBO 绑定替换glDrawBuffer()调用。

于 2015-07-15T21:06:09.383 回答