Selective bloom

Hi

I’m trying to create what I think is pretty much the “classic bloom” effect where bright sky areas glow, and the glow “bleeds over” into the non-sky objects. I don’t want any bloom effects to “derive” from my (non-sky) objects, but they “partake” in so far as they glow just where the sky bleeds into them.

I thought this would be quite easy to achieve but so far all my attempts have failed. I am pasting a very simple example with just a skybox and a sphere. If I set bloom mode to GlowMode.Scene then everything glows (regardless of GlowColor/GlowMap properties for the sphere’s material). If I set to GlowMode.Objects then the sky doesn’t glow, sphere glows according to its GlowColor/GlowMap (which I’ve set to Black as I don’t want it to the sphere to glow). GlowMode.SceneAndObjects obviously combines these, so still no way to have only the sky generating glow.

I accidentally came across a way to get the sphere to generate no glow and the sky to glow (which might in fact be a bug), which was to set the sphere’s queue bucket to RenderQueue.Bucket.Translucent, but this is still not right. Though this makes the sky glow and the sphere not glow, the glow from the sky does not bleed over the sphere’s edges.

These four cases can be seen by setting the int attempt = 1, 2, 3 or 4 in the pasted example.

What am I missing?

Thanks
Barney

[java]package jme3test.helloworld;

import com.jme3.app.SimpleApplication;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.BloomFilter;
import com.jme3.renderer.queue.RenderQueue;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Sphere;
import com.jme3.util.SkyFactory;
import com.jme3.util.TangentBinormalGenerator;
import jme3test.post.BloomUI;

public class HelloAgainMaterial extends SimpleApplication
{

public static void main(String[] args)
{
    HelloAgainMaterial app = new HelloAgainMaterial();
    app.start();
}
private Spatial skyBox;
private Geometry sphereGeo;

@Override
public void simpleInitApp()
{

    flyCam.setEnabled(false);
    setUpSkyBox();

    /**
     * A bumpy rock with a shiny light effect. To make bumpy objects you must create a NormalMap.
     */
    Sphere sphereMesh = new Sphere(32, 32, 2f);
    sphereGeo = new Geometry("Shiny rock", sphereMesh);
    sphereMesh.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres
    TangentBinormalGenerator.generate(sphereMesh);           // for lighting effect
    Material sphereMat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
    sphereMat.setTexture("DiffuseMap", assetManager.loadTexture("Textures/Terrain/Pond/Pond.jpg"));
    sphereMat.setTexture("NormalMap", assetManager.loadTexture("Textures/Terrain/Pond/Pond_normal.png"));
    sphereMat.setBoolean("UseMaterialColors", true);
    sphereMat.setColor("Diffuse", ColorRGBA.White);
    sphereMat.setColor("Specular", ColorRGBA.White);
    sphereMat.setFloat("Shininess", 64f); // [0,128]
    sphereGeo.setMaterial(sphereMat);
    sphereGeo.setLocalTranslation(0, 0, 0); // Move it a bit
    sphereGeo.rotate(1.6f, 0, 0);          // Rotate it a bit
    sphereGeo.setLocalScale(1.4f);
    rootNode.attachChild(sphereGeo);
    rootNode.attachChild(skyBox);

    /**
     * Must add a light to make the lit object visible!
     */
    DirectionalLight sun = new DirectionalLight();
    sun.setDirection(new Vector3f(0, 0, -2).normalizeLocal());
    sun.setColor(ColorRGBA.White);
    rootNode.addLight(sun);

    FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
    BloomFilter bloom;
    sphereMat.setColor("GlowColor", ColorRGBA.Black);

    int attempt = 4;
    switch (attempt)
    {
        case 1:
            bloom = new BloomFilter(BloomFilter.GlowMode.Scene);
            break;
        case 2:
            bloom = new BloomFilter(BloomFilter.GlowMode.Objects);
            break;
        case 3:
            bloom = new BloomFilter(BloomFilter.GlowMode.SceneAndObjects);
            break;
        case 4:
            bloom = new BloomFilter(BloomFilter.GlowMode.Scene);
            sphereGeo.setQueueBucket(RenderQueue.Bucket.Translucent);
            break;

        default:
            throw new IllegalStateException();
    }

    bloom.setDownSamplingFactor(2);
    bloom.setBlurScale(1.37f);
    bloom.setExposurePower(0.4f);
    bloom.setExposureCutOff(0.5f);
    bloom.setBloomIntensity(2f);
    new BloomUI(inputManager, bloom);

    viewPort.addProcessor(fpp);
    fpp.addFilter(bloom);
}

@Override
public void simpleUpdate(float tpf)
{
    sphereGeo.rotate(tpf / 3f, tpf, 0);
}

private void setUpSkyBox()
{
    skyBox = SkyFactory.createSky(assetManager, "Textures/Sky/Bright/BrightSky.dds", false);
}

}[/java]

I posted a very similar thread and I was told that you need to make a custom viewport that renders what you want to bloom on top of the main one. I haven’t had any luck however

GlowMode.Objects determines which pixels to bloom by looking for “glowy” materials in the scene. Since your scene has no glowy materials, nothing gets bloomed.

There doesn’t seem to be any way to make Lighting.j3md glowy. You need to either use a different material or else GlowMode.Scene.

SkyFactory uses Common/MatDefs/Misc/Sky.j3md, which lacks glow. This seems like a major flaw to me.

SkyControl’s SkyMaterial, on the other hand, allows you to configure glow for sun, moon, and clouds. So maybe you should try SkyControl.