CSAA/MSAA и зеркальные огни
Я реализовал поддержку MSAA в нескольких вариантах:
Он может использовать либо контекст, основанный (путем вызова wglChoosePixelFormatARB при настройке контекста и передачи ему соответствующего списка параметров), либо путем включения рендеринга MSAA в FBO (создание мультисэмплирующего FBO с вложением визуального буфера цвета и глубины и другого FBO с вложенным цветом для разрешения), и сглаживание, кажется, работает в целом.
Однако я обнаружил некоторые артефакты, которые, по-видимому, связаны с зеркальным освещением, когда я включаю сглаживание. Это хуже всего для контекстно-ориентированной CSAA и довольно плохо для контекстно-ориентированной MSAA, но гораздо лучше, когда я использую MSAA при рендеринге в мой FBO.
Для одной из моделей самолетов, которые я использую для тестирования, это очень заметно, особенно вокруг цилиндров двигателя и некоторых "проводов" (на самом деле это не линии, а тонкие цилиндры):
Как вы можете видеть на изображении, когда я выключаю зеркальные источники света, проблема в значительной степени исчезает, но я не совсем уверен, что ее вызывает.
Изображения выше используют этот код шейдера для расчета зеркального отражения (внутри цикла для всех источников света):
if( matShininess > 0.0 )
{
vec3 reflectionCamSpace = reflect(-lightDirectionCamSpace, faceNormal);
vec3 surfToViewerCamSpace = normalize (-vertPositionCamSpace);
float dotSpecular = max( 0.0, dot (reflectionCamSpace, surfToViewerCamSpace) );
float specularFactor = pow( dotSpecular, matShininess );
specularTerm += vec3(lgt.specular * specularFactor);
}
Также, кажется, есть большая разница между различными моделями освещения:
Левая сторона использует вышеупомянутый код для зеркальных бликов, тогда как правая сторона использует это (снова внутри основного цикла освещения, который проходит через все источники света)
if( matShininess > 0.0 )
{
vec3 surfToViewerCamSpace = normalize (-vertPositionCamSpace);
vec3 halfAngle = normalize(lightDirectionCamSpace + surfToViewerCamSpace);
float specularFactor = dot(faceNormal, halfAngle);
specularFactor = clamp(specularFactor, 0, 1);
specularFactor = lightDot != 0.0 ? specularFactor : 0.0;
specularFactor = pow(specularFactor, matShininess);
specularTerm += vec3(lgt.specular * specularFactor);
}
Поэтому мне интересно, почему такая большая разница при использовании MSAA на основе FBO и контекстной. А также, что я сделал не так с моими зеркальными бликами, чтобы создать проблему в первую очередь?
Изменить: В соответствии с запросом ниже я также добавил тест для сравнения результатов CSAA 16xQ через контекст и через FBO (для FBO я просто использую RenderbufferStorageMultisampleCoverageNV вместо glRenderbufferStorageMultisample). Снова результат FBO кажется лучше (но все еще не убедительным):
1 ответ
Это не ответ;больше похоже на длительный запрос комментариев.
Затенение образца может помочь, вы можете попросить GL оценивать шейдер несколько раз, вместо того, чтобы выполнять вычисления один раз для фрагмента и переносить результаты во все образцы, если покрытие позволяет эту оптимизацию. С MSAA шейдер оценивается только один раз для фрагмента, примитив которого полностью покрывает пиксель. Сэмплы глубины / трафарета являются уникальными для каждого сэмпла, и это помогает с наложением краев, но любое наложение, которое происходит внутри самого шейдера (например, наложение текстур, зеркальное выделение и т. Д.), Не исправляется с использованием чистого MSAA.
Затенение образца эффективно превращает MSAA в нечто среднее между MSAA (несколько образцов могут быть закрашены один раз) в SSAA (1:1 образец: отношение затенения). Почему ваша проблема обнаруживается только при использовании разрешения MSAA, выполняемого кадровым буфером по умолчанию, я не могу сказать. Но затенение образца должно помочь.
Что касается CSAA, то это полностью выходит за рамки вещей, над которыми нерасширенный GL имеет какой-либо контроль. Нет никакого понятия CSAA где-нибудь в ванильном трубопроводе GL. Хотя вы можете реализовать это с помощью FBO, если вы используете NVNV_framebuffer_multisample_coverage
расширение.
Честно говоря, я бы почти всегда отдавал предпочтение сглаживанию на основе FBO в наши дни. Вам не нужно заново создавать контекст рендеринга, чтобы конечный пользователь мог изменить настройки АА, если вы это сделаете, что означает гораздо меньшую перезагрузку ресурсов, если пользователь начнет экспериментировать с настройками конфигурации для производительности / качества изображения. Это гораздо более гибкий дизайн, и вы даже можете использовать отложенное затенение MSAA, используя FBO на современном оборудовании, благодаря мультисэмпловому извлечению текстур (вы можете реализовать разрешение на уровне шейдера).
Мне было бы любопытно узнать, имели ли вы какие-либо различия между CSAA на основе контекста и FBO или если какое-либо влияние имеет явная установка минимального количества образцов затенения.