Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在JavaFX中将2D文本用于3D场景会导致文本模糊_Javafx_Javafx 3d - Fatal编程技术网

在JavaFX中将2D文本用于3D场景会导致文本模糊

在JavaFX中将2D文本用于3D场景会导致文本模糊,javafx,javafx-3d,Javafx,Javafx 3d,我试图在3D场景中显示各种文本对象 问题是,当我放大文本时,它看起来非常模糊 这是我的应用程序的截图 问题:如何提高屏幕上文本的图形质量 我曾尝试将缓存设置为中,因为它似乎可以提高答案屏幕截图上的图形质量,但对我的情况没有帮助 下面是一个可编译的示例,从我的应用程序中剥离出来。它只是创建一些随机的文本对象和位置,并为您提供了一种移动的方式。请注意,当您缩小时,文本显示得非常糟糕 您可以F10和F11进行放大和缩小,并拖动鼠标来移动相机 package timelinefx; import s

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

问题是,当我放大文本时,它看起来非常模糊

这是我的应用程序的截图

问题:如何提高屏幕上文本的图形质量

我曾尝试将缓存设置为中,因为它似乎可以提高答案屏幕截图上的图形质量,但对我的情况没有帮助

下面是一个可编译的示例,从我的应用程序中剥离出来。它只是创建一些随机的文本对象和位置,并为您提供了一种移动的方式。请注意,当您缩小时,文本显示得非常糟糕

您可以F10F11进行放大和缩小,并拖动鼠标来移动相机

package timelinefx;

import static javafx.application.Application.launch;
import java.util.Random;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.transform.Translate;
import javafx.stage.Stage;
import javafx.scene.CacheHint;


public class TextInto3DScene extends Application {
    static Stage stage;
    static Scene scene;
    static Group root;
    static Group subSceneRoot;
    static PerspectiveCamera camera;
    static SubScene subScene;
    static boolean cached = true;
    static int width = 1000;
    static int height = width;

    @Override
    public void start(Stage primaryStage) throws Exception {
        createWindow();
    }

    protected static void createWindow(){
        stage = new Stage();
        root = new Group();
            root.setCache(cached);
            root.setCacheHint(CacheHint.QUALITY); //doesn't work
        scene = new Scene(root, 1500, 700, true, SceneAntialiasing.BALANCED);
        //Initialize the camera
        camera = new PerspectiveCamera(true);
        camera.setNearClip(0.1);
        camera.setFarClip(5000);
        camera.setTranslateZ(-200);

        //creates the SubScene and add the camera to it!
        subSceneRoot = new Group();
            subSceneRoot.setCache(cached); //doesn't work

        subScene = new SubScene(subSceneRoot, 1800, 700, true, SceneAntialiasing.BALANCED);
            subScene.setCache(cached);
            root.getChildren().add(subScene); 
        subScene.setFill(Color.WHITE);
        subScene.setCamera(camera);

        //Create random texts
        for( int i = 0;i<=100;++i){
            Text text = new Text(Math.random()* width-width/2, Math.random()*height-height/2, randomText() );
            text.setFill(  Color.BLACK  );
            text.setTranslateZ( Math.random()*750 );
            text.setCache(cached); //doesn't work
            text.setCacheHint(CacheHint.QUALITY);
            subSceneRoot.getChildren().add(text);
        }
        stage.setScene(scene);
        setEventHandlers();
        stage.show();
    }

    static void setEventHandlers() {
        scene.setOnMouseDragged((event) -> {

            //camera.setRotate(event.getX());
            double translateX = (event.getSceneX() - 0) / stage.getWidth();
            translateX = translateX * width - width/2;
            double translateY = (event.getSceneY() - 0) / stage.getHeight();
            translateY = translateY * height - height/2;
            double tz;
            if(!camera.getTransforms().isEmpty()){
                tz = camera.getTransforms().get(0).getTz();
            } else {
                tz = camera.getTranslateZ();
            }
            camera.getTransforms().clear();
            camera.getTransforms().addAll(  new Translate(translateX, translateY, tz)     );
        });

        //KEY PRESSED
        scene.setOnKeyPressed((event) -> {
            switch (event.getCode().toString()) {
                case "F10":
                    double amt = event.isControlDown() ? 100 : 30;
                    camera.setTranslateZ(camera.getTranslateZ() + amt);
                    break;
                case "F11":
                    amt = event.isControlDown() ? -100 : -30;
                    camera.setTranslateZ(camera.getTranslateZ() + amt);
                    break;
            }
        });
    }

    static String randomText(){
        String out = "";
        Random r = new Random();
        for(int i = 0;i<=10;++i){
            char c = (char) (r.nextInt(26) + 'a');
            out += c;
        }
        return out;
    }

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

}
package timelinefx;
导入静态javafx.application.application.launch;
导入java.util.Random;
导入javafx.application.application;
导入javafx.scene.Group;
导入javafx.scene.PerspectiveCamera;
导入javafx.scene.scene;
导入javafx.scene.sceneatialiasing;
导入javafx.scene.SubScene;
导入javafx.scene.paint.Color;
导入javafx.scene.text.text;
导入javafx.scene.transform.Translate;
导入javafx.stage.stage;
导入javafx.scene.CacheHint;
公共类textinoto3dsecene扩展应用程序{
静态阶段;
静态场景;
静态群根;
静态群次塞诺;
静态透视照相机;
静态亚新统;
静态布尔缓存=真;
静态整数宽度=1000;
静态整数高度=宽度;
@凌驾
public void start(Stage primaryStage)引发异常{
createWindow();
}
受保护的静态void createWindow(){
阶段=新阶段();
root=新组();
setCache(缓存);
root.setCacheHint(CacheHint.QUALITY);//不起作用
场景=新场景(root,1500700,true,sceneatialiasing.BALANCED);
//初始化相机
摄像头=新透视摄像头(正确);
摄像头。setNearClip(0.1);
相机。setFarClip(5000);
照相机.setTranslateZ(-200);
//创建子场景并将摄影机添加到其中!
subSceneRoot=新组();
subSceneRoot.setCache(缓存);//不工作
亚新世=新亚新世(亚新世,1800,700,真实,场景化。平衡);
subScene.setCache(缓存);
root.getChildren().add(子场景);
亚新世。刚毛填充(颜色。白色);
亚场景设置摄像机(摄像机);
//创建随机文本

对于(int i=0;i而言,您尝试执行的操作与引用的操作之间的主要区别在于摄影机移动:缓存在该问题中起作用,因为在旋转节点时,摄影机保持在相同的位置

但在本例中,您在给定的位置以给定的质量渲染文本节点,当您开始平移摄影机时,这些节点的渲染方式不同(大小或质量不同),因此它们变得模糊

如果缓存不起作用,那么还有另一种可能性,正如本文中所建议的:使用3D节点

这显然需要处理3D对象,比2D文本节点更重

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

我们需要FXyz3D中的
长方体网格
,因为内置的3D
将相同的图像放置到每个面中,所以这不起作用。我们也可以使用自定义的
三角形网格
实现3D棱镜,但长方体已经提供了这一功能

然后,我们可以生成长方体的净图像,并将其设置为获得所需的卡:

这张卡片看起来很暗,但是有了环境光,我们可以去掉它的暗背景

让我们生成100张卡片:

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);
}
然后运行它:

并使用相机进行缩放:

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


还有一个小问题,因为卡片不透明,并且覆盖了后面的卡片(我已经尽量降低了它们的高度).

非常感谢您解决了这个问题,并提供了一个示例!出于好奇,为什么不使用ImageView而不是长方体?我刚刚做了一些测试,它工作了。我还做了一个小例程,检查图像上的白色像素(对于ex,R、G和B>=0.8)我没有尝试ImageView,但是很明显,如果你要创建一个快照并显示一个高分辨率的图像,它应该可以工作(并且允许透明,正如你提到的)。每当我必须使用3D时,我宁愿只使用3D节点,正如您所经历的那样,2D和3D并没有很好的混合。
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);
}
subScene.setFill(Color.WHITESMOKE);
subSceneRoot.getChildren().add(new AmbientLight(Color.WHITE));