août
2014
La toute récente sortie du JDK8_u20 a été l’occasion de relancer quelques tests portant sur la 3D.
Précédemment, j’avais fait mes tests de bump map en utilisant une heightmap : c’est à dire une image en niveau de gris qui est sensée indiquer la « hauteur » ou l’élévation (positive ou négative) d’un point par rapport au niveau du plan (normale) de la surface et ce de manière à modifier l’éclairage.
Par exemple, l’article de Wikipedia montre comment on peut donner l’apparence d’une peau d’orange à une sphère bien lisse avec un texture granuleuse :
Seulement, voilà, cela ne fonctionne pas en JavaFX 3D. En effet l’API supporte en fait le normal mapping en tant que « bump map ». Ici ce n’est plus une simple image en niveau de gris que nous avons mais une image en RVB qui contient en fait un vecteur X, Y, Z qui indique l’orientation du point par rapport à la normale de la surface.
Extrayons la normal map depuis l’image fournie sur Wikipedia et intégrons la dans le code pour éclairer un cube.
final URL normalMapURL = getClass().getResource("NormalMap.png");
final Image normalMap = new Image(normalMapURL.toExternalForm());
final PhongMaterial material = new PhongMaterial(diffuseColor, null, null, normalMap, null);
Box box = new Box();
box.setWidth(300);
box.setHeight(300);
box.setDepth(300);
box.setMaterial(material);
box.setLayoutX(300);
box.setLayoutY(300);
//
final AmbientLight ambientLight = new AmbientLight();
ambientLight.setColor(Color.rgb(127, 127, 127));
//
final PointLight pointLight = new PointLight();
pointLight.setColor(Color.WHITE);
pointLight.setLayoutX(200);
pointLight.setLayoutY(-100);
pointLight.setTranslateZ(-1100);
pointLight.getScope().add(box);
//
final Line xAxis = new Line(0, 0, 100, 0);
xAxis.setStroke(Color.RED);
final Line yAxis = new Line(0, 0, 0, 100);
yAxis.setStroke(Color.CYAN);
final Line zAxis = new Line(0, 0, 100, 0);
zAxis.setStroke(Color.YELLOW);
zAxis.getTransforms().add(new Rotate(-90, new Point3D(0, 1, 0)));
//
final Group content = new Group();
content.getChildren().addAll(box, pointLight, /*ambientLight,*/ xAxis, yAxis, zAxis);
//
final AnchorPane root = new AnchorPane();
root.setStyle("-fx-background-color: black;");
root.getChildren().add(content);
Scene scene = new Scene(root, 600, 600);
scene.setFill(Color.BLACK);
//
final PerspectiveCamera camera = new PerspectiveCamera(false);
scene.setCamera(camera);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
//
final RotateTransition rotateTransition = new RotateTransition();
rotateTransition.setAxis(new Point3D(0, 1, 0));
rotateTransition.setDuration(Duration.seconds(30));
rotateTransition.setByAngle(360);
rotateTransition.setCycleCount(Timeline.INDEFINITE);
rotateTransition.setInterpolator(Interpolator.LINEAR);
rotateTransition.setNode(box);
rotateTransition.play();
Note : mes derniers tests de 3D remontent à la version Early Access du JDK 8 l’an dernier, il semble que dans les versions release la lumière dégagée par les AmbientLight soit devenue très forte donc je l’ai baissée ici (en utilisant la couleur grise au lieu du blanc) puis l’ai commentée pour mieux voir les faces non éclairées du cube.
Voici le résultat : l’eclairge simule le fait que nous ayons une surface en 3D sur les faces de notre cube ce qui n’est pas le cas :
Un intérêt à utiliser ce genre de technique est de pouvoir simuler des surfaces complexes à moindre coût de polygones ; par exemple dans les jeux. Pour les besoins d’un jeu de shoot, on fait un rendu HD d’une arme pleine de détails (qui servira aussi aux besoin de packaging, à des fins publicitaires ou dans les séquences CGI) puis en on extrait la normal map. Ensuite dans le jeu lui-même, on met une version LD ou MD de l’arme (avec beaucoup moins de polygones donc) sur laquelle on utilisera la normnal map , couplée à une texture affichant les détails absents, pour simuler une apparence plus complexe grâce aux changements d’éclairages.
Commentaires récents
- Back from the future… dans
- Back from the future… dans
- Static linking = does not Compute dans
- Paquetage x 2 dans
- Why you little… dans