У меня есть шейдер GLSL, который рисует 3D-кривую с учетом набора кривых Безье (3d-координаты точек). Сам чертеж выполняется так, как я хочу, за исключением того, что окклюзия работает некорректно, т. Е. При определенных точках зрения кривая, которая, как предполагается, находится в самой передней части, по-видимому, все еще закрыта, а наоборот: часть кривой, которая предполагается чтобы быть окклюдированным, все еще видно.Шейдер GLSL: порядок окклюзии и отбраковка
Для иллюстрации, вот несколько примеров скриншотов:
1 - Цветная кривая ближе к камере, поэтому он визуализируется правильно здесь.
2 - Цветная кривая должна находиться за серой кривой, но она отображается сверху.
Я новичок в GLSL и не может знать правильный термин для такого рода эффект, но я предполагаю, что это закупорка выбраковки (обновление: это фактически указывает на проблему с буфером глубины, терминологической путанице). Мой вопрос: как я могу справиться с окклюзами при использовании шейдеров GLSL? Должен ли я лечить их в шейдерной программе или где-то еще?
Что касается моего кода, это немного долго (плюс я использую OpenGL библиотеку оболочки), но основные шаги:
- В вершинном шейдере, рассчитать
gl_Position = ModelViewProjectionMatrix * Vertex;
и передать дальше информацию цвета геометрии шейдер. - В геометрическом шейдере я беру 4 контрольных точки (
lines_adjacency
) и соответствующие им цвета и создаю треугольную полосу, которая следует кривой Безье (я использую некоторую базовую цветовую интерполяцию между сегментами Безье). - Фрагментный шейдер также прост:
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);
). Это решило мою проблему.
Что касается настроек буфера глубины, я не должен был явно указывать их, так как библиотека, которую я использую, по умолчанию правильно настроила, насколько мне нужно.
Используйте отладчик, например apitrace или renderdoc, чтобы узнать, какие значения глубины записываются в буфер глубины. – pleluron
Если я не смогу понять это на уровне теории, я попробую. – vicrucann
У вас есть буфер глубины? В зависимости от инструментария/рамки оконной системы, которую вы используете для настройки контекста и поверхности рендеринга, это может быть значение по умолчанию, или вам, возможно, придется специально запросить его. –