Я играл с OpenGL целую неделю или эквивалент.После 2D я сейчас пробую 3D.Я хочу воспроизвести 3D-сцену, которую вы можете увидеть в третьем видео на http://johnnylee.net/projects/wii/.
Мне было трудно заставить все работать должным образом с текстурами и глубиной.
У меня недавно было 2 проблемыкоторые визуально имеют несколько одинаковое воздействие:
- Один с текстурами, которые не очень хорошо сочетаются в 3D, с использованием техник, которые я нашел для 2D.
- Один с объектами, которые отображаются снизу вверх,Как проблема, описанная здесь: Буфер глубины в OpenGL
Я решил обе проблемы, но я хотел бы знать, правильно ли я все понял , специально для второго пункта .
Для первого , я думаю, он у меня есть.У меня есть изображение круглой цели с альфой для всего, что находится за пределами диска.Он хорошо загружен внутри OpenGL.Некоторые (из-за моей проблемы z-упорядочения) другие цели позади него страдали от того, что были скрыты прозрачными областями квадрата естественного квадрата, который я использовал для его рисования.
Причина этого состояла в том, что каждая часть текстурыпредполагается, что он полностью непрозрачен с учетом буфера глубины.Использование glEnable(GL_ALPHA_TEST)
с тестом для glAlphaFunc(GL_GREATER, 0.5f)
заставляет альфа-слой текстуры действовать как индикатор непрозрачности (булево) и, таким образом, делает смешивание совершенно бесполезным (потому что мое изображение имеет логическую прозрачность).
Дополнительный вопрос: Кстати, есть ли способ указать источник альфа-теста, отличный от альфа-слоя, используемого для смешивания?
Второй , я нашел решение моей проблемы.Перед очисткой буфера цвета и глубины я установил глубину по умолчанию 0 glClearDepth(0.0f)
, и я использовал "большую" функцию глубины glDepthFunc(GL_GREATER)
.
Что мне кажется странным, так это то, что глубинаравен 1.0, а функция глубины по умолчанию «меньше» GL_LESS
.Я в основном инвертирую это, чтобы мои объекты не отображались в перевернутом виде ...
Я нигде не видел такого взлома, но, с другой стороны, я не видел, чтобы объекты систематически рисовались внеправильный порядок, независимо от того, в каком порядке я их рисую !
Хорошо, вот фрагмент кода (урезанный, надеюсь, не слишком много), который сейчас работает так, как я хочу:
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(600, 600); // Size of the OpenGL window
glutCreateWindow("OpenGL - 3D Test"); // Creates OpenGL Window
glutDisplayFunc(display);
glutReshapeFunc(reshape);
PngImage* pi = new PngImage(); // custom class that reads well PNG with transparency
pi->read_from_file("target.png");
GLuint texs[1];
glGenTextures(1, texs);
target_texture = texs[0];
glBindTexture(GL_TEXTURE_2D, target_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, pi->getGLInternalFormat(), pi->getWidth(), pi->getHeight(), 0, pi->getGLFormat(), GL_UNSIGNED_BYTE, pi->getTexels());
glutMainLoop(); // never returns!
return 0;
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1, 1, -1, 1);
gluPerspective(45.0, w/(GLdouble)h, 0.5, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display(void) {
// The stared *** lines in this function make the (ugly?) fix for my second problem
glClearColor(0, 0, 0, 1.00);
glClearDepth(0); // ***
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_DEPTH_FUNC); // ***
glDepthFunc(GL_GREATER); // ***
draw_scene();
glutSwapBuffers();
glutPostRedisplay();
}
void draw_scene() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.5, 0, -3, 0, 0, 1, 0, 1, 0);
glColor4f(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
// The following 2 lines fix the first problem
glEnable(GL_ALPHA_TEST); // makes highly transparent parts
glAlphaFunc(GL_GREATER, 0.2f); // as not existent/not drawn
glBindTexture(GL_TEXTURE_2D, target_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Drawing a textured target
float x = 0, y = 0, z = 0, size = 0.2;
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(x-size, y-size, z);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(x+size, y-size, z);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(x+size, y+size, z);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(x-size, y+size, z);
glEnd();
// Drawing an textured target behind the other (but drawn after)
float x = 0, y = 0, z = 2, size = 0.2;
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(x-size, y-size, z);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(x+size, y-size, z);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(x+size, y+size, z);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(x-size, y+size, z);
glEnd();
}