Skip to content

Commit

Permalink
Document the new pipelined renderer (#3094)
Browse files Browse the repository at this point in the history
This is a squash-and-rebase of @Ku95's documentation of the new renderer onto the latest `pipelined-rendering` branch.

Original PR is #2884.

Co-authored-by: dataphract <[email protected]>
Co-authored-by: Carter Anderson <[email protected]>
  • Loading branch information
3 people committed Nov 16, 2021
1 parent 14ce281 commit 1076a8f
Show file tree
Hide file tree
Showing 33 changed files with 590 additions and 70 deletions.
9 changes: 9 additions & 0 deletions crates/bevy_ecs/src/system/function_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,18 @@ impl<Param: SystemParam> SystemState<Param> {
}
}

/// A trait for defining systems with a [`SystemParam`] associated type.
///
/// This facilitates the creation of systems that are generic over some trait
/// and that use that trait's associated types as `SystemParam`s.
pub trait RunSystem: Send + Sync + 'static {
/// The `SystemParam` type passed to the system when it runs.
type Param: SystemParam;

/// Runs the system.
fn run(param: SystemParamItem<Self::Param>);

/// Creates a concrete instance of the system for the specified `World`.
fn system(world: &mut World) -> ParamSystem<Self::Param> {
ParamSystem {
run: Self::run,
Expand Down
7 changes: 6 additions & 1 deletion pipelined/bevy_gltf2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bevy_reflect::TypeUuid;
use bevy_render2::mesh::Mesh;
use bevy_scene::Scene;

/// Adds support for GLTF file loading to Apps
/// Adds support for glTF file loading to the app.
#[derive(Default)]
pub struct GltfPlugin;

Expand All @@ -24,6 +24,7 @@ impl Plugin for GltfPlugin {
}
}

/// Representation of a loaded glTF file.
#[derive(Debug, TypeUuid)]
#[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"]
pub struct Gltf {
Expand All @@ -38,6 +39,8 @@ pub struct Gltf {
pub default_scene: Option<Handle<Scene>>,
}

/// A glTF node with all of its child nodes, its [`GltfMesh`] and
/// [`Transform`](bevy_transform::prelude::Transform).
#[derive(Debug, Clone, TypeUuid)]
#[uuid = "dad74750-1fd6-460f-ac51-0a7937563865"]
pub struct GltfNode {
Expand All @@ -46,12 +49,14 @@ pub struct GltfNode {
pub transform: bevy_transform::prelude::Transform,
}

/// A glTF mesh, which may consists of multiple [`GtlfPrimitives`](GltfPrimitive).
#[derive(Debug, Clone, TypeUuid)]
#[uuid = "8ceaec9a-926a-4f29-8ee3-578a69f42315"]
pub struct GltfMesh {
pub primitives: Vec<GltfPrimitive>,
}

/// Part of a [`GltfMesh`] that consists of a [`Mesh`] and an optional [`StandardMaterial`].
#[derive(Debug, Clone, TypeUuid)]
#[uuid = "cbfca302-82fd-41cb-af77-cab6b3d50af1"]
pub struct GltfPrimitive {
Expand Down
22 changes: 18 additions & 4 deletions pipelined/bevy_gltf2/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ use wgpu::{AddressMode, FilterMode, PrimitiveTopology, SamplerDescriptor, Textur

use crate::{Gltf, GltfNode};

/// An error that occurs when loading a GLTF file
/// An error that occurs when loading a glTF file.
#[derive(Error, Debug)]
pub enum GltfError {
#[error("unsupported primitive mode")]
UnsupportedPrimitive { mode: Mode },
#[error("invalid GLTF file: {0}")]
#[error("invalid glTF file: {0}")]
Gltf(#[from] gltf::Error),
#[error("binary blob is missing")]
MissingBlob,
Expand All @@ -56,7 +56,7 @@ pub enum GltfError {
AssetIoError(#[from] AssetIoError),
}

/// Loads meshes from GLTF files into Mesh assets
/// Loads glTF files with all of their data as their corresponding bevy representations.
#[derive(Default)]
pub struct GltfLoader;

Expand All @@ -74,6 +74,7 @@ impl AssetLoader for GltfLoader {
}
}

/// Loads an entire glTF file.
async fn load_gltf<'a, 'b>(
bytes: &'a [u8],
load_context: &'a mut LoadContext<'b>,
Expand Down Expand Up @@ -265,7 +266,7 @@ async fn load_gltf<'a, 'b>(
.into_iter()
.filter_map(|res| {
if let Err(err) = res.as_ref() {
warn!("Error loading GLTF texture: {}", err);
warn!("Error loading glTF texture: {}", err);
}
res.ok()
})
Expand Down Expand Up @@ -320,6 +321,7 @@ async fn load_gltf<'a, 'b>(
Ok(())
}

/// Loads a glTF texture as a bevy [`Image`] and returns it together with its label.
async fn load_texture<'a>(
gltf_texture: gltf::Texture<'a>,
buffer_data: &[Vec<u8>],
Expand Down Expand Up @@ -368,6 +370,7 @@ async fn load_texture<'a>(
Ok((texture, texture_label(&gltf_texture)))
}

/// Loads a glTF material as a bevy [`StandardMaterial`] and returns it.
fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<StandardMaterial> {
let material_label = material_label(material);

Expand Down Expand Up @@ -444,6 +447,7 @@ fn load_material(material: &Material, load_context: &mut LoadContext) -> Handle<
)
}

/// Loads a glTF node.
fn load_node(
gltf_node: &gltf::Node,
world_builder: &mut WorldChildBuilder,
Expand Down Expand Up @@ -559,14 +563,17 @@ fn load_node(
}
}

/// Returns the label for the `mesh`.
fn mesh_label(mesh: &gltf::Mesh) -> String {
format!("Mesh{}", mesh.index())
}

/// Returns the label for the `mesh` and `primitive`.
fn primitive_label(mesh: &gltf::Mesh, primitive: &Primitive) -> String {
format!("Mesh{}/Primitive{}", mesh.index(), primitive.index())
}

/// Returns the label for the `material`.
fn material_label(material: &gltf::Material) -> String {
if let Some(index) = material.index() {
format!("Material{}", index)
Expand All @@ -575,18 +582,22 @@ fn material_label(material: &gltf::Material) -> String {
}
}

/// Returns the label for the `texture`.
fn texture_label(texture: &gltf::Texture) -> String {
format!("Texture{}", texture.index())
}

/// Returns the label for the `node`.
fn node_label(node: &gltf::Node) -> String {
format!("Node{}", node.index())
}

/// Returns the label for the `scene`.
fn scene_label(scene: &gltf::Scene) -> String {
format!("Scene{}", scene.index())
}

/// Extracts the texture sampler data from the glTF texture.
fn texture_sampler<'a>(texture: &gltf::Texture) -> SamplerDescriptor<'a> {
let gltf_sampler = texture.sampler();

Expand Down Expand Up @@ -631,6 +642,7 @@ fn texture_sampler<'a>(texture: &gltf::Texture) -> SamplerDescriptor<'a> {
}
}

/// Maps the texture address mode form glTF to wgpu.
fn texture_address_mode(gltf_address_mode: &gltf::texture::WrappingMode) -> AddressMode {
match gltf_address_mode {
WrappingMode::ClampToEdge => AddressMode::ClampToEdge,
Expand All @@ -639,6 +651,7 @@ fn texture_address_mode(gltf_address_mode: &gltf::texture::WrappingMode) -> Addr
}
}

/// Maps the primitive_topology form glTF to wgpu.
fn get_primitive_topology(mode: Mode) -> Result<PrimitiveTopology, GltfError> {
match mode {
Mode::Points => Ok(PrimitiveTopology::PointList),
Expand All @@ -658,6 +671,7 @@ fn alpha_mode(material: &Material) -> AlphaMode {
}
}

/// Loads the raw glTF buffer data for a specific glTF file.
async fn load_buffers(
gltf: &gltf::Gltf,
load_context: &LoadContext<'_>,
Expand Down
5 changes: 3 additions & 2 deletions pipelined/bevy_pbr2/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use bevy_render2::{
};
use bevy_transform::components::{GlobalTransform, Transform};

/// A component bundle for PBR entities with a [`Mesh`] and a [`StandardMaterial`].
#[derive(Bundle, Clone)]
pub struct PbrBundle {
pub mesh: Handle<Mesh>,
Expand Down Expand Up @@ -56,7 +57,7 @@ impl CubemapVisibleEntities {
}
}

/// A component bundle for "point light" entities
/// A component bundle for [`PointLight`] entities.
#[derive(Debug, Bundle, Default)]
pub struct PointLightBundle {
pub point_light: PointLight,
Expand All @@ -66,7 +67,7 @@ pub struct PointLightBundle {
pub global_transform: GlobalTransform,
}

/// A component bundle for "directional light" entities
/// A component bundle for [`DirectionalLight`] entities.
#[derive(Debug, Bundle, Default)]
pub struct DirectionalLightBundle {
pub directional_light: DirectionalLight,
Expand Down
2 changes: 2 additions & 0 deletions pipelined/bevy_pbr2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use bevy_transform::TransformSystem;

pub mod draw_3d_graph {
pub mod node {
/// Label for the shadow pass node.
pub const SHADOW_PASS: &str = "shadow_pass";
}
}
Expand All @@ -36,6 +37,7 @@ pub const PBR_SHADER_HANDLE: HandleUntyped =
pub const SHADOW_SHADER_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 1836745567947005696);

/// Sets up the entire PBR infrastructure of bevy.
#[derive(Default)]
pub struct PbrPlugin;

Expand Down
8 changes: 4 additions & 4 deletions pipelined/bevy_pbr2/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ impl Default for DirectionalLightShadowMap {
}
}

/// Ambient light.
/// An ambient light, which lights the entire scene equally.
#[derive(Debug)]
pub struct AmbientLight {
pub color: Color,
/// A direct scale factor multiplied with `color` before being passed to the shader
/// A direct scale factor multiplied with `color` before being passed to the shader.
pub brightness: f32,
}

Expand All @@ -162,9 +162,9 @@ impl Default for AmbientLight {
}
}

/// Add this component to make a `Mesh` not cast shadows
/// Add this component to make a [`Mesh`](bevy_render2::mesh::Mesh) not cast shadows.
pub struct NotShadowCaster;
/// Add this component to make a `Mesh` not receive shadows
/// Add this component to make a [`Mesh`](bevy_render2::mesh::Mesh) not receive shadows.
pub struct NotShadowReceiver;

#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
Expand Down
16 changes: 13 additions & 3 deletions pipelined/bevy_pbr2/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use crevice::std140::{AsStd140, Std140};
use wgpu::{BindGroupDescriptor, BindGroupEntry, BindingResource};

/// A material with "standard" properties used in PBR lighting
/// Standard property values with pictures here https://google.github.io/filament/Material%20Properties.pdf
/// Standard property values with pictures here
/// <https://google.github.io/filament/Material%20Properties.pdf>.
///
/// May be created directly from a [`Color`] or an [`Image`].
#[derive(Debug, Clone, TypeUuid)]
#[uuid = "7494888b-c082-457b-aacf-517228cc0c22"]
pub struct StandardMaterial {
Expand Down Expand Up @@ -56,7 +59,7 @@ impl Default for StandardMaterial {
emissive: Color::BLACK,
emissive_texture: None,
// This is the minimum the roughness is clamped to in shader code
// See https://google.github.io/filament/Filament.html#materialsystem/parameterization/
// See <https://google.github.io/filament/Filament.html#materialsystem/parameterization/>
// It's the minimum floating point value that won't be rounded down to 0 in the
// calculations used. Although technically for 32-bit floats, 0.045 could be
// used.
Expand All @@ -66,7 +69,8 @@ impl Default for StandardMaterial {
metallic: 0.01,
metallic_roughness_texture: None,
// Minimum real-world reflectance is 2%, most materials between 2-5%
// Expressed in a linear scale and equivalent to 4% reflectance see https://google.github.io/filament/Material%20Properties.pdf
// Expressed in a linear scale and equivalent to 4% reflectance see
// <https://google.github.io/filament/Material%20Properties.pdf>
reflectance: 0.5,
occlusion_texture: None,
normal_map_texture: None,
Expand Down Expand Up @@ -95,6 +99,7 @@ impl From<Handle<Image>> for StandardMaterial {
}
}

/// The GPU representation of the uniform data of a [`StandardMaterial`].
#[derive(Clone, Default, AsStd140)]
pub struct StandardMaterialUniformData {
/// Doubles as diffuse albedo for non-metallic, specular for metallic and a mix for everything
Expand All @@ -117,6 +122,7 @@ pub struct StandardMaterialUniformData {
pub alpha_cutoff: f32,
}

/// This plugin adds the [`StandardMaterial`] asset to the app.
pub struct StandardMaterialPlugin;

impl Plugin for StandardMaterialPlugin {
Expand All @@ -126,9 +132,13 @@ impl Plugin for StandardMaterialPlugin {
}
}

/// The GPU representation of a [`StandardMaterial`].
#[derive(Debug, Clone)]
pub struct GpuStandardMaterial {
/// A buffer containing the [`StandardMaterialUniformData`] of the material.
pub buffer: Buffer,
/// The bind group specifying how the [`StandardMaterialUniformData`] and
/// all the textures of the material are bound.
pub bind_group: BindGroup,
pub has_normal_map: bool,
pub flags: StandardMaterialFlags,
Expand Down
27 changes: 17 additions & 10 deletions pipelined/bevy_render2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,32 @@ use bevy_ecs::prelude::*;
use std::ops::{Deref, DerefMut};
use wgpu::Backends;

/// Contains the default Bevy rendering backend based on wgpu.
#[derive(Default)]
pub struct RenderPlugin;

/// The names of the default App stages
/// The labels of the default App rendering stages.
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
pub enum RenderStage {
/// Extract data from "app world" and insert it into "render world". This step should be kept
/// as short as possible to increase the "pipelining potential" for running the next frame
/// while rendering the current frame.
/// Extract data from the "app world" and insert it into the "render world".
/// This step should be kept as short as possible to increase the "pipelining potential" for
/// running the next frame while rendering the current frame.
Extract,

/// Prepare render resources from extracted data.
/// Prepare render resources from the extracted data for the GPU.
Prepare,

/// Create Bind Groups that depend on Prepare data and queue up draw calls to run during the Render stage.
/// Create [`BindGroups`](crate::render_resource::BindGroup) that depend on
/// [`Prepare`](RenderStage::Prepare) data and queue up draw calls to run during the
/// [`Render`](RenderStage::Render) stage.
Queue,

// TODO: This could probably be moved in favor of a system ordering abstraction in Render or Queue
/// Sort RenderPhases here
/// Sort the [`RenderPhases`](crate::render_phase::RenderPhase) here.
PhaseSort,

/// Actual rendering happens here. In most cases, only the render backend should insert resources here
/// Actual rendering happens here.
/// In most cases, only the render backend should insert resources here.
Render,

/// Cleanup render resources here.
Expand All @@ -75,16 +79,17 @@ impl DerefMut for RenderWorld {
}
}

/// Label for the rendering sub-app
/// A Label for the rendering sub-app.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, AppLabel)]
pub struct RenderApp;

/// A "scratch" world used to avoid allocating new worlds every frame when
// swapping out the Render World.
/// swapping out the [`RenderWorld`].
#[derive(Default)]
struct ScratchRenderWorld(World);

impl Plugin for RenderPlugin {
/// Initializes the renderer, sets up the [`RenderStage`](RenderStage) and creates the rendering sub-app.
fn build(&self, app: &mut App) {
let default_backend = if cfg!(not(target_arch = "wasm32")) {
Backends::PRIMARY
Expand Down Expand Up @@ -271,6 +276,8 @@ impl Plugin for RenderPlugin {
}
}

/// Executes the [`Extract`](RenderStage::Extract) stage of the renderer.
/// This updates the render world with the extracted ECS data of the current frame.
fn extract(app_world: &mut World, render_app: &mut App) {
let extract = render_app
.schedule
Expand Down
Loading

0 comments on commit 1076a8f

Please sign in to comment.