Как избавиться от проблемы z -ighting в OpenGL? - PullRequest
2 голосов
/ 01 августа 2011

Я пишу симулятор полета и застрял в классической проблеме этого жанра: ближняя плоскость поля зрения должна быть достаточно близко, чтобы сделать кабину самолета видимой, дальний самолет должен быть далеко, чтобы обеспечить видимые расстоянияс длиной до 40 км.

Расстояние видимости или отношение ближнего / дальнего радиуса действительно превышает точность точности z-буфера для opengl и удаленных объектов, которые сильно мерцают.Это место, где причудливый 3D-движок оставляет вас наедине со своей проблемой, и вам нужно истинное знание opengl :).Вероятно, я нашел правильный способ исправить проблему (эксперты OpenGL меня поправят, если я ошибаюсь), но мое решение упускает важный момент.Измененный рендерер выполняет двухпроходный рендеринг:

  1. в первом проходе должны отображаться удаленные объекты и фон, удалена ближняя плоскость, z-буфер доволен, местность выглядит хорошо, но ближние объекты отсечены.
  2. во втором проходе матрица проекции настраивается для объектов ближнего действия и должна отображать кабину.

Нерешенная проблема: во втором проходе все дальниеобъекты и фон невидимы, поэтому у меня есть кабина и черный фон за ней.Результат второго прохода полностью тратит впустую результат первого прохода.Ergo запланированного наложения не происходит.Вопрос: как заставить opengl игнорировать цвет фона во втором проходе, чтобы результаты обоих проходов создавали желаемое наложение?

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

http://www.flickr.com/photos/43342833@N04/5995604542/sizes/l/in/photostream/

Очистка буфера происходит только один раз за цикл рендеринга и не включается между 2 проходами.Здесь код очистки:

JoglContext jctx = (JoglContext) ctx;
GLContext context = context(ctx);
GL gl = context.getGL();
// Mask of which buffers to clear, this always includes color & depth
int clearMask = GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT;
gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT);
gl.glDepthMask(true);
gl.glClearColor(r, g, b, jctx.getAlphaClearValue());
gl.glClear(clearMask);
gl.glPopAttrib();

Подход, который вы описываете, также используется в 2 проходах: 1. проекция «на большие расстояния» и рельеф местности 2. «короткое расстояние» и кабина не пропускаются, но послевторой проход фон позади кабины черный.Может быть, функция glDepthRange поможет, надо проверить руководства.

Глубина zbuffer составляет 24 бита.

Ответы [ 2 ]

6 голосов
/ 01 августа 2011

Не очищать экран между двумя проходами.Если вы просто хотите очистить буфер глубины, то очистите просто буфер глубины.Не передавайте GL_COLOR_BUFFER_BIT на glClear.

. В любом случае, лучший способ сделать это (чтобы вам не нужно было перерисовывать все), это использовать надлежащий диапазон глубины.Так как ваша кабина не может пересекаться со сценой, нет причин для ее встраивания в диапазон глубины сцены.

Итак, сначала вы рисуете свою сцену, используя разумную матрицу перспективы (то есть: ту, у которой z-ближняядостаточно большой. Порядка нескольких футов или около того).Ваша сцена не состоит из вашей кабины.glDepthRange для этого рендеринга должно быть примерно таким: [0,05, 1,0].

После этого вы рисуете свою кабину, используя разумную перспективную матрицу только для кабины.glDepthRange для этого будет [0,05].Это должно дать вам много битов глубины точности как для сцены, так и для кабины.

О, и убедитесь, что вы получаете 24-битный буфер глубины.

2 голосов
/ 01 августа 2011

Кабина против внешнего - это классический случай буфера трафарета, очень похожий на HUD против сцены. Преимущество трафарета в том, что вам вообще не нужен z, поэтому вы можете установить ближнюю плоскость гораздо дальше. Кроме того, окна, через которые вы видите, не меняются (за исключением случаев, когда вы поворачиваете виртуальную головку внутри кабины), так что это вещь, которая используется один раз для многократного использования.

Также, логарифмический z может быть интересным для вас.

...