Opacity - front and back [SOLVED]

Hi,

I have a problem with opacity - I can see through objects from their front side:







but not form the back:







What can I do so that objects are opaque no mater if the camera is facing their back of front?



These screen shoots come from a project which I did to demonstrate this behaviour - source code below:

import com.jme.app.SimpleGame;
import com.jme.light.DirectionalLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.MaterialState;
import com.jme.system.DisplaySystem;

public class TestSphere extends SimpleGame {
   final float opacityAmount = 0.3f;

   public static void main(String[] args) {
      TestSphere app = new TestSphere();
      app.setConfigShowMode(SimpleGame.ConfigShowMode.AlwaysShow);
      app.start();
   }

   protected void simpleInitGame() {
      // setup light
      LightState lightState = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
      lightState.detachAll();
      DirectionalLight light = new DirectionalLight();
      light.setDiffuse(ColorRGBA.white);
      light.setAmbient(ColorRGBA.white);
      light.setDirection(new Vector3f(0, -1, 0));
      light.setEnabled(true);
      lightState.setEnabled(true);
      lightState.attach(light);
      rootNode.setRenderState(lightState);

      // create 5 spheres
      for (int i = 0; i < 5; i++)
         rootNode.attachChild(createSphere(i));

      BlendState alphaState = DisplaySystem.getDisplaySystem().getRenderer().createBlendState();
      alphaState.setBlendEnabled(true);
      alphaState.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
      alphaState.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
      alphaState.setTestEnabled(true);
      alphaState.setTestFunction(BlendState.TestFunction.GreaterThanOrEqualTo);
      alphaState.setEnabled(true);
      rootNode.setRenderState(alphaState);

      DisplaySystem.getDisplaySystem().setVSyncEnabled(true);
   }

   private Sphere createSphere(int index) {
      ColorRGBA diffuse = ColorRGBA.randomColor();
      diffuse.a = opacityAmount;

      float darker = 0.9f;
      float lighter = 0.5f;

      ColorRGBA ambient = new ColorRGBA(diffuse.r - darker, diffuse.g - darker, diffuse.b - darker, opacityAmount);
      ambient.clamp();

      ColorRGBA specular = new ColorRGBA(diffuse.r + lighter, diffuse.g + lighter, diffuse.b + lighter, opacityAmount);
      specular.clamp();

      MaterialState materialState = DisplaySystem.getDisplaySystem().getRenderer().createMaterialState();
      materialState.setAmbient(ambient);
      materialState.setDiffuse(diffuse);
      materialState.setSpecular(specular);
      materialState.setShininess(80f);

      materialState.setEmissive(ambient);
      materialState.setEnabled(true);
      materialState.setMaterialFace(MaterialState.MaterialFace.FrontAndBack);

      Sphere sphere = new Sphere("Sphere", new Vector3f(0, 0, -100 + (50 * index)), 63, 50, 25);
      sphere.setRenderState(materialState);
      sphere.updateRenderState();
      sphere.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);

      return sphere;
   }
}

You need bounding volumes set for each of your spheres. Try adding the following to each of them.


   
sphere.setModelBound(new BoundingSphere());
sphere.updateModelBound();



I was wondering why adding bounding boxes fixes that problem.



If no BoundingBox is set, the sorting of the transparent items is done with its world translation.

(see RenderQueue.distanceToCam())

But the world translation of all your spheres is 0,0,0, because you just set different centers, but not translations.



The 2nd parameter of the Spheres Constructor is its center.

If you use setLocalTranslation() instead modifying the center, it will also work without BoundingVolumes.


        Sphere sphere = new Sphere("Sphere", new Vector3f(0, 0, 0), 63, 50, 25);
        sphere.setLocalTranslation(0, 0, -100 + (50 * index));



But anyway, as JOC said, you should always set BoundingVolumes for any objects or they might get culled accidentally etc.

Thank you for your help!