crashinvaders / gdx-vfx

libGDX post-processing visual effects
https://crashinvaders.github.io/gdx-vfx
Apache License 2.0
191 stars 25 forks source link

3D (depth buffer enabled) support #7

Open mgsx-dev opened 5 years ago

mgsx-dev commented 5 years ago

Because PingPong buffer doesn't use depth buffer, capturing a 3D scene doesn't work.

A workaround is to render 3D scene into another FBO (with depth buffer enabled) and then render this FBO with a sprite batch during capture. This workaround adds an extra full screen rendering.

A solution could be an alternate capture method : user could provide an "input Texture" which be used as the first input texture in the process chain...

I'm not familiar with this library, maybe i missed something?

Great job with this library btw :-)

metaphore commented 5 years ago

Right, that's just because I've never tried it with any of 3D stuff. Since FrameBuffer can be configured with depth buffer only upon startup, there is no any simple way to activate it for the capture stage for the existing buffers, right? And as it seems activating depth buffer for all the frame buffers will be an overhead.

Overall, providing already captured buffer instead of doing a capture stage sounds reasonable, could be useful for some other cases. Will implement it in the next version.

Thanks!

mgsx-dev commented 5 years ago

Dynamically activate depth bufffer is possible but would be a lot of pain and not efficient.

I agree, enabling depth buffer for all VfxFBO might be overkill and you have to manage buffer clearing options which would over complexify API and implementation.

Looking forward to get my hands on the next version :-)

Thank you!

metaphore commented 4 years ago

As 49d236c introduces a way to provide an input texture as an alternative to capturing the whole scene, I think this issue might be resolved now.

I'm not quite happy about the way it looks currently (scene capturing mechanism alongside the manual texture submission). Scene capturing feels more like a standalone stage that shall be separated from VfxManager and the manager just should be supplied with an input texture at all times. But just not to overthink it and get the ball rolling, I'm gonna keep the things as-is for now and deal with it in the next release.

@mgsx-dev, I'd appreciate it if you can try this new VfxManager#setCapturedInput() method with the 3D setup you have and let me know if there are any issues. As I don't work with any 3D rendering, thus can't really tell if there's something else's missing. The 0.5.0-SNAPSHOT version should have this functionality.

mgsx-dev commented 4 years ago

@metaphore thanks for the update :+1: , i tested it and it works. Unfortunately, it doesn't solve extra rendering issue because setCapturedInput render the texture to a VfxFBO (which was exactly my previous workaround). As you mentioned, every stage input should be a Texture supplied either :

I understand it's a huge change in your implementation (and maybe API) but it would make things more clean, extendable, and above all efficient.

There are no crazy features in a 3D context regarding your lib, only the depth buffer attachment (and other attachments) differs. Note that you can also use depth buffer and such for 2D rendering, but that's not so common.

As we discussed earlier, it's not the responsibility of your lib to handle that. User code have to handle depth buffer or not, MRT or not and simply provide a texture as input.

Capture feature still useful for classic use cases though.

If you have further questions, we could discuss about it on discord if you want :-)

Thanks for your work :heart:

dbchan commented 4 years ago

So is it suppose to work with 3D? I followed the example and got the "Current bound OpenGL FBO's handle doesn't match to wrapped one. It seems like begin/end order was violated" error. I use 3D and depth shader to create shadows.

mgsx-dev commented 4 years ago

@dbchan if you're using capture begin/end, you need to use the same workaround i used (see my first comment in this issue): first render your scene in your own FBO and then capture the content of that FBO.

If you're using 0.5.0-SNAPSHOT, you can use setCapturedInput(Texture) instead.

dbchan commented 4 years ago

Sorry, do you mind sharing a sample? And do I actually better off implementing my own shader then using this library from an efficiency perspective?

mgsx-dev commented 4 years ago

1- render your 3D scene into your own FBO (which has a depth buffer) 2- render your own FBO color texture with a SpriteBatch while capturing with gdx-vfx (see code below)

assuming fbo variable is your own FBO containing your 3D scene, you can capture it like this:

vfxManager.beginCapture();
spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, 1, 1);
spriteBatch.begin();
spriteBatch.draw(fbo.getColorBufferTexture(), 0, 0, 1, 1, 0, 0, 1, 1);
spriteBatch.end();
vfxManager.endCapture();

@dbchan if you need more help, please ask on discord.

dzikoysk commented 4 years ago

@metaphore do you think there is a chance to support 3D out of the box by gdx-vfx? We've been discussing about it on Discord and there are people interested in it, but because of the re-rendering process it's kinda uncertain in the prospect of performance.

metaphore commented 4 years ago

I'm not quite sure, to be honest. While preparing 0.5.0 for the release, I was thinking that packing the capture functionality into the VfxManager was a bad idea. The whole reason behind writing the custom FBO was to enable simple nested usage within the game code and make some adjustments for the ping-pong related reasons. What eventually turned out to be a very weird mix, where is nothing works quite perfectly. I'm thinking to move away from the custom FBO, or at least optimize it for the VFX chain ping-pong only and strip the capturing functionality (maybe move it to a dedicated utility class that uses a regular FrameBuffer).