Multi sampling issues

Alpha to coverage and filters does not work well. It’s very weird.



This is an example with bloom, and it’s the same with fog and other stuff. When I run the bloom filter this happens:


  • It works perfectly with MS disabled.
  • It works perfectly with MS enabled (as far as I could tell, only tested to 4x).
  • With atoc enabled it causes weird artifacts.



    http://www.jamtlandoutdoors.se/images/dist/bloom_smear.png



    The bloom areas looks fine as long as the camera has not moved, but when I move the camera the colors are smeared out. In the image I’m moving the camera down and to the right, slowly. Every bloomed object acts sort of like a particle emitter while in view.





    I would be very grateful if someone with an NVIDIA card (and also someone with a new Radeon card) could try this test case. It looks like the frame buffers aren’t cleared properly. Just run the test, drag the camera around the sky for some time then go back to the teapot. If it fails there will be a bunch of garbage on the screen.







    package jme3test.post;



    import com.jme3.app.SimpleApplication;

    import com.jme3.input.KeyInput;

    import com.jme3.input.controls.ActionListener;

    import com.jme3.input.controls.KeyTrigger;

    import com.jme3.light.DirectionalLight;

    import com.jme3.material.Material;

    import com.jme3.math.ColorRGBA;

    import com.jme3.math.Quaternion;

    import com.jme3.math.Vector3f;

    import com.jme3.post.FilterPostProcessor;

    import com.jme3.post.filters.BloomFilter;

    import com.jme3.renderer.queue.RenderQueue.ShadowMode;

    import com.jme3.scene.Geometry;

    import com.jme3.scene.Spatial;

    import com.jme3.scene.debug.WireFrustum;

    import com.jme3.scene.shape.Box;

    import com.jme3.util.SkyFactory;



    import org.lwjgl.opengl.ARBMultisample;

    import static org.lwjgl.opengl.GL11.*;



    public class TestBloom extends SimpleApplication {



    float angle;

    Spatial lightMdl;

    Spatial teapot;

    Geometry frustumMdl;

    WireFrustum frustum;

    boolean active=true;

    FilterPostProcessor fpp;



    public static void main(String[] args){

    TestBloom app = new TestBloom();

    app.start();

    }



    @Override

    public void simpleInitApp() {



    glEnable(ARBMultisample.GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);



    // put the camera in a bad position

    cam.setLocation(new Vector3f(-2.336393f, 11.91392f, -7.139601f));

    cam.setRotation(new Quaternion(0.23602544f, 0.11321983f, -0.027698677f, 0.96473104f));

    //cam.setFrustumFar(1000);



    Material mat = new Material(assetManager,“Common/MatDefs/Light/Lighting.j3md”);

    mat.setFloat(“Shininess”, 15f);

    mat.setBoolean(“UseMaterialColors”, true);

    mat.setColor(“Ambient”, ColorRGBA.Yellow.mult(0.2f));

    mat.setColor(“Diffuse”, ColorRGBA.Yellow.mult(0.2f));

    mat.setColor(“Specular”, ColorRGBA.Yellow.mult(0.8f));



    Material matSoil = new Material(assetManager,“Common/MatDefs/Light/Lighting.j3md”);

    matSoil.setFloat(“Shininess”, 15f);

    matSoil.setBoolean(“UseMaterialColors”, true);

    matSoil.setColor(“Ambient”, ColorRGBA.Gray);

    matSoil.setColor(“Diffuse”, ColorRGBA.Black);

    matSoil.setColor(“Specular”, ColorRGBA.Gray);



    teapot = assetManager.loadModel(“Models/Teapot/Teapot.obj”);

    teapot.setLocalTranslation(0,0,10);



    teapot.setMaterial(mat);

    teapot.setShadowMode(ShadowMode.CastAndReceive);

    teapot.setLocalScale(10.0f);

    rootNode.attachChild(teapot);



    Geometry soil=new Geometry(“soil”, new Box(new Vector3f(0, -13, 550), 800, 10, 700));

    soil.setMaterial(matSoil);

    soil.setShadowMode(ShadowMode.CastAndReceive);

    rootNode.attachChild(soil);



    DirectionalLight light=new DirectionalLight();

    light.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());

    light.setColor(ColorRGBA.White.mult(1.5f));

    rootNode.addLight(light);



    // load sky

    Spatial sky = SkyFactory.createSky(assetManager, “Textures/Sky/Bright/FullskiesBlueClear03.dds”, false);

    sky.setCullHint(Spatial.CullHint.Never);

    rootNode.attachChild(sky);



    fpp=new FilterPostProcessor(assetManager);

    // fpp.setNumSamples(4);

    BloomFilter bloom=new BloomFilter();

    bloom.setDownSamplingFactor(2);

    bloom.setBlurScale(1.37f);

    bloom.setExposurePower(3.30f);

    bloom.setExposureCutOff(0.2f);

    bloom.setBloomIntensity(2.45f);

    BloomUI ui=new BloomUI(inputManager, bloom);





    viewPort.addProcessor(fpp);

    fpp.addFilter(bloom);

    fpp.setNumSamples(4);

    initInputs();

    }



    private void initInputs() {

    inputManager.addMapping(“toggle”, new KeyTrigger(KeyInput.KEY_SPACE));



    ActionListener acl = new ActionListener() {



    public void onAction(String name, boolean keyPressed, float tpf) {

    if (name.equals(“toggle”) && keyPressed) {

    if(active){

    active=false;

    viewPort.removeProcessor(fpp);

    }else{

    active=true;

    viewPort.addProcessor(fpp);

    }

    }

    }

    };



    inputManager.addListener(acl, “toggle”);



    }







    }

3 Likes

+1, filters seem to have very different results depending on amount of sampling.

@perfecticus said:
+1, filters seem to have very different results depending on amount of sampling.


Yeah, super weird stuff. In this case it's alpha to coverage causing problems tho. I know atoc is implemented differently by different vendors, and I wanna know if this is a hardware issue before proceeding (or maybe just a major screw-up by me, somehow).

Nightly build? Working perfect with the release channel.

Yes newest nightly, but I’ve had problems for quite some time with this.



It would be nice if I am told the number of samples y’all use, and maybe you could paste in the caps as well. Forgot to say this but a “non-fail” does not necessarily mean it works, because I’m pretty sure the glEnable call is just ignored if atoc isn’t supported by the card.

Actually, I know what’s going on



MS is not resolved correctly by filters. Only the waterFilter resolve it as it should.

Btw if you put the water filter before the bloom filter it works.



To resolve MS what I do on most filters is averaging the samples then applying the effect.

The correct way of doing it is to apply the effect on each sample and then average resulting the samples.

The huge drawback is that you are basically executing the shader as many times as you have samples, so it kills the performance.



For water it was making bad artifacts so it’s been done the correct way, but that’s slow as hell.



Maybe I could make a ResolveMSFilter that would only resolve it the correct way, then the other filters could stack over it without caring of multisampling…



That’s one of the reason why FXAA exists. MSAA does not play well with deferred rendering or post processing.

2 Likes

Ah, thanks for the info. This means no hardware crap then.

@nehon



A resolve MS filter would be awesome, actually. I realize there will still be plenty of work on top of that for atoc to work well, but it would be a great foundation because it’d make debugging a lot easier. Basically an “empty” filter that resolves MSAA and nothing else. It would be a great starting point for MS+atoc enabled filters as well (DoF and other effects has to be tailor made when using MS afaik, which is probably why it doesn’t work at all but the others “kind of work”).



Gonna get to work myself right away. This seems like a big issue (judging from the numerous atoc fail posts out there), so I have to get to the bottom of it. Maybe I can make an observation or two that could be useful.



Weird that it seems to work with MS without atoc enabled tho. Gonna have to check some more.

Also there is a renderManager.getRenderer().enableAlphaToCoverage() method to avoid direct ogl calls.

But i realized this morning it was bugged too, because it checks for a caps that does not exists.



I’m not completely sure a resolve MS filter would be correct though i have to test it.

I’ll keep you informed

For a starter i fixed the way to enable alpha to coverage

use

[java]

renderManager.getRenderer().setAlphaToCoverage(true);

[/java]

It’s bets to use this instead of calling ogl function directly, because it checks the hardware capabilities.

ok it should be fixed in last SVN could you check?

Actually there was a bug where the color was not cleared, that was producing those color bleeding.

@nehon

I’ll wait for the nightly and update through the platform. I don’t update through the repo.



The post water fix works in the latest nightly btw. I can confirm (that waterfilter root node stuff).

This seems to have fixed the problems. I have to test some more, but the “smudging” appears to be gone.