Пытаясь реализовать сглаживание поверх отложенного затенения, я пытаюсь использовать буферы рендеринга с несколькими выборками, а затем разрешать выборки с помощью прохода буфера-блита.
Как обычно в отложенном затенении, я рендерил сцену с выделенным шейдером, выдавая 3 цветовых выхода:
- Должность
- нормали
- Диффузный и зеркальный
Затем они используются в проходе вычисления освещения, что приводит к окончательной текстуре сцены
Текстура сцены отображается на экране в полноэкранном четырехугольнике с использованием упрощенного шейдера
Как вы, вероятно, догадались, экранное MSAA не применяется к содержимому текстуры сцены при визуализации на экране:
таким образом, чтобы добиться сглаживания, я решил использовать буферы рендеринга с несколькими выборками на шаге 1) и ввел дополнительный шаг 1.1) для разрешения. Конечно, мультисэмплинг необходим / полезен только для цветовой карты, а не для 2 других карт.
Моя проблема и вопрос в том, что, очевидно, кадровый буфер с несколькими буферами рендеринга / цветными вложениями может быть определен только для одних и тех же типов вложений; Это означает, что если одно вложение является множественным, то все остальные должны быть.
Это становится проблемой для буферов положений и нормалей во время разрешения, потому что на геометрию и освещение влияет сглаживание.
- Является ли мое понимание верным в отношении вложений кадрового буфера?
- Есть ли способ обойти это, чтобы по-прежнему иметь множественную выборку на карте Diffuse & Specular, но не влиять на другие карты?
// Create the frame buffer for deferred shading: 3 color attachments and a depth buffer
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
{
// - Position color buffer
glGenRenderbuffers(1, &gPosition);
glBindRenderbuffer(GL_RENDERBUFFER, gPosition);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGBA16F, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, gPosition);
// - Normal color buffer
glGenRenderbuffers(1, &gNormal);
glBindRenderbuffer(GL_RENDERBUFFER, gNormal);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGBA16F, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, gNormal);
// - Color + specular color buffer
glGenRenderbuffers(1, &gColorSpec);
glBindRenderbuffer(GL_RENDERBUFFER, gColorSpec);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGBA, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_RENDERBUFFER, gColorSpec);
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
// - Generate the depth buffer for rendering
glGenRenderbuffers(1, &sceneDepth);
glBindRenderbuffer(GL_RENDERBUFFER, sceneDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, w, h);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH_COMPONENT, w, h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, sceneDepth);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Create a frame buffer with 3 attachments for sample resolution
glGenFramebuffers(1, &gFrameRes);
glBindFramebuffer(GL_FRAMEBUFFER, gFrameRes);
{
glGenTextures(1, &gPositionRes);
glBindTexture(GL_TEXTURE_2D, gPositionRes);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, w, h, 0, GL_RGB, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPositionRes, 0);
glGenTextures(1, &gNormalRes);
glBindTexture(GL_TEXTURE_2D, gNormalRes);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, w, h, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormalRes, 0);
glGenTextures(1, &gColorSpecRes);
glBindTexture(GL_TEXTURE_2D, gColorSpecRes);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColorSpecRes, 0);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// ...
//
// Once the scene is rendered, resolve:
glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gFrameRes);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, sw, sh, 0, 0, sw, sh, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, sw, sh, 0, 0, sw, sh, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glReadBuffer(GL_COLOR_ATTACHMENT2);
glDrawBuffer(GL_COLOR_ATTACHMENT2);
glBlitFramebuffer(0, 0, sw, sh, 0, 0, sw, sh, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
Результат приведенного выше примера кода состоит в том, что на краях освещенного объекта появляются артефакты неоправданно темных / черных или ярких / белых пикселей, возможно потому, что их положение и / или нормаль были изменены в процессе.