Problem using GLSL shader together with ShadowedRenderPass

Hi, I’m trying to enable shadows together with usage of shaders and have ran into a strange problem. I’m combining the code from jmetest.renderer.TestShadowPass with jmetest.effects.TestDiffNormSpecmap.java (http://jmonkeyengine.googlecode.com/svn/trunk/src/jmetest/effects/TestDiffNormSpecmap.java).



Everything is diplayed correctly until I press F4 to view the statistics. After that the ball which uses shaders is “masked” with black and I’ve no idea why? It looks like the ball is casting shadow on itself, which is a bit strange. It seems that specular reflection is still visible on it, but otherwise it’s all black. I’ve made lots of attempts to get it working, but wasn’t successfull :’( Any help would be appreciated.



Statistics off - ball with applied shader is displayed correctly





Statistcs on - ball is masked with black, only specular reflection is visible





Here’s the code:



package TestDiffNormSpecmap;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.FloatBuffer;
import java.util.logging.Logger;

import jmetest.renderer.loader.TestNormalmap;

import com.jme.app.SimplePassGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.input.FirstPersonHandler;
import com.jme.light.PointLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.RenderPass;
import com.jme.renderer.pass.ShadowedRenderPass;
import com.jme.scene.Node;
import com.jme.scene.TriMesh;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.CullState;
import com.jme.scene.state.GLSLShaderObjectsState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jme.util.geom.TangentBinormalGenerator;


public class TestDiffNormSpecmap extends SimplePassGame{
    private static final Logger logger = Logger.getLogger(TestNormalmap.class.getName());

    private GLSLShaderObjectsState so;
    private String currentShaderStr = "./models/shader/normalmap";
    private Sphere lightSphere1, lightSphere2, lightSphere3;
    private PointLight pl1, pl2, pl3;  
    private Node m_character;
    private ShadowedRenderPass sPass = new ShadowedRenderPass();
    private static boolean debug = true;

    public static void main(String[] args) {
        TestDiffNormSpecmap app = new TestDiffNormSpecmap();

        app.setConfigShowMode(ConfigShowMode.AlwaysShow);
        app.start();
    }

 
    TestDiffNormSpecmap() {
        stencilBits = 4; // we need a minimum stencil buffer at least.
    }

    protected void simpleUpdate() {

    }

    protected void simpleInitGame() {

        cam.setAxes(new Vector3f(-1, 0, 0), new Vector3f(0, 0, 1), new Vector3f(0, 1, 0));
        cam.setLocation(new Vector3f(0, -200, 0));

        //lights
        pl1 = new PointLight();
        pl1.setAmbient(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));
        pl1.setDiffuse(new ColorRGBA(.25f, .25f, .25f, 1.0f));//.25f, .25f, .25f, .25f
        pl1.setSpecular(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        pl1.setLocation(new Vector3f(30,-200,30));
        pl1.setEnabled(true);
        pl1.setShadowCaster(true);

        pl2 = new PointLight();
        pl2.setAmbient(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));
        pl2.setDiffuse(new ColorRGBA(.25f, .25f, .25f, 1.0f));//.25f, .25f, .25f, .25f
        pl2.setSpecular(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        pl2.setLocation(new Vector3f(-30,-200,0));
        pl2.setEnabled(true);
        pl2.setShadowCaster(true);

        pl3 = new PointLight();
        pl3.setAmbient(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));//0.2f, 0.2f, 0.2f, 1.0f
        pl3.setDiffuse(new ColorRGBA(.25f, .25f, .25f, 1.0f));//.25f, .25f, .25f, .25f
        pl3.setSpecular(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        pl3.setLocation(new Vector3f(30,-200,-30));
        pl3.setEnabled(true);


        lightState.detachAll();
        lightState.setGlobalAmbient(new ColorRGBA(0.2f, 0.2f, 0.2f, 1f));
        lightState.setTwoSidedLighting(false);
        lightState.setSeparateSpecular(true);
        lightState.attach(pl1);
        lightState.attach(pl2);
        lightState.attach(pl3);

        TextureState ts = display.getRenderer().createTextureState();

        // Base texture
        Texture baseMap = TextureManager.loadTexture(TestNormalmap.class.getClassLoader().getResource(
                "jmetest/data/images/Fieldstone.jpg"), Texture.MinificationFilter.Trilinear,
                Texture.MagnificationFilter.Bilinear);
        ts.setTexture(baseMap, 0);

        // Normal map
        Texture normalMap = TextureManager.loadTexture(TestNormalmap.class.getClassLoader().getResource(
                "jmetest/data/images/FieldstoneNormal.jpg"), Texture.MinificationFilter.Trilinear,
                Texture.MagnificationFilter.Bilinear, Image.Format.GuessNoCompression, 0.0f, true);
        ts.setTexture(normalMap, 1);

        // Specular map
        Texture specMap = TextureManager.loadTexture(TestNormalmap.class.getClassLoader().getResource(
                "jmetest/data/images/FieldstoneSpec.jpg"), Texture.MinificationFilter.Trilinear,
                Texture.MagnificationFilter.Bilinear);
        ts.setTexture(specMap, 2);

        Sphere model = new Sphere("sphere", new Vector3f(0, 0, 0), 50, 50, 20.0f, false);
        model.setModelBound(new BoundingSphere());
        model.updateModelBound();

        createShader(lightState.getQuantity(), model);

        MaterialState ms = display.getRenderer().createMaterialState();
        //ms.setColorMaterial(MaterialState.ColorMaterial.AmbientAndDiffuse);
        ms.setAmbient(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));//1.0f, 1.0f, 1.0f, 1.0f
        ms.setDiffuse(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));
        ms.setSpecular(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        ms.setShininess(50.0f);

        m_character = new Node("char node");
        m_character.attachChild(model);
        m_character.updateWorldBound();
        rootNode.attachChild(m_character);


        // Set all states on model
        m_character.setRenderState(ts);
        m_character.setRenderState(so);
        m_character.setRenderState(ms);
        m_character.setRenderState(lightState);
        m_character.updateGeometricState(0.0f, true);
        m_character.updateRenderState();


        //floor
        Box floor = new Box("floor", new Vector3f(0.0f,100.0f,0.0f),150, 10, 150);

        floor.setModelBound(new BoundingBox());
        floor.updateModelBound();
        //floor.setVBOInfo(new VBOInfo(true));//


raises exception: org.lwjgl.opengl.OpenGLException: Cannot use Buffers when Array Buffer Object is enabled
        
        rootNode.attachChild(floor);

        MaterialState ms2 = display.getRenderer().createMaterialState();
        ms2.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
        ms2.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        ms2.setSpecular(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        ms2.setShininess(50.0f);

        floor.setRenderState(ms2);

        CullState cs = display.getRenderer().createCullState();
        cs.setCullFace(CullState.Face.Back);
        cs.setEnabled(true);
        rootNode.setRenderState(cs);

        rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);

        rootNode.updateGeometricState(0, true);
        rootNode.updateRenderState();

        //shadows
        sPass.add(rootNode);
        sPass.addOccluder(m_character);
        sPass.setRenderShadows(true);
        sPass.setLightingMethod(ShadowedRenderPass.LightingMethod.Additive);
        pManager.add(sPass);

 
        RenderPass rPass = new RenderPass();
        rPass.add(statNode);
        pManager.add(rPass);

        input = new FirstPersonHandler(cam, 80, 1);
    }

    /**
     * Loads shader from URL
     *
     * @param url
     * @return String with shader
     */
    private String load(URL url) {
        BufferedReader r = null;
        try {
            r = new BufferedReader(new InputStreamReader(url.openStream()));
            StringBuffer buf = new StringBuffer();
            while (r.ready()) {
                buf.append(r.readLine()).append('n');
            }
            r.close();
            return buf.toString();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private void createShader(int numLights, TriMesh geometry) {
        so = DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState();
        String vert = load(TestDiffNormSpecmap.class.getClassLoader().getResource(currentShaderStr + ".vert"));
        String frag = load(TestDiffNormSpecmap.class.getClassLoader().getResource(currentShaderStr + ".frag"));
        vert = vert.replace("$NL$", "" + numLights);
        frag = frag.replace("$NL$", "" + numLights);
        TangentBinormalGenerator.generate(geometry);
        so.load(vert, frag);
        so.setUniform("baseMap", 0);
        so.setUniform("normalMap", 1);
        so.setUniform("specularMap", 2);
        FloatBuffer tangent = geometry.getTangentBuffer();
        // the binormal is computed in the shader from tangent and normal
        so.setAttributePointer("modelTangent", 3, false, 0, tangent);
    }
}



And here are links to the shaders I'm using
http://jmonkeyengine.googlecode.com/svn/trunk/src/jmetest/data/shaders/normalmap.frag
http://jmonkeyengine.googlecode.com/svn/trunk/src/jmetest/data/shaders/normalmap.vert

Could you please explain to me how to get rid of that black masking of the ball? Thank you for any replies