2016-09-10 3 views
2

У меня есть шейдер GLSL, который рисует 3D-кривую с учетом набора кривых Безье (3d-координаты точек). Сам чертеж выполняется так, как я хочу, за исключением того, что окклюзия работает некорректно, т. Е. При определенных точках зрения кривая, которая, как предполагается, находится в самой передней части, по-видимому, все еще закрыта, а наоборот: часть кривой, которая предполагается чтобы быть окклюдированным, все еще видно.Шейдер GLSL: порядок окклюзии и отбраковка

Для иллюстрации, вот несколько примеров скриншотов:

1 - Цветная кривая ближе к камере, поэтому он визуализируется правильно здесь. correct render

2 - Цветная кривая должна находиться за серой кривой, но она отображается сверху. wrong render

Я новичок в GLSL и не может знать правильный термин для такого рода эффект, но я предполагаю, что это закупорка выбраковки (обновление: это фактически указывает на проблему с буфером глубины, терминологической путанице). Мой вопрос: как я могу справиться с окклюзами при использовании шейдеров GLSL? Должен ли я лечить их в шейдерной программе или где-то еще?

Что касается моего кода, это немного долго (плюс я использую OpenGL библиотеку оболочки), но основные шаги:

  1. В вершинном шейдере, рассчитать gl_Position = ModelViewProjectionMatrix * Vertex; и передать дальше информацию цвета геометрии шейдер.
  2. В геометрическом шейдере я беру 4 контрольных точки (lines_adjacency) и соответствующие им цвета и создаю треугольную полосу, которая следует кривой Безье (я использую некоторую базовую цветовую интерполяцию между сегментами Безье).
  3. Фрагментный шейдер также прост: gl_FragColor = VertexIn.mColor;.

Что касается настроек OpenGL, я включаю GL_DEPTH_TEST, но, похоже, у меня нет ничего из того, что мне нужно. Кроме того, если я помещаю любую другую геометрию без шейдера на сцену (например, quad), кривые всегда отображаются сверху, независимо от точки обзора.

Любые идеи и советы о том, как его решить и почему это происходит, оцениваются.

решение Update

Таким образом, исходная задача, как я узнал, не о нахождении алгоритма отбрасывания невидимых граней, но я не обрабатывает вычисление г значений правильно (см принятого ответа) , Я также узнал, что, учитывая правильную настройку буфера глубины, OpenGL правильно обрабатывает окклюзии, поэтому мне не нужно повторно изобретать колесо.

Я искал в своей программе GLSL и обнаружил, что я в основном устанавливаю z-значения как нули в своем геометрическом шейдере при переводе координат вершин на координаты экрана (vec2(vertex.xy/vertex.w) * Viewport;). Я исправил его, вычислив значения z (vertex.z/vertex.w) отдельно и присвоив их испускаемым точкам (gl_Position = vec4(screenCoords[i], zValues[i], 1.0);). Это решило мою проблему.

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

+0

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

+0

Если я не смогу понять это на уровне теории, я попробую. – vicrucann

+0

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

ответ

1

Если вы не используете буфер глубины, то последний обработанный объект будет сверху.

Вам необходимо включить его с помощью glEnable(GL_DEPTH_TEST), установить функцию по своему усмотрению (glDepthFunc(GL_LEQUAL)) и убедиться, что вы очистите ее каждый кадр всем остальным (glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)).

Затем убедитесь, что ваш вершинный шейдер правильно задает значение Z конечной вершины. Похоже, что для вас самый простой способ - установить часть «Модель» ModelViewProjectionMatrix на стороне процессора, чтобы иметь значение глубины перед тем, как оно будет передано в шейдер.

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

+0

Не могли бы вы пояснить немного, что означает «вершинный шейдер, правильно устанавливающий значение Z конечной вершины»? Что такое Z-значение, это 'gl_Position.z'? и что такое ** надлежащее ** z-значение? – vicrucann

+0

Значение Z vec4 (например, gl_Position) подобно X и Y, но для глубины. Правильное значение Z - это что-то между 0 и 1 или любым другим, что вы установили zNear и zFar, когда делаете свою проекционную матрицу. 0 - экран, а 1 выталкивает заднюю часть монитора, поэтому, когда вы устанавливаете функцию глубины в GL_LEQUAL, вы говорите, что делаете только объекты, наиболее близкие к монитору. –

+0

Более конкретный пример состоит в том, что если вы установите глубину радуги на 0,8 и оттенки серого на 0,2 и сначала отрисуете полутоновые изображения, перекрывающиеся пиксели на радуге проваливают проверку глубины и не рисуют, потому что 0,8 не меньше или равно 0.2. Если вы переверните порядок рисования и сначала нарисуете радугу, тогда вместо полутоновых пикселей пересекаются оттенки серого. 0.2 меньше или равно 0,8, поэтому он перекрывает радужные пиксели с оттенками серого. –

 Смежные вопросы

  • Нет связанных вопросов^_^