Я хочу сделать два шага постобработки для моего алгоритма обнаружения края: 1. Найти ребро через Собела-Эдж алгоритм обнаружения 2. Тонких края с помощью морфологического истонченияOpenGL/OpenTK - Несколько фреймбуфера
Итак, что Я хочу достичь - превратить всю сцену в отдельный фреймбуфер, образец созданной текстуры, чтобы найти все ребра и, наконец, снова пробовать вновь сгенерированную текстуру, чтобы тонкие края.
Таким образом, я решил, что для достижения этой цели мне нужны три фреймбуфера (один для обнаружения края, один для прореживания и фреймбуфер по умолчанию). Первый дополнительный фреймбуфер использует три текстуры, а именно цвет, нормали и глубину. Второй дополнительный фреймбуфер должен использовать сгенерированные изображения первого фреймбуфера, чтобы выполнить прореживание и снова выводить его.
Если я использую два фреймбуфера (по умолчанию fb и определение края fb), все работает нормально. Но как только я добавляю дополнительный третий fb, текстура, созданная этим третьим фреймбуфером, не отображается. Вместо этого отображается черное окно.
Так вот код для инициализации первого фреймбуфером:
private void GenerateFramebuffer()
{
//Generate framebuffer
framebuffer = GL.GenFramebuffer();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);
// create a RGBA color texture
GL.GenTextures(1, out textureColorBuffer);
GL.BindTexture(TextureTarget.Texture2D, textureColorBuffer);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
glControl1.Width, glControl1.Height,
0, (PixelFormat)PixelInternalFormat.Rgba, PixelType.UnsignedByte,
IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
GL.BindTexture(TextureTarget.Texture2D, 0);
// create a RGBA color texture for normals
... generated like texture above
// create a depth texture
... generated like texture above
////Create color attachment texture
GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, textureColorBuffer, 0);
GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment1, normalBuffer, 0);
GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, depthBuffer, 0);
DrawBuffersEnum[] bufs = new DrawBuffersEnum[2] { (DrawBuffersEnum)FramebufferAttachment.ColorAttachment0, (DrawBuffersEnum)FramebufferAttachment.ColorAttachment1 };
GL.DrawBuffers(bufs.Length, bufs);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}
Все работает хорошо, никаких проблем не возникает. Второй фреймбуфера создаются одинаково, за исключением того, что мне нужно только прикрепление один цвета:
private void GenerateFramebuffer2()
{
//Generate framebuffer
framebuffer2 = GL.GenFramebuffer();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer2);
// create a RGBA color texture
GL.GenTextures(1, out edgeBuffer);
GL.BindTexture(TextureTarget.Texture2D, edgeBuffer);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
glControl1.Width, glControl1.Height,
0, (PixelFormat)PixelInternalFormat.Rgba, PixelType.UnsignedByte,
IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
GL.BindTexture(TextureTarget.Texture2D, 0);
////Create color attachment texture
GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, edgeBuffer, 0);
DrawBuffersEnum[] bufs = new DrawBuffersEnum[1] { (DrawBuffersEnum)FramebufferAttachment.ColorAttachment0};
GL.DrawBuffers(bufs.Length, bufs);
//No need for renderbuffer object since we don't need stencil buffer yet
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
}
А теперь приходит рендеринга часть: Сначала я связываю первый видеобуфер и использовать фрагмент шейдер для вывода нормалей и цветовых значений к два вложения:
GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // We're not using stencil buffer so why bother with clearing?
GL.Enable(EnableCap.DepthTest);
Shader.Use();
Model.Draw();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
Затем я связать второй FB и использовать текстуры, что предыдущие фреймбуфера сгенерированные:
GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebuffer2);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // We're not using stencil buffer so why bother with clearing?
//Find edges and put them in separate texture (colors not needed here)
edgeDetectionShader.Use();
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.Texture2D, normalBuffer);
GL.Uniform1(GL.GetUniformLocation(edgeDetectionShader.program, "normalTexture"), 1);
GL.ActiveTexture(TextureUnit.Texture2);
GL.BindTexture(TextureTarget.Texture2D, depthBuffer);
GL.Uniform1(GL.GetUniformLocation(edgeDetectionShader.program, "depthTexture"), 2);
И, наконец, я связываю с фреймбуфером по умолчанию и нарисуйте сгенерированные текстуры на простой четырехугольника:
/////////////////////////////////////////////////////
// Bind to default framebuffer again and draw the
// quad plane with attched screen texture.
// //////////////////////////////////////////////////
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
// Clear all relevant buffers
GL.ClearColor(1, 1, 1, 1); // Set clear color to white
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.Disable(EnableCap.DepthTest); // We don't care about depth information when rendering a single quad
//Combine edges with color values
finalImageProzessingShader.Use();
GL.BindVertexArray(quadVAO);
//Testing purpose: Send color texture to the shader
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, textureColorBuffer);
GL.Uniform1(GL.GetUniformLocation(finalImageProzessingShader.program, "screenTexture"), 0);
//Testing purpose: Send normal texture to the shader
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.Texture2D, normalBuffer);
GL.Uniform1(GL.GetUniformLocation(finalImageProzessingShader.program, "normalTexture"), 1);
//Testing purpose: Send depth texture to the shader
GL.ActiveTexture(TextureUnit.Texture3);
GL.BindTexture(TextureTarget.Texture2D, depthBuffer);
GL.Uniform1(GL.GetUniformLocation(finalImageProzessingShader.program, "depthTexture"), 2);
//Send the texture of fb2 to shader (generates black screen)
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, edgeBuffer);
GL.Uniform1(GL.GetUniformLocation(finalImageProzessingShader.program, "depthTexture"), 3);
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
GL.BindVertexArray(0);
Так выводя цвет текстуры, глубину текстуры или нормальную структуру, порожденную фреймбуфером один работает, но если я выход текстуры сгенерированный framebuffer two, я получаю черный экран. Я также пробовал его с TextureUnit.Texture4 при использовании edgeBuffer, но это тоже не работает.
Это даже правильный подход, когда я хочу сделать 2 этапа после обработки?