Использование буфера глубины с GL_LINES - PullRequest
3 голосов
/ 24 ноября 2011

Я хочу нарисовать края объекта с удаленными скрытыми краями. Идея, которую я хочу применить, состоит в том, чтобы визуализировать грани объекта сначала в буфер глубины, а затем за второй проход нарисовать края с включенным тестированием глубины.

Поскольку не все ребра треугольника должны быть видимыми, ребра хранятся отдельно (простой пример: в кубе не должны быть видны диагональные ребра, хотя они и есть, поскольку квадрат представлен в виде двух треугольников). Поэтому грани рисуются с использованием GL_TRIANGLES, а грани - с GL_LINES с отдельным буфером вершин.

Проблема в том, что скрытые края частично отображаются с помощью этой настройки, а видимые края частично скрыты. Как мне добиться правильного результата?

  • без проверки глубины:

    Without depth testing

  • с проверкой глубины:

    With depth testing

  • граней, которые отображаются в буфере глубины:

    Faces only

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

// Color buffer setup.
glBindTexture(GL_TEXTURE_2D, objectEdges);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 360, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);

// Depth buffer setup.
glBindRenderbuffer(GL_RENDERBUFFER, objectFaces);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 640, 360);

// Framebuffer setup.
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
                       GL_TEXTURE_2D, objectEdges, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
                          GL_RENDERBUFFER, objectFaces);
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
assert(glGetError() == GL_NO_ERROR);

Эта настройка работает без проблем. Я рисую свой объект следующим образом:

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_TRUE);
glBindVertexArrayOES(vertexArray_faces);
glDrawArrays(GL_TRIANGLES, 0, vertexCount_faces);
glBindVertexArrayOES(0);

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_FALSE);
glBindVertexArrayOES(vertexArray_edges);
glDrawArrays(GL_LINES, 0, vertexCount_edges);
glBindVertexArrayOES(0);

glDisable(GL_DEPTH_TEST);

Используемый шейдер - это просто стандартный вершинный шейдер модели-проекции и фрагментный шейдер, который выводит белый цвет для всех фрагментов.

GLKMatrix4 projectionMatrix = 
    GLKMatrix4MakePerspective(
        GLKMathDegreesToRadians(65.0f), 640.0 / 360.0f, 0.01f, 10.0f);
GLKMatrix4 modelViewMatrix = 
    GLKMatrix4MakeLookAt(0.2f, 0.4f, 0.2f, 0.2f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);

1 Ответ

5 голосов
/ 24 ноября 2011

Вы столкнулись с проблемой, что значения глубины рассчитываются для линий немного иначе, чем для заполненных примитивов. То, что вы пытаетесь сделать, является одной из причин существования так называемого «полигона». Все это описано в официальном руководстве по программированию в приложении: «Удаление скрытой линии»

...