i'm trying to implement a shader based 2D filtering support for JME3 (ie applying a blur effect on the entire rendered scene).
The requirements are :
be able to apply a shader based filter to the entire scene
be able to stack multiple effects
be able to enable/disable filter at runtime
make it simple enough so that you don’t need to know what’s going on in the shader
I read a lot of posts about techniques on how to achieve this since i’m pretty new to the 3D development mechanics, and finaly came to some results.
But i have some gliches which i can’t get rid of, and i don’t really know if i’m doing things the way they should.
here is the rendered effect (2 combined filters : radial blur + color overlay (light grey))
I combined what i found in exemples in JME3 source code (FBO passthrough, render to texture, BasicShadowProcessor, Picture …) to make it work.
I’ve got a SceneProcessor that creates one postViewPort by filter. It’s redirecting the main viewport render into a frame buffer which texture is the input of the filter.
The filter stacking is done by rendering each filter in a frame buffer and applying the texture to the next filter.
Only the last filter is rendered to the screen.
A filter is basicaly a full screen quad on which you apply the previously rendered scene as a texture and a material using the filter shader.
That said… i have few questions :
1- Am i doing things right??
As i said i’m a bit new to JME and maybe there is method like renderer.applyCrazyShader(ThatCrazyEffectEveryOneWants.class)… and i’m just reinventing the wheel.
2- I’ve got a strange glitch. when my spider robot thingy is at the center of the scene and filtering is enabled i’ve got a flying quad ruining the effect (see pic below)
The quad is rotating with the camera (it’s not just on the full screen quad) and if i move the spider, at some point, it just move out of the scene and disapear.
Maybe someone can have an idea on how to get rid of it?
3- This one is tricky to explain : to disable the filtering at runtime, i’m removing the processor from the viewport, and re-add it for enabling. The problem is that when i enable the filter, the fullscreen quad seems to appear before the render of the scene is done. The result is that you can see a blink of the scene as it was last time you disabled filtering.
I don’t understand how it’s appening, because the fullscreen quad is in a postviewport and should be rendered after the main viewport.
This is pretty cool. I was going to make something like this at some point, but you beat me to it
So far I think you're doing things right, if you follow in the same way that ShadowProcessor and HDRProcessor do things.
One thing I did notice, was that you attach the fullscreen quad as a post viewport, this is probably not a good idea. The post viewport is usually used for GUI and such.
The best way is to set a framebuffer on the main viewport, then process it in SceneProcessor, and output the results to the screen.
As a result, the moment you attach the SceneProcessor to a viewport of your choice, it will be processed and the effect displayed the moment it finishes handling that viewport. Look at how HDRProcsesor for example renders all the result to the screen after its done.
i made some progress whith the FilterPostProcessor, and finally came to a quite satisfying solution.
As you advised, Momoko_Fan, i used HDRRenderer as a model, so now :
i have only a single quad to render multiple filters
Filters are no more geometry, they just hold a FrameBuffer and the corresponding texture.
No more postViewPort usage
No more UFO quad glitch
I attached an exemple based on the TestSceneLoading.
here is a screenshot
If you want to try it just create a new project with JMP and copy the content of the zip file to the root folder.
To initialize the filter see those lines in simpleInitApp
if (renderer.getCaps().contains(Caps.GLSL100)) {
fpp=new FilterPostProcessor(assetManager);
//adding RadialBlurFilter
// you can ply with the values to tweek the radial blur (those are default values)
fpp.addFilter(new RadialBlurFilter(1.0f, 2.2f));
//adding ColorOverlayFilter
//you can change the color (default is white resulting in a transparent filter)
fpp.addFilter(new ColorOverlayFilter(ColorRGBA.LightGray));
}
In game press "f" to activate filtering and "g" key to deactivate.
If you want to make your own filter you just need to create a MyFilter java class that extends Filter and implement the getMaterial method.
This method should return a material using the effect shader and with all uniforms setted.
The uniform for the texture holding the render of the scene must be named "m_Texture" in your matDef/shader.
hope you'll find this usefull.
by the way you'll have to find the brightSky.dds texture in the JME3 test resource file as it's to big to be attached in a post