2016-08-03 5 views
0

Я хочу сделать два шага постобработки для моего алгоритма обнаружения края: 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 этапа после обработки?

ответ

0

Ну, ответ заключается в рендеринге сцены на квадроцикл, хотя это не окончательное изображение, которое должно выводиться на дисплей.

Так шаги для выполнения Медленно Много почтовых процессов являются:

-> Bind 1st render texture 
-> Draw scene 

-> Bind 2nd render texture 
-> Feed 1st render texture to a shader and draw quad 

-> Bind 1st render texture 
-> Feed 2nd render texture to another shader and draw quad 

-> Bind 2nd render texture 
-> Feed 1st render texture to a third shader and draw quad 

... 
-> Unbind 
-> Draw quad 

(см Post processing and resulting texture)

Так выше код правильно, только рисунок на четырехъядерный после первого фреймбуфера отсутствует (только в случае, если это кому-то еще понадобится).

Смежные вопросы