在2DFX中使用2D文本到3D场景会导致文本模糊

时间:2018-03-24 19:39:31

标签: javafx javafx-3d

我试图在3D场景中显示各种Text对象

问题在于,当我缩放到文本附近时,它看起来非常模糊。

这是我的应用

的屏幕截图

enter image description here

问题:如何改善屏幕上文字的图像质量?

我已尝试在JavaFX 2D text with background in 3D scene 中设置缓存,因为它似乎可以提高答案屏幕截图的图像质量,但在我的情况下它并没有帮助我。

以下是从我的应用程序中删除的可编译示例。它只是创建一些带位置的随机Text对象,并为您提供移动方式。请注意缩放关闭时文本显示的可能性如何。

F10 F11 可放大和缩小,鼠标拖动可移动相机。

{{1}}

1 个答案:

答案 0 :(得分:3)

您尝试做的事与被引用的question之间的主要区别在于相机移动:缓存在该问题中起作用,因为在旋转节点时,相机保持在同一位置。

但是在您的情况下,您在给定位置渲染Text节点,并且具有给定的质量,并且当您开始平移相机时,这些节点不会以不同的方式呈现(具有不同的大小或质量),因此它们变得模糊。

如果缓存不起作用,还有另一种可能性,正如其他question中所建议的那样:使用3D节点。

这具有处理3D对象的明显成本,比2D文本节点更重。

主要思想是:对于给定的文本,我们将文本写入图像,我们将使用此图像作为3D长方体的漫反射贴图。然后我们将长方体添加到子场景并转换为x,y,z坐标。

我们需要来自FXyz3D libraryin,因为内置的3D CuboidMesh会将相同的图像放入每张脸,因此无效。我们也可以使用自定义Box实现3D棱镜,但是长方体已经提供了它。

然后我们可以为长方体生成一个网络图像,并设置它以便我们有所需的

TriangleMesh

card

卡片看起来很暗,但是在环境光线下,我们可以摆脱它的黑暗背景。

让我们生成100张卡片:

private CuboidMesh generateCard(String message) {

    Text text5 = new Text(message);
    text5.setFont(Font.font("Arial", FontWeight.BLACK, FontPosture.REGULAR, 60));
    GridPane grid = new GridPane();
    grid.setAlignment(Pos.CENTER);

    CuboidMesh contentShape = new CuboidMesh(40, 8, 0.01);
    PhongMaterial shader = new PhongMaterial();

    GridPane.setHalignment(text5, HPos.CENTER);

    grid.add(text5, 3, 1);

    double w = contentShape.getWidth() * 10; // more resolution
    double h = contentShape.getHeight() * 10;
    double d = contentShape.getDepth() * 10;
    final double W = 2 * d + 2 * w;
    final double H = 2 * d + h;

    ColumnConstraints col1 = new ColumnConstraints();
    col1.setPercentWidth(d * 100 / W);
    ColumnConstraints col2 = new ColumnConstraints();
    col2.setPercentWidth(w * 100 / W);
    ColumnConstraints col3 = new ColumnConstraints();
    col3.setPercentWidth(d * 100 / W);
    ColumnConstraints col4 = new ColumnConstraints();
    col4.setPercentWidth(w * 100 / W);
    grid.getColumnConstraints().addAll(col1, col2, col3, col4);

    RowConstraints row1 = new RowConstraints();
    row1.setPercentHeight(d * 100 / H);
    RowConstraints row2 = new RowConstraints();
    row2.setPercentHeight(h * 100 / H);
    RowConstraints row3 = new RowConstraints();
    row3.setPercentHeight(d * 100 / H);
    grid.getRowConstraints().addAll(row1, row2, row3);
    grid.setPrefSize(W, H);
    grid.setBackground(new Background(new BackgroundFill(Color.WHITESMOKE, CornerRadii.EMPTY, Insets.EMPTY)));
    new Scene(grid);
    WritableImage image = grid.snapshot(null, null);
    shader.setDiffuseMap(image);
    contentShape.setMaterial(shader);
    return contentShape;
}    

最后设置subScene:

for (int i = 0; i <= 100; i++) {
    CuboidMesh card = generateCard(randomText());
    card.setTranslateX(Math.random() * width - width / 2);
    card.setTranslateY(Math.random() * height - height / 2);
    card.setTranslateZ(Math.random() * 750);
    subSceneRoot.getChildren().add(card);
}

并运行它:

100 cards

并使用相机进行缩放:

zooming

文字看起来不再模糊。如果您仍然需要更高的分辨率,则可以创建更大的快照,但这会带来内存成本。

还有一个小问题,因为卡片不透明并覆盖在它们后面(我试图尽可能地降低它们的高度)。