OpenGL Occlusion Queries

  • あるオブジェクトが画面内に描写されたか、そうでないかの判定には Occlusion Queries を使います
  • なお、クエリー内に入る数は、デプステストを通過するとインクリメントします。もし、デプステストを通過し値がインクリメントされたとしても、後に前のオブジェクトに遮られて全く見えなくなることもあるので注意
unsigned int idsQuery[27];//描写するオブジェクトのクエリーの結果を保存する

void Init()
{
  glGenQueries(27, idsQuery);
  ...
}

void Draw()
{
  DrawOccluder();//オブジェクトをさえぎる壁など

  /////クエリーの作成なので、光などは不要
  glDisable(GL_LIGHTING);
  glDisable(GL_NORMALIZE);
  glDepthMask(GL_FALSE);
  glColorMask(0, 0, 0, 0);

  for(int x=0; x<3; x++){
    for(int y=0; y<3; y++){
      for(int z=0; z<3; z++){
        glPushMatrix();
        glTranslatef(100.0*x, 100.0*y, 100.0*z);
        glBeginQuery(GL_SAMPLES_PASSED, idsQuery[x*9+y*3+z]);//クエリーの指定はじめ
        glutSolidCube(100.0);//描写されるか判定を行うオブジェクト、単純な形状のものを使う
        glEndQuery(GL_SAMPLES_PASSED);
        //int passed;
        //glGetQueryObjectiv(idsQuery[x*9+y*3+z], GL_QUERY_RESULT, &passed);
        //このクエリーの結果はすぐには得られないので、ここでは問い合わせない
        //もし問い合わせをすると、結果が出るまで処理が止まってしまう
        glPopMatrix();
      }
    }
  }

  ///// クエリーの結果から描写するかを決める
  glEnable(GL_LIGHTING);
  glEnable(GL_NORMALIZE);
  glDepthMask(GL_TRUE);
  glColorMask(1, 1, 1, 1);
  for(int x=0; x<3; x++){
    for(int y=0; y<3; y++){
      for(int z=0; z<3; z++){
        glPushMatrix();
        glTranslatef(100.0*x, 100.0*y, 100.0*z);
        int passed;
        glGetQueryObjectiv(idsQuery[x*9+y*3+z], GL_QUERY_RESULT, &passed);//
        if(passed > 0) DrawObject();//少しでも見えるということで、お好みのオブジェクトを描写
        glPopMatrix();
      }
    }
  }
}