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(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(argv[0]);
init();
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Хорошо, я изменил код, так что я рисую голубые прямоугольники на 0,01f позади, а не на 0,001f сзади, и это, похоже, исправило z-бой. Однако мне бы хотелось использовать glPolygonOffset(factor, unit) для решения этой проблемы, но я не смог это сделать по следующим причинам:
- Я не знаю, как установить facor и единицы измерения (я пробовал 1.0 для обоих).
- Я пробовал разные значения безрезультатно.
Вот код без кровотечения / сшивания / 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(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(argv[0]);
init();
glutKeyboardFunc(keyboard);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
3 ответа
Я думаю, что вы рисуете свои шашки как копланарные квадраты граней вашего главного куба; если это так, проблема, с которой вы сталкиваетесь, называется "Z сражается".
Вы можете взглянуть на пункт 12.040. Буферизация глубины, кажется, работает, но полигоны, кажется, просачиваются через полигоны, которые находятся перед ними. В чем дело? здесь: http://www.opengl.org/resources/faq/technical/depthbuffer.htm
По сути, ваш буфер глубины не имеет достаточной точности, чтобы определить, какой квадр отображать для каждого пикселя, что вызывает проблему.
Вы можете вручную добавить смещение к четырем шашкам, чтобы отодвинуть их от куба; или используйте глубину смещения через glPolygonOffset
решить вопрос.
Я думаю, что вы пытаетесь сделать компланарный рендеринг. Заглянуть в glPolygonOffset()
вместо использования небольших смещений Z, как вы делаете.
Это то, что я получаю из вашего кода, скомпилированного с gcc -std=c99 -lGL -lGLU -lglut a.c
: нет пятен. Вы можете опубликовать свой? (Ubuntu 11.10, Intel GPU)