Можно ли прочитать один образец из MSAA FBO?
Используя OpenGL для рисования объектов, а также чтобы мой фрагментный шейдер выдал скалярный целочисленный идентификатор. Для рисования объектов я использую мультисэмплинг для сглаживания, поэтому, когда я создаю буфер для целочисленного идентификатора, я должен создать его как буфер MSAA, чтобы FBO было завершено:
glBindRenderbuffer(GL_RENDERBUFFER, rboColorId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaSamples, GL_RGBA8,
cam.getWidth(), cam.getHeight());
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaSamples, GL_DEPTH_COMPONENT,
cam.getWidth(), cam.getHeight());
glBindRenderbuffer(GL_RENDERBUFFER, rboObjId);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaaSamples, GL_R32UI,
cam.getWidth(), cam.getHeight());
glBindRenderbuffer(GL_RENDERBUFFER, rboColorNoMsaaId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8,
cam.getWidth(), cam.getHeight());
glBindRenderbuffer(GL_RENDERBUFFER, rboObjNoMsaaId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_R32UI,
cam.getWidth(), cam.getHeight());
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboColorId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rboObjId);
glBindFramebuffer(GL_FRAMEBUFFER, fboNoMsaaId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rboColorNoMsaaId);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, rboObjNoMsaaId);
Как вы можете видеть в коде выше, у меня есть 2 FBO. Первый - это MSAA, в котором есть буфер для рисования сцены, буфер глубины и целочисленный буфер для идентификаторов. Второе FBO с одиночной выборкой (не MSAA) и имеет только буфер сцены рисования и буфер целых чисел. После того, как я нарисовал все (фрагментный шейдер устанавливает значения для каждого пикселя), я прочитал буфер целочисленного идентификатора (GL_COLOR_ATTACHMENT1), сначала перетащив его в одиночный FBO выборки, чтобы я мог получить из него glReadPixels. В этом конкретном коде я просто читаю 1 пиксель, на который указывает мышь:
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId);
glReadBuffer(GL_COLOR_ATTACHMENT1);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboNoMsaaId);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(mouse_x_pos, cam.getHeight() - mouse_y_pos, mouse_x_pos+1, cam.getHeight() - mouse_y_pos + 1,
0, 0, 1, 1,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboNoMsaaId);
glReadBuffer(GL_COLOR_ATTACHMENT1);
GLuint objectId;
glReadPixels(0, 0, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &objectId);
Моя проблема в том, что когда я блею, мультисэмплы для нужного пикселя интерполируются в один пиксель, который я получаю для чтения. Я хочу это для цветового буфера, который я использую для рисования сцены, но я не хочу этого для целочисленных идентификаторов, которые я читаю. Если я читаю пиксель, который содержит фрагменты как для идентификатора 50, так и для идентификатора 100, я хочу прочитать либо 50, либо 100 (все равно, какие). Но то, что я получаю, это какое-то значение между 50 и 100, например 75. 75 на самом деле может быть совершенно другим пикселем, поэтому я не хочу этого вообще.
Что я могу сделать, чтобы прочитать один образец для целочисленного идентификатора вместо интерполяции нескольких образцов?
1 ответ
Вместо того, чтобы разрешать текстуру мультисэмпла путем блиттинга, вы можете реализовать собственное разрешение мультисэмпла на этапе рендеринга в текстуру. Вы можете использовать сэмплер типа sampler2DMS
и использовать это texelFetch( variant
:
gvec4 texelFetch( gsampler2DMS sampler, ivec2 P, int sample);
так P
являются 2D ненормализованными текселевыми координатами, и sample
это идентификатор образца. Если вы действительно не заботитесь о том, какое из значений вы получаете, вы можете просто использовать образец 0 все время. Но вы также можете, например, перебрать все образцы и взять тот, который встречается чаще всего, или любой другой, который соответствует вашим потребностям.
Чтобы это работало, вам придется переключиться с рендеринга буфера для прикрепления идентификатора на многосэмплированную 2D текстуру.
Таким образом, по сути, вы можете привязать немультисэмплированный FBO как рисовать FBO, сделать стандартный блик для текстур глубины и цвета, а также выполнить полноэкранный рендеринг с текстурой мультисэмплированного идентификатора, записав в цветовое приложение немультисэмплированного идентификатора.