Lấy kết cấu từ trình kết xuất đồ họa trong OpenGL?


13

Tôi đã có một renderbuffer (DepthStpson) trong một FBO và tôi cần lấy một kết cấu từ nó. Tôi dường như không thể có cả kết cấu DepthComponent và trình kết xuất DepthStpson trong FBO, vì vậy tôi cần một số cách để chuyển đổi trình kết xuất thành kết cấu DepthComponent sau khi tôi hoàn thành nó để sử dụng sau này.

Tôi đã thử rất nhiều kỹ thuật để lấy thành phần độ sâu từ renderbuffer trong nhiều tuần nhưng tôi luôn phát hiện ra rác. Tất cả những gì tôi muốn ở cuối là cùng một kết cấu mà tôi nhận được từ một FBO nếu tôi không sử dụng trình kết xuất đồ họa. Bất cứ ai cũng có thể đăng một số hướng dẫn toàn diện hoặc mã bao gồm hoạt động có vẻ đơn giản này?

BIÊN TẬP:

Liên kết với phiên bản trích xuất của mã http://dl.dropbox.com/u/9279501/fbo.cs

Sàng lọc hiệu ứng Độ sâu của Trường + FBO - không có chiều sâu (!) Http://i.stack.imgur.com/Hj9Oe.jpg

Sàng lọc không có hiệu ứng Độ sâu trường ảnh + FBO - độ sâu hoạt động tốt http://i.stack.imgur.com/boOm1.jpg

Câu trả lời:


2

Thay phiên, bạn có thể chuyển từ FBO này sang FBO khác, chẳng hạn như từ một nền tảng kết xuất đồ họa sang một nền tảng dựa trên kết cấu. Tôi làm theo cách này:

glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_renderBufferSurface->m_fbo);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_textureSurface->m_fbo);
glBlitFramebufferEXT(0, 0, m_renderBufferSurface->m_width, m_renderBufferSurface->m_height, 0, 0, m_textureSurface->m_width, m_textureSurface->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

(Trong trường hợp của bạn, nơi bạn muốn đệm sâu, bạn có thể sử dụng GL_DEPTH_BUFFER_BIT thay vì GL_COLOR_BUFFER_BIT)

Sau khi chuyển vào trình kết xuất dựa trên kết cấu, bạn có thể sử dụng kết cấu như bình thường; chuyển nó vào shader như một bộ đồng phục hoặc bất cứ điều gì bạn thích.


1

Không, điều đó là không thể. Nhiều nhất bạn có thể glReadPixels dữ liệu cho CPU và tạo kết cấu của nó, nhưng điều đó sẽ cồng kềnh và chậm chạp. Renderbuffers không có nghĩa cho nó, chức năng đó chỉ được cung cấp bởi kết cấu.


Cho rằng, những gì thay thế? Làm thế nào bạn có thể duy trì độ sâu trong bộ đệm vẽ của bạn và cũng có được thành phần độ sâu như một kết cấu?
Rushyo

@Rushyo: Một giải pháp thay thế có thể là loại bỏ bộ đệm stpson (nếu có thể!) Và làm cho trình kết xuất độ sâu trở thành kết cấu chiều sâu. Tại sao bạn sử dụng một stprint?
Calvin1602

Về cơ bản bất cứ khi nào tôi có được kết cấu độ sâu, các bài kiểm tra độ sâu của tôi bị phá vỡ. Nếu tôi đính kèm tệp đính kèm độ sâu vào FBO của mình, FBO sẽ không ghi bất kỳ thông tin độ sâu nào ở nơi khác - vì vậy khi tôi cố gắng truy xuất tệp đính kèm màu thì không có kiểm tra độ sâu trên đó (thông thường là nếu tôi không có tệp đính kèm độ sâu ). Tôi đã thử mọi sự kết hợp mà tôi có thể nghĩ ra, bao gồm cả phương pháp 'rườm rà và chậm chạp' đã nói ở trên. Dù tôi làm gì tôi cũng không thể có được kết xuất 'điển hình' cho cảnh của mình trong một kết cấu và chỉ chiều sâu ở một kết cấu khác.
Rushyo

@ Calvin1602 Khi tôi tìm hiểu về trình kết xuất đồ họa, tôi thấy rằng việc sử dụng tệp đính kèm độ sâu mà không có tệp đính kèm stprint tạo ra kết quả không mong muốn.
Rushyo

@Rushyo Tôi cá là bạn không thiết lập kết cấu chính xác, mã đăng sẽ cho phép chúng tôi giúp :)
Matias Valdenegro

1

Những gì bạn đang hỏi là có thể có trong OpenGL 3.2. Tôi đã nhận được FBO của mình phun ra màu khuếch tán thành một kết cấu màu, quy tắc cho kết cấu màu khác và chiều sâu đến kết cấu chiều sâu - không cần kết xuất đồ họa. Trong thực tế, trình kết xuất chỉ là một vấn đề, vì bạn không thể lấy mẫu từ chúng, do đó bạn phải sử dụng glReadPixels(...)hoặc bằng cách nào đó sao chép dữ liệu ra khỏi RBO và vào kết cấu trên CPU, thay vì chỉ duy trì mọi thứ trong bộ nhớ GPU. Vì thế...

Nếu bạn thực sự muốn, bạn có thể viết mã trong trình đổ bóng đầu tiên của mình để xuất thủ công các thứ như độ sâu, đến một tệp đính kèm kết cấu màu riêng biệt trong FBO của bạn. Điều đó sẽ được sử dụng bởi bạn trong các shader sau khi vượt qua của bạn. Để sử dụng OpenGL trong thử nghiệm độ sâu bên trong của nó, bạn cũng cần thêm RBO hoặc kết cấu được đặt làm GL_DEPTH_ATTACHMENT của FBO. Nhưng bạn có thể thiết lập một kết cấu duy nhất để phục vụ cả hai - điều này hiệu quả hơn & dễ sử dụng hơn.

Mã thiết lập kết cấu chiều sâu của tôi trông như thế này (Java, chỉ cần bỏ qua công cụ ByteBuffer ... và lưu ý tôi sử dụng "id" để chỉ các thẻ điều khiển / con trỏ số nguyên, vì khái niệm đó không thực sự phù hợp với Java):

        gBufferDepthTexture = new Texture();
        gBufferDepthTexture.id = glGenTextures();
        gBufferDepthTexture.unit = 2;
        gBufferDepthTexture.width = Display.getWidth();
        gBufferDepthTexture.height = Display.getHeight();
        gBufferDepthTexture.bytes = ByteBuffer.allocateDirect(Display.getWidth()*Display.getHeight() * 4);
        glActiveTexture(gBufferDepthTexture.unit + GL_TEXTURE0); //eg. 0 + 33984 = GL_TEXTURE0, while 31 + 33984 = GL_TEXTURE31.
        glBindTexture(GL_TEXTURE_2D, gBufferDepthTexture.id);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, gBufferDepthTexture.width, gBufferDepthTexture.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, gBufferDepthTexture.bytes);
        //...GL_UNSIGNED_INT or GL_UNSIGNED_BYTE may work better for you, instead... YMMV.

        //glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

Và sau đó:

        glBindFrameBuffer(GL_DRAW_FRAMEBUFFER, fbo.id);
        //your existing glFramebufferTexture2D(...) calls here
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gBufferDepthTexture.id, 0);

Bây giờ bạn có thể vượt qua gBufferDepthTexture(hoặc những gì có bạn) như một bộ đồng phục cho các shader mảnh thứ hai, thứ ba của bạn. Tôi nghĩ rằng chúng ta có thể giả định một cách an toàn rằng bạn có thể thực hiện chính xác điều tương tự với bộ đệm stpson.


0

Bạn sẽ có thể tạo một kết cấu (thay vì RenderBuffer) bằng định dạng GL_DEPTH_STENCIL. Tôi không chắc chắn về quy trình chính xác để sử dụng độ sâu từ kết cấu như vậy trong chương trình đổ bóng (mà tôi cho rằng bạn đang sử dụng, vì bạn đang sử dụng FBO), nhưng thông số OpenGL sẽ chỉ định kênh màu nào nhận được giá trị nào ( Tôi đoán là R, G và B đều được đặt ở độ sâu và A được đặt thành stprint).

Tôi nhắm mục tiêu OpenGL 3.2 những ngày này, vì vậy bạn có thể cần xác minh rằng định dạng kết cấu phù hợp với bạn. Tôi không bao giờ có thể nhớ phiên bản nào giới thiệu các tính năng khác nhau.


Rắc rối sau đó không bắt được thành phần GL_DEPTH_STENCIL trong một kết cấu, nhưng thực tế là tất cả thông tin chuyên sâu bị mất trong FBO bất cứ khi nào bạn làm như vậy. FBO trở nên vô dụng khi sau đó kết xuất cảnh vào bộ đệm vẽ. Do đó tôi đã sử dụng Renderbuffer với hy vọng bỏ qua vấn đề này. Tôi nghĩ bây giờ tôi không có lựa chọn nào khác ngoài việc thực hiện hai đường chuyền để lấy độ sâu + rút thông tin riêng = (đắt như địa ngục cho đến khi tôi có thể tìm cách vượt qua nó.
Rushyo

@Rushyo Tôi đã đăng một câu trả lời cho câu hỏi cổ xưa này :) Bạn có thể muốn xem, mặc dù bạn có thể đã giải quyết những năm trước.
Kỹ sư

@NickWiggill tôi ước! Làm mờ một cái gì đó và tiếp tục với cuộc sống của tôi. Thực tế không thể kiểm tra câu trả lời của bạn cho đến khi tôi tạo lại các tài sản mà tôi đã sử dụng trong nguyên mẫu này. Có thể đi xung quanh vấn đề đó vào một lúc nào đó ...
Rushyo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.