如何在JavaFX3D中创建雾?

如何在JavaFX3D中创建雾?,javafx,javafx-3d,Javafx,Javafx 3d,我正在用JavaFX3D开发一个游戏,在这个游戏中,玩家正在一条漫长的道路上奔跑。有东西和障碍向他走来。关键是:现在,如果对象进入我的剪裁距离,它们就会不知从何处出现。因此,我想创建某种雾(或任何其他“隐藏”对象初始化的东西) 问题是我找不到任何这样做的例子。我正在寻找一段示例代码/指向源代码的链接/任何其他建议。已经说过这是一个太宽泛的问题,必须有很多很多方法来实现,下面是一个可能的实现。这是2D的,但很容易适应3D应用(我想)。这个想法就是让一些浅灰色的圆圈在白色背景上漂移,然后对整个东西应

我正在用JavaFX3D开发一个游戏,在这个游戏中,玩家正在一条漫长的道路上奔跑。有东西和障碍向他走来。关键是:现在,如果对象进入我的剪裁距离,它们就会不知从何处出现。因此,我想创建某种雾(或任何其他“隐藏”对象初始化的东西)


问题是我找不到任何这样做的例子。我正在寻找一段示例代码/指向源代码的链接/任何其他建议。

已经说过这是一个太宽泛的问题,必须有很多很多方法来实现,下面是一个可能的实现。这是2D的,但很容易适应3D应用(我想)。这个想法就是让一些浅灰色的圆圈在白色背景上漂移,然后对整个东西应用一个巨大的模糊

然后,您可以让您的对象以此作为背景显示,并将其从灰色淡入到真实颜色(或类似颜色)。圆的颜色和速度,以及模糊半径,可能需要一些调整

import java.util.Random;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.effect.GaussianBlur;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class FogExample extends Application {

    private static final int WIDTH = 600 ;
    private static final int HEIGHT = 600 ;


    @Override
    public void start(Stage primaryStage) {

        Fog fog = new Fog(WIDTH, HEIGHT);

        Scene scene = new Scene(new StackPane(fog.getView()), WIDTH, HEIGHT);
        primaryStage.setScene(scene);
        primaryStage.show();
    }


    public static class Fog {
        private final int width ;
        private final int height ;
        private final Pane fog ;
        private final Random RNG = new Random();

        public Fog(int width, int height) {
            this.width = width ;
            this.height = height ;
            this.fog = new Pane();
            Rectangle rect = new Rectangle(0, 0, width, height);
            rect.setFill(Color.rgb(0xe0, 0xe0, 0xe0));
            fog.getChildren().add(rect);

            for (int i = 0; i < 50; i++) {
                fog.getChildren().add(createFogElement());
            }

            fog.setEffect(new GaussianBlur((width + height) / 2.5));

        }

        private Circle createFogElement() {
            Circle circle = new Circle(RNG.nextInt(width - 50) + 25, RNG.nextInt(height - 50) + 25, 15 + RNG.nextInt(50));
            int shade = 0xcf + RNG.nextInt(0x20);
            circle.setFill(Color.rgb(shade, shade, shade));
            AnimationTimer anim = new AnimationTimer() {

                double xVel = RNG.nextDouble()*40 - 20 ;
                double yVel = RNG.nextDouble()*40 - 20 ;

                long lastUpdate = 0 ;

                @Override
                public void handle(long now) {
                    if (lastUpdate > 0) {
                        double elapsedSeconds = (now - lastUpdate) / 1_000_000_000.0 ;
                        double x = circle.getCenterX() ;
                        double y = circle.getCenterY() ;
                        if ( x + elapsedSeconds * xVel > width || x + elapsedSeconds * xVel < 0) {
                            xVel = - xVel ; 
                        }
                        if ( y + elapsedSeconds * yVel > height || y + elapsedSeconds * yVel < 0) {
                            yVel = - yVel ; 
                        }
                        circle.setCenterX(x + elapsedSeconds*xVel);
                        circle.setCenterY(y + elapsedSeconds * yVel);
                    }
                    lastUpdate = now ;
                }

            };
            anim.start();
            return circle ;
        }

        public Node getView() {
            return fog ;
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
import java.util.Random;
导入javafx.animation.AnimationTimer;
导入javafx.application.application;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.effect.GaussianBlur;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.StackPane;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Circle;
导入javafx.scene.shape.Rectangle;
导入javafx.stage.stage;
公共类示例扩展了应用程序{
专用静态最终整数宽度=600;
专用静态最终内部高度=600;
@凌驾
公共无效开始(阶段primaryStage){
雾=新雾(宽度、高度);
场景=新场景(新堆栈窗格(fog.getView())、宽度、高度);
初级阶段。场景(场景);
primaryStage.show();
}
公共静态类雾{
私有最终整数宽度;
私人最终整数高度;
私人终审法院;
私有最终随机RNG=新随机();
公共雾(内部宽度、内部高度){
这个。宽度=宽度;
高度=高度;
this.fog=新窗格();
矩形rect=新矩形(0,0,宽度,高度);
rect.setFill(Color.rgb(0xe0,0xe0,0xe0));
fog.getChildren().add(rect);
对于(int i=0;i<50;i++){
getChildren().add(createFogElement());
}
设置效果(新高斯亮度((宽度+高度)/2.5));
}
private Circle createFogElement(){
圆圈=新圆圈(RNG.nextInt(宽度-50)+25,RNG.nextInt(高度-50)+25,15+RNG.nextInt(50));
int shade=0xcf+RNG.nextInt(0x20);
circle.setFill(Color.rgb(shade,shade,shade));
AnimationTimer anim=新的AnimationTimer(){
双xVel=RNG.nextDouble()*40-20;
双yVel=RNG.nextDouble()*40-20;
long lastUpdate=0;
@凌驾
公共无效句柄(长){
如果(上次更新>0){
双延时秒=(现在-最新更新)/1_000_000.0;
double x=圆。getCenterX();
双y=圆。getCenterY();
如果(x+elapsedSeconds*xVel>width | | x+elapsedSeconds*xVel<0){
xVel=-xVel;
}
如果(y+elapsedSeconds*yVel>height | | y+elapsedSeconds*yVel<0){
yVel=-yVel;
}
圆.setCenterX(x+elapsedSeconds*xVel);
圆。设置中心y(y+延时秒*yVel);
}
lastUpdate=now;
}
};
anim.start();
返回圈;
}
公共节点getView(){
返雾;
}
}
公共静态void main(字符串[]args){
发射(args);
}
}

典型的3D系统使用粒子系统来实现这一点,包括透明度、alpha波动和广告牌纹理的组合。信不信由你,雾、烟和火焰。。。粒子效果。。。实际上并不是3D的,而是2D图像,这些图像已经定位、大小和颜色以3D形式显示。然后,它们被快速地动画化,以至于人类观众无法分辨出2D图像的细微差别。 javafx3d的问题是它还不支持透明性(它是非正式的)。此外,没有粒子类型的对象可以让你像James_D建议的那样覆盖形状和纹理,而不需要手动管理相机的定位。 不过还是有希望的。。。F(X)yz项目提供了一个BillBoard类,允许您垂直于相机放置图像。您可以使用计时器和一些随机的.next()类型,使用James_D建议的方法快速更新此图像。BillboardBehavior Test和CameraViewTest中有一个以类似方式使用公告牌的示例。性能在CameraViewTest中演示。 如果我是你,我会做的是在你的平截头体的后Z位置(物体进入场景的位置)设置一个大的平截头体宽的广告牌对象,然后在屏幕外的窗格中设置一个计时器/随机圆生成器。然后使用CameraViewTest中的方法,快照屏幕外窗格(其中有圆圈),然后将该图像设置为公告牌。您必须让快照调用位于某个计时器上,才能实现动画效果。CameraViewTest演示了如何做到这一点。对用户的影响将是一组移动模糊的小圆圈。

便宜的雾

这个问题太宽泛了,无法提供一个明确的答案,但也许a会有所帮助。