title: Lighting for JavaFX pano viewer
body: <p>I am currently trying to set up a panorama viewer in JavaFX using its 3D features. I think I got the geometry right (3D sub-scene, TriangleMesh, etc.) but I am fighting with the proper lighting. What I need is actually no lighting at all, just the geometrically correct display of the original colors of the texture image. JavaFX seems to introduce some unwanted default lighting if there is no explicit lighting specified and is driving me crazy.</p>
  
  <p>Can anybody tell me how to set up the material and the light sources and maybe other related stuff if I do not want to have any lighting at all but just the plain image (texture) colors?</p>
  
  <p>Edit:
  Here is the requested code example. When the box is rotating you clearly see the corners of the box due to the lighting. If you could switch off the lighting these corners should disappear.</p>
  
  <pre><code>import javafx.animation.Interpolator;
  import javafx.animation.RotateTransition;
  import javafx.application.Application;
  import javafx.scene.Group;
  import javafx.scene.PerspectiveCamera;
  import javafx.scene.Scene;
  import javafx.scene.SubScene;
  import javafx.scene.image.Image;
  import javafx.scene.layout.VBox;
  import javafx.scene.paint.Color;
  import javafx.scene.paint.PhongMaterial;
  import javafx.scene.shape.CullFace;
  import javafx.scene.shape.DrawMode;
  import javafx.scene.shape.MeshView;
  import javafx.scene.shape.TriangleMesh;
  import javafx.scene.transform.Rotate;
  import javafx.stage.Stage;
  import javafx.util.Duration;
  
  public class SimplePanoViewer extends Application {
  
    private static final int VIEWPORT_SIZE = 1200;
  
    private static final double MODEL_SCALE_FACTOR = VIEWPORT_SIZE/2;
  
    private static final String textureLoc = "http://www.f-lohmueller.de/pov_tut/backgrnd/im/Cubemap_2_2048x1536.jpg";
  
    private Image texture;
    private PhongMaterial texturedMaterial = new PhongMaterial();
  
    private MeshView meshView = loadMeshView();
  
    private MeshView loadMeshView() {
  
      float[] points = {
              -0.5f, -0.5f, -0.5f,
              -0.5f, +0.5f, -0.5f,
              +0.5f, +0.5f, -0.5f,
              +0.5f, -0.5f, -0.5f,
  
              -0.5f, -0.5f, +0.5f,
              -0.5f, +0.5f, +0.5f,
              +0.5f, +0.5f, +0.5f,
              +0.5f, -0.5f, +0.5f
      };
  
      float TX0 = 0f;
      float TX1 = 1f/4f;
      float TX2 = 2f/4f;
      float TX3 = 3f/4f;
      float TX4 = 1f;
  
      float TY0 = 0f;
      float TY1 = 1f/3f;
      float TY2 = 2f/3f;
      float TY3 = 1f;
  
      float[] texCoords = {
              TX0, TY1,
              TX0, TY2,
              TX1, TY2,
              TX1, TY3,
              TX2, TY3,
              TX2, TY2,
              TX3, TY2,
              TX4, TY2,
              TX4, TY1,
              TX3, TY1,
              TX2, TY1,
              TX2, TY0,
              TX1, TY0,
              TX1, TY1,
          };
      int[] faces = {
              0, 0, 1, 1, 5, 2,  5, 2, 4, 13, 0, 0,           // 0
              4, 13, 5, 2, 6, 5,  6, 5, 7, 10, 4, 13,         // 1
              7, 10, 6, 5, 2, 6,  2, 6, 3, 9, 7, 10,          // 2
              3, 9, 2, 6, 1, 7,  1, 7, 0, 8, 3, 9,            // 3
              0, 12, 4, 13, 7, 10,  7, 10, 3, 11, 0, 12,      // 4
              5, 2, 1, 3, 2, 4,  2, 4, 6, 5, 5, 2             // 5
      };
  
      TriangleMesh mesh = new TriangleMesh();
      mesh.getPoints().setAll(points);
      mesh.getTexCoords().setAll(texCoords);
      mesh.getFaces().setAll(faces);
  
      return new MeshView(mesh);
    }
  
    private Group buildScene() {
      meshView.setTranslateX(VIEWPORT_SIZE / 2);
      meshView.setTranslateY(VIEWPORT_SIZE / 2 * 9.0 / 16);
      meshView.setTranslateZ(-VIEWPORT_SIZE );
      meshView.setScaleX(MODEL_SCALE_FACTOR);
      meshView.setScaleY(MODEL_SCALE_FACTOR);
      meshView.setScaleZ(MODEL_SCALE_FACTOR);
  
      return new Group(meshView);
    }
  
    @Override
    public void start(Stage stage) {
      texture = new Image(textureLoc);
      texturedMaterial.setDiffuseMap(texture);
  
      Group group = buildScene();
  
      RotateTransition rotate = rotate3dGroup(group);
  
      meshView.setCullFace(CullFace.NONE);
      meshView.setDrawMode(DrawMode.FILL);
      rotate.play();
      meshView.setMaterial(texturedMaterial);
  
      VBox layout = new VBox(
          createScene3D(group)
      );
  
      stage.setTitle("Model Viewer");
  
      Scene scene = new Scene(layout, Color.CORNSILK);
      stage.setScene(scene);
      stage.show();
    }
  
    private SubScene createScene3D(Group group) {
      SubScene scene3d = new SubScene(group, VIEWPORT_SIZE, VIEWPORT_SIZE * 9.0/16);
      scene3d.setFill(Color.rgb(10, 10, 40));
      PerspectiveCamera camera = new PerspectiveCamera();
      scene3d.setCamera(camera);
      return scene3d;
    }
  
    private RotateTransition rotate3dGroup(Group group) {
      RotateTransition rotate = new RotateTransition(Duration.seconds(30), group);
      rotate.setAxis(Rotate.Y_AXIS);
      rotate.setFromAngle(0);
      rotate.setToAngle(360);
      rotate.setInterpolator(Interpolator.LINEAR);
      rotate.setCycleCount(RotateTransition.INDEFINITE);
  
      return rotate;
    }
  
    public static void main(String[] args) {
      launch(args);
    }
  }
  </code></pre>