Ability to change image format for FilterPostProcessor

Hello!

Prehistory: BloomFilter artifacts

FilterPostProcessor uses GL_R11F_G11F_B10F image format by default. If packed floats are not supported, then fallback format is GL_RGB8UI. Both formats don’t work well in some situations:

  1. GL_R11F_G11F_B10F fails to work correctly on AMD HD 4570, which supports OpenGL 3.3 and packed floats. No matter what filter is added to FilterPostProcessor, all transparent objects show incorrect colors. Either AMD lies about packed float support or GL_R11F_G11F_B10F is not a valid format for post processing, even if packed floats are supported.

  2. GL_RGB8UI shows correct colors for transparent objects, but there is a color banding problem, because floats are converted to unsigned, normalized, 8-bit integers, and, precission is lost. For example, if gamma 2.2 is used for the application (not always through GammaCorrectionFilter), then application will show colors 0, 8, 13, 18, etc (integer 0 - 255), and colors 1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 14, etc. will never be shown, and there will be a visible gradient in dark colors.

If to use GL_RGB16F or GL_RGB32F for framebuffer image format, then no artifacts are shown for transparent objects. Color banding is absent as well.

I understand, that GL_R11F_G11F_B10F is chosen, because it uses only 32 bits per color. Half-float GL_RGB16F will use 48 bits. I would tolerate increased size, if it will show good picture without artifacts. I would like to set up image format manually. Unfortunately FilterPostProcessor is designed to be not extendable. All fields are private. I propose to add a simple setter and additional check in the initialize method for compatibility:

--- jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java	(revision 201010b6f0bf8d65bdf04fdbcd2d178db9cf95e6)
+++ jme3-core/src/main/java/com/jme3/post/FilterPostProcessor.java	(revision )
@@ -141,7 +141,7 @@
         fsQuad.setWidth(1);
         fsQuad.setHeight(1);
         
-        if (!renderer.getCaps().contains(Caps.PackedFloatTexture)) {
+        if (fbFormat == Format.RGB111110F && !renderer.getCaps().contains(Caps.PackedFloatTexture)) {
             fbFormat = Format.RGB8;
         }
         
@@ -518,6 +518,10 @@
      */
     public void setAssetManager(AssetManager assetManager) {
         this.assetManager = assetManager;
+    }
+
+    public void setFrameBufferFormat(Format fbFormat) {
+        this.fbFormat = fbFormat;
     }
 
     public void write(JmeExporter ex) throws IOException {

Please, let me know your thoughts, and if such update is ok, I will create a PR.

Thank you!

1 Like

yes please make a PR. I wanted to do this, but a PR would be perfect
Note that RGB32f is huge for back buffer. The issue is not really the storage in memory, but more the GPU bandwidth you will use for big resolutions.

1 Like

PR for master (3.2) and PR for v3.1.

I agree, that RGB32f is huge. RGB16f works fine in my tests, and 1.5x size in comparison with packed floats, is bearable for me.

Thank you!

2 Likes

thanks :wink: