2

当 JavaFX8 代码加载颜色、凹凸和规格贴图时,颜色和规格按预期工作,但凹凸贴图会导致奇怪的效果。这三个都是地球的墨卡托地图。通常,凹凸贴图不会添加 3d 效果。凹凸贴图只会导致喜马拉雅山和安第斯山脉在地球的明亮一侧显示为带有闪亮边框的黑色区域,而在彩色地图上显示为阴影一侧。我究竟做错了什么?

Image diffMap = null;
Image bumpMap = null;
Image specMap = null;
diffMap = new Image(MoleculeSampleApp.class.getResource("Color Map1.jpg").toExternalForm());
bumpMap = new Image(MoleculeSampleApp.class.getResource("Bump1.jpg").toExternalForm());
specMap = new Image(MoleculeSampleApp.class.getResource("Spec Mask1.png").toExternalForm());
final PhongMaterial earthMaterial = new PhongMaterial(Color.WHITE, diffMap, specMap, bumpMap, null);
earthMaterial.setDiffuseColor(Color.WHITE);
earthMaterial.setSpecularColor(Color.WHITE);

作为 3d 的新手,我的第一个想法是应该有某种将凹凸贴图的像素颜色值缩放为高程的方式,我错过了这一点。

4

1 回答 1

3

JavaFX 的凹凸贴图是法线贴图,而不是高度贴图,更多信息请参阅:法线贴图和高度贴图信息

这是您可以尝试的示例。

在此处输入图像描述

地图的图像非常大,因此在您的场景显示之前可能需要一些时间来下载它们。

我用于图像的来源是 =>无聊?然后创建一个行星(现在是死链接)。

import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.*;
import javafx.scene.shape.Sphere;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;
import javafx.util.Duration;

public class EarthViewer extends Application {

  private static final double EARTH_RADIUS  = 400;
  private static final double VIEWPORT_SIZE = 800;
  private static final double ROTATE_SECS   = 30;

  private static final double MAP_WIDTH  = 4096;
  private static final double MAP_HEIGHT = 2048;

  private static final String DIFFUSE_MAP =
      "https://imgur.com/vrNnXIs.jpeg";
  private static final String NORMAL_MAP =
      "https://imgur.com/5T2oAuk.jpeg";
  private static final String SPECULAR_MAP =
      "https://imgur.com/GV11WNV.jpeg";

  private Group buildScene() {
    Sphere earth = new Sphere(EARTH_RADIUS);
    earth.setTranslateX(VIEWPORT_SIZE / 2d);
    earth.setTranslateY(VIEWPORT_SIZE / 2d);

    PhongMaterial earthMaterial = new PhongMaterial();
    earthMaterial.setDiffuseMap(
      new Image(
        DIFFUSE_MAP,
        MAP_WIDTH,
        MAP_HEIGHT,
        true,
        true
      )
    );
    earthMaterial.setBumpMap(
      new Image(
        NORMAL_MAP,
        MAP_WIDTH,
        MAP_HEIGHT,
        true,
        true
      )
    );
    earthMaterial.setSpecularMap(
      new Image(
        SPECULAR_MAP,
        MAP_WIDTH,
        MAP_HEIGHT,
        true,
        true
      )
    );

    earth.setMaterial(
        earthMaterial
    );

    return new Group(earth);
  }

  @Override
  public void start(Stage stage) {
    Group group = buildScene();

    Scene scene = new Scene(
      new StackPane(group),
      VIEWPORT_SIZE, VIEWPORT_SIZE,
      true,
      SceneAntialiasing.BALANCED
    );

    scene.setFill(Color.rgb(10, 10, 40));

    scene.setCamera(new PerspectiveCamera());

    stage.setScene(scene);
    stage.show();

    stage.setFullScreen(true);

    rotateAroundYAxis(group).play();
  }

  private RotateTransition rotateAroundYAxis(Node node) {
    RotateTransition rotate = new RotateTransition(
      Duration.seconds(ROTATE_SECS), 
      node
    );
    rotate.setAxis(Rotate.Y_AXIS);
    rotate.setFromAngle(360);
    rotate.setToAngle(0);
    rotate.setInterpolator(Interpolator.LINEAR);
    rotate.setCycleCount(RotateTransition.INDEFINITE);

    return rotate;
  }

  public static void main(String[] args) {
    launch(args);
  }
}

普通的?为什么????

PhongMaterial bumpMapProperty的 JavaDoc 状态说明:

此 PhongMaterial 的凹凸贴图,它是存储为 RGB 图像的法线贴图。

使用法线贴图而不是高度贴图,因为

[法线贴图]更加准确,因为它们不仅可以模拟像素沿着一条线远离面部,还可以模拟以任意方式在任何方向移动的像素。

维基百科凹凸贴图文章中提供了法线贴图和高度贴图的简要说明。

示例图像

更新,2021 年 7 月

不幸的是,“无聊?然后创建一个星球”的图像源不再可用,所以我更新了链接到不同图像的答案(希望这些图像将保持在线)。因为它链接到不同的图像,所以生成的地球渲染看起来与上面的示例图像有点不同,尽管它是相似的。渲染的代码基本上没有什么不同,尽管图像发生了变化。

漫反射贴图

漫反射贴图

法线贴图

法线贴图

高光贴图

高光贴图

于 2013-10-27T22:01:33.277 回答