OpenGL: пятна, нарисованные на поверхностях изображений

#c #opengl #rubiks-cube

#c #opengl #кубик рубика

Вопрос:

Я пытаюсь закодировать интерфейс для кубика Рубика.

Однако, когда я рисую это, на гранях куба остаются пятна:

Куб

Вот хорошо прокомментированный код. Может кто-нибудь, пожалуйста, помочь мне и, возможно, запустить код и сказать мне, где я могу ошибаться?

 #include <GL/glut.h>
#include <stdlib.h>

#include <stdio.h>

void init() {

  glClearColor(1.0f, 0.0f, 1.0f, 1.0f);

  glEnable(GL_DEPTH_TEST);

}

static float x_degs = 0.0f;
static float y_degs = 0.0f;

void keyboard(unsigned char key, int x, int y) {

  switch (key) {

    case 'q':

      exit(EXIT_SUCCESS);

    case 'h':

      y_degs -= 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

    case 'j':

      x_degs -= 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

    case 'k':

      x_degs  = 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

    case 'l':

      y_degs  = 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

  }

}

// half the length of one card

static const float card_half_size = 1.0f;

// half the space between cards

static const float space_half_size = 0.1f;

// number of cards per face

static const int NUM_CARDS_PER_FACE = 4;
/*
// start position of center of top left card 

const float start = - 3 * (card_half_size   space_half_size);

// increment between center of cards

const float incr = 2 * (card_half_size   space_half_size);

// half the size of a cube face

const float cube_half_size = 4 * (card_half_size   space_half_size);
*/
// draw a card centered at the origin

void draw_card() {

  glBegin(GL_QUADS);
    glVertex3f(- card_half_size, - card_half_size, 0.0f);
    glVertex3f(- card_half_size, card_half_size, 0.0f);
    glVertex3f(card_half_size, card_half_size, 0.0f);
    glVertex3f(card_half_size, - card_half_size, 0.0f);
  glEnd();

}

// draw a cube face made up of cards

void draw_card_face() {

  const float cube_half_size = 4 * (card_half_size   space_half_size);
  const float start = - 3 * (card_half_size   space_half_size);
  const float incr = 2 * (card_half_size   space_half_size);

  glColor3f(0.0f, 1.0f, 1.0f);

  glBegin(GL_QUADS);
    glVertex3f(- cube_half_size, - cube_half_size, -0.001f);
    glVertex3f(- cube_half_size, cube_half_size, -0.001f);
    glVertex3f(cube_half_size, cube_half_size, -0.001f);
    glVertex3f(cube_half_size, - cube_half_size, -0.001f);
  glEnd();

  glColor3f(1.0f, 1.0f, 1.0f);

  for (int i = 0; i < NUM_CARDS_PER_FACE; i  )

    for (int j = 0; j < NUM_CARDS_PER_FACE; j  ) {

      glPushMatrix();
        glTranslatef(start   i * incr, start   j * incr, 0.0f);
        draw_card();
      glPopMatrix();

    }

}

// draw a cube made up of cards

void draw_card_cube() {

  const float cube_half_size = 4 * (card_half_size   space_half_size);

  // front face

  glPushMatrix();
    glTranslatef(0.0f, 0.0f, cube_half_size);
    draw_card_face();
  glPopMatrix();

  // back face

  glPushMatrix();
    glTranslatef(0.0f, 0.0f, - cube_half_size);
    glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // right face

  glPushMatrix();
    glTranslatef(cube_half_size, 0.0f, 0.0f);
    glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // left face

  glPushMatrix();
    glTranslatef(- cube_half_size, 0.0f, 0.0f);
    glRotatef(- 90.0f, 0.0f, 1.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // top face

  glPushMatrix();
    glTranslatef(0.0f, cube_half_size, 0.0f);
    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // bottom face

  glPushMatrix();
    glTranslatef(0.0f, - cube_half_size, 0.0f);
    glRotatef(- 90.0f, 1.0f, 0.0f, 0.0f);
    draw_card_face();
  glPopMatrix();


}

void display() {

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  glRotatef(x_degs, 1.0f, 0.0f, 0.0f);
  glRotatef(y_degs, 0.0f, 1.0f, 0.0f);

  gluLookAt(-0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
  draw_card_cube();
  glutSwapBuffers();

}

void reshape(int w, int h) {

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-15.0f, 15.0f, -15.0f, 15.0f, -15.0f, 15.0f);
  glViewport(0, 0, w, h);
  glMatrixMode(GL_MODELVIEW);

}

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

  glutInit(amp;argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  init();
  glutKeyboardFunc(keyboard);
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutMainLoop();
  return 0;

}
  

Хорошо, я пересмотрел код так, что теперь я рисую голубые прямоугольники на расстоянии 0,01 f единиц вместо 0,001 f единиц, и это, кажется, исправило z-битву. Однако я хотел бы использовать glPolygonOffset (factor, units), чтобы исправить эту проблему, но я не смог этого сделать из-за следующего
причины:

  1. Я не знаю, как установить facor и units (я пробовал 1.0 для обоих).
  2. Я пробовал разные значения, но безрезультатно.

Вот код без кровотечения / сшивания / z-борьбы:

 #include <GL/glut.h>
#include <stdlib.h>

#include <stdio.h>

void init() {

  glClearColor(1.0f, 0.0f, 1.0f, 1.0f);

  glEnable(GL_DEPTH_TEST);

}

static float x_degs = 0.0f;
static float y_degs = 0.0f;

void keyboard(unsigned char key, int x, int y) {

  switch (key) {

    case 'q':

      exit(EXIT_SUCCESS);

    case 'h':

      y_degs -= 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

    case 'j':

      x_degs -= 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

    case 'k':

      x_degs  = 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

    case 'l':

      y_degs  = 1.0f;

      glutPostRedisplay();

      glutSwapBuffers();

      break;

  }

}

// half the length of one card

static const float card_half_size = 1.0f;

// half the space between cards

static const float space_half_size = 0.1f;

// number of cards per face

static const int NUM_CARDS_PER_FACE = 4;
/*
// start position of center of top left card 

const float start = - 3 * (card_half_size   space_half_size);

// increment between center of cards

const float incr = 2 * (card_half_size   space_half_size);

// half the size of a cube face

const float cube_half_size = 4 * (card_half_size   space_half_size);
*/
// draw a card centered at the origin

void draw_card() {

  glBegin(GL_QUADS);
    glVertex3f(- card_half_size, - card_half_size, 0.0f);
    glVertex3f(- card_half_size, card_half_size, 0.0f);
    glVertex3f(card_half_size, card_half_size, 0.0f);
    glVertex3f(card_half_size, - card_half_size, 0.0f);
  glEnd();

}

// draw a cube face made up of cards

void draw_card_face() {

  const float cube_half_size = 4 * (card_half_size   space_half_size);
  const float start = - 3 * (card_half_size   space_half_size);
  const float incr = 2 * (card_half_size   space_half_size);

  glColor3f(0.0f, 1.0f, 1.0f);

  glBegin(GL_QUADS);
    glVertex3f(- cube_half_size, - cube_half_size, -0.001f);
    glVertex3f(- cube_half_size, cube_half_size, -0.001f);
    glVertex3f(cube_half_size, cube_half_size, -0.001f);
    glVertex3f(cube_half_size, - cube_half_size, -0.001f);
  glEnd();

  glColor3f(1.0f, 1.0f, 1.0f);

  for (int i = 0; i < NUM_CARDS_PER_FACE; i  )

    for (int j = 0; j < NUM_CARDS_PER_FACE; j  ) {

      glPushMatrix();
        glTranslatef(start   i * incr, start   j * incr, 0.0f);
        draw_card();
      glPopMatrix();

    }

}

// draw a cube made up of cards

void draw_card_cube() {

  const float cube_half_size = 4 * (card_half_size   space_half_size);

  // front face

  glPushMatrix();
    glTranslatef(0.0f, 0.0f, cube_half_size);
    draw_card_face();
  glPopMatrix();

  // back face

  glPushMatrix();
    glTranslatef(0.0f, 0.0f, - cube_half_size);
    glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // right face

  glPushMatrix();
    glTranslatef(cube_half_size, 0.0f, 0.0f);
    glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // left face

  glPushMatrix();
    glTranslatef(- cube_half_size, 0.0f, 0.0f);
    glRotatef(- 90.0f, 0.0f, 1.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // top face

  glPushMatrix();
    glTranslatef(0.0f, cube_half_size, 0.0f);
    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
    draw_card_face();
  glPopMatrix();

  // bottom face

  glPushMatrix();
    glTranslatef(0.0f, - cube_half_size, 0.0f);
    glRotatef(- 90.0f, 1.0f, 0.0f, 0.0f);
    draw_card_face();
  glPopMatrix();


}

void display() {

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  glRotatef(x_degs, 1.0f, 0.0f, 0.0f);
  glRotatef(y_degs, 0.0f, 1.0f, 0.0f);

  gluLookAt(-0.6f, 0.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
  draw_card_cube();
  glutSwapBuffers();

}

void reshape(int w, int h) {

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(-15.0f, 15.0f, -15.0f, 15.0f, -15.0f, 15.0f);
  glViewport(0, 0, w, h);
  glMatrixMode(GL_MODELVIEW);

}

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

  glutInit(amp;argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  init();
  glutKeyboardFunc(keyboard);
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);
  glutMainLoop();
  return 0;

}
  

Комментарии:

1. «пятна на гранях куба». Есть ли вероятность появления изображения?

2. Я рекомендую использовать мягкое моющее средство и мягкую ткань.

3. Здравствуйте, я не уверен, как включить изображение в stack overflow, поэтому я поделился им на PicasaWeb здесь: ! ссылка

4. Вам не нужен glutSwapBuffers() обработчик клавиатуры, просто glutPostRedisplay() s

5. Дважды проверьте, сколько бит в вашем буфере глубины через glGet() и GL_DEPTH_BITS . Некоторые пользователи могут получать 24- или 32-разрядные буферы глубины «по умолчанию», тогда как вы можете получать 16, если запускаете свою программу на виртуальной машине.

Ответ №1:

Я думаю, что вы рисуете свои шашки в виде копланарных квадратов граней вашего основного куба; если это так, проблема, с которой вы сталкиваетесь, называется «борьба с z».

Вы можете взглянуть на пункт 12.040, буферизация глубины, похоже, работает, но полигоны, похоже, просачиваются через полигоны, которые находятся перед ними. Что происходит? здесь : http://www.opengl.org/resources/faq/technical/depthbuffer.htm

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

Вы можете либо вручную добавить смещение к вашим контрольным квадратам, чтобы переместить их подальше от куба; или использовать смещение глубины через glPolygonOffset , чтобы решить проблему.

Ответ №2:

Я думаю, вы пытаетесь выполнить копланарный рендеринг. Изучите glPolygonOffset() вместо использования небольших смещений Z, как вы делаете.

Комментарии:

1. Спасибо за ваши ответы. Да, я пытался выполнить копланарный рендеринг. Насколько glPolygonOffset () более стабилен, чем использование небольших смещений z, и как мне вообще использовать его в своем коде? Как мне выбрать два параметра для glPolygonOffset () и где разместить вызовы glPolygonOffset() в коде.

Ответ №3:

Это то, что я получаю из вашего кода, скомпилированного с gcc -std=c99 -lGL -lGLU -lglut a.c : никаких пятен. Можете ли вы опубликовать свои? (Ubuntu 11.10, графический процессор Intel)

локальный снимок экрана

Комментарии:

1. Привет, спасибо за ваш ответ, например, верхняя грань полностью синяя, а не в клеточку. Теперь попробуйте ввести j, k, h, l, чтобы переместить куб. Смотрите ссылку выше, где я разместил изображение. Есть пятна (также Ubuntu 11.10 с gcc -std=c99 foo.c -lGL -lGLU -lglut

2. Куб «стабилен», если я его поворачиваю, по крайней мере, здесь. Из того, что вы опубликовали, я бы предположил, что некоторые вершины расположены очень близко друг к другу, и какой треугольник выигрывает поверхность, численно нестабилен. Не читайте код подробно, хотя.

3. Имеет ли значение тот факт, что я запускаю свой код внутри Oracle VirtualBox с Ubuntu 11.10? Моя видеокарта — NVIDIA GeForce 410M.

4. Кажется, единственное отличие — драйвер. Другие ответы, похоже, подтверждают нестабильность z-координаты, которую я также предложил.