2D & 3D

When creating a game with both 2D and 3D elements, you may want to combine these two worlds for better visual effects or more engaging gameplay.

This can be useful for example in first-person shooters that require heads-up displays (HUDs) to display information about the player.

To achieve this fusion of 2D and 3D, you'll need to follow these steps:

1. Set up a 2D camera

First, set up your project like any other 2D setup.

#![allow(unused)]
fn main() {
commands.spawn(
    MainUi,
    Camera2dBundle {
        transform: Transform::from_xyz(0.0, 0.0, 1000.0),
        ..default()
    }
);
}

2. Create a texture

Next, create a texture with the size of your viewport that will serve as the rendering target for your 3D camera.

#![allow(unused)]
fn main() {
// Create a texture resource that our 3D camera will render to
let size = Extent3d { width: 1920, height: 1080, ..default() };

// Create the texture
let mut image = Image {
    texture_descriptor: TextureDescriptor {
        label: None,
        size,
        dimension: TextureDimension::D2,
        format: TextureFormat::Bgra8UnormSrgb,
        mip_level_count: 1,
        sample_count: 1,
        usage: TextureUsages::TEXTURE_BINDING
            | TextureUsages::COPY_DST
            | TextureUsages::RENDER_ATTACHMENT,
        view_formats: &[]
    },
    ..default()
};

// Initiate the image
image.resize(size);

// Add our texture to asset server and get a handle
let render_image = asset_server.add(image);
}

3. Set up your 3D camera

Then, spawn your 3D camera anywhere, specifying the target and any additional settings you require.

#![allow(unused)]
fn main() {
// Spawn 3D camera
commands.spawn(
    Camera3dBundle {
        camera: Camera {
            // To make this camera run before 2D camera
            order: -1,

            // The render target handle
            target: render_image.clone().into(),

            // For transparency
            clear_color: ClearColorConfig::Custom(Color::rgba(0.0, 0.0, 0.0, 0.0)),
            ..default()
        },
        ..default()
    }
);
}

4. Spawn a UI node with ImageBundle

Finally, spawn a UI node with the new image texture using the UiImage2dBundle structure.

#![allow(unused)]
fn main() {
// Spawn 3D camera view
ui.spawn((
    root.add("Camera3d"),
    UiLayout::solid().size((1920.0, 1080.0)).scaling(Scaling::Fill).pack::<Base>(),
    UiImage2dBundle::from(render_image),
    PickingPortal, // You can add this component to send picking events through the viewport.
));
}

By following these steps, you can successfully merge the 2D and 3D worlds in your game.