aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Silas Bartha <[email protected]>2024-07-24 11:46:40 -0400
committerLibravatar Silas Bartha <[email protected]>2024-07-24 11:47:21 -0400
commitd7e1903369330c5438892c5ddfdbc7c1ef179633 (patch)
tree1913fc25e8d35e8743ea432ec80390f0f23538b2
parent52005369648e06cb2e1b36bb5dd7c19445aa4ee4 (diff)
Renamed + Updated to Bevy 0.14 + Added 0BSD Option
-rw-r--r--Cargo.toml8
-rw-r--r--LICENSE-0BSD5
-rw-r--r--README.md42
-rw-r--r--src/components.rs20
-rw-r--r--src/lib.rs33
-rw-r--r--src/nodes.rs16
-rw-r--r--src/render_assets.rs35
-rw-r--r--src/systems.rs14
8 files changed, 94 insertions, 79 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 240cea2..1005586 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,11 +1,13 @@
[package]
-name = "bevy_framebuffer_extract"
-version = "0.1.2"
+name = "bevy_headless_render"
+version = "0.1.0"
edition = "2021"
+description = "A plugin for the bevy engine which enables headless rendering to an image for use in the main world."
+license = "0BSD OR MIT OR Apache-2.0"
[dependencies]
oneshot = "0.1.6"
pollster = "0.3.0"
[dependencies.bevy]
-version = "0.13"
+version = "0.14"
diff --git a/LICENSE-0BSD b/LICENSE-0BSD
new file mode 100644
index 0000000..7a39b21
--- /dev/null
+++ b/LICENSE-0BSD
@@ -0,0 +1,5 @@
+Copyright (C) 2024 by Silas Bartha [email protected]
+
+Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/README.md b/README.md
index ad6f12b..9de9ea9 100644
--- a/README.md
+++ b/README.md
@@ -1,26 +1,33 @@
-# bevy_framebuffer_extract
+# bevy_headless_render
+[![Crates](https://img.shields.io/crates/v/bevy_headless_render)](https://crates.io/crates/bevy_headless_render)
![License](https://img.shields.io/badge/license-MIT%2FApache-blue.svg)
-![Tag](https://img.shields.io/github/v/tag/exvacuum/bevy_framebuffer_extract)
-![Build](https://img.shields.io/github/actions/workflow/status/exvacuum/bevy_framebuffer_extract/rust.yml)
-[![Docs](https://img.shields.io/website?url=https%3A%2F%2Fexvacuum.github.io%2Fbevy_framebuffer_extract%2F&label=docs)](https://exvacuum.github.io/bevy_framebuffer_extract)
+![Tag](https://img.shields.io/github/v/tag/exvacuum/bevy_headless_render)
+![Build](https://img.shields.io/github/actions/workflow/status/exvacuum/bevy_headless_render/rust.yml)
+[![Docs](https://img.shields.io/website?url=https%3A%2F%2Fexvacuum.github.io%2Fbevy_headless_render%2F&label=docs)](https://exvacuum.github.io/bevy_headless_render)
-A plugin for the [Bevy](https://bevyengine.org) engine which allows for exporting framebuffer data from a camera.
+A plugin for the [Bevy](https://bevyengine.org) engine which allows for headless rendering.
-Currently it only supports cameras which render to a render texture.
+Every frame will be copied from `HeadlessRenderSource` render textures into `HeadlessRenderDestination` images each frame.
## Compatibility
| Crate Version | Bevy Version |
|--- |--- |
-| 0.1 | 0.13 |
+| 0.1 | 0.14 |
## Installation
+### crates.io
+```toml
+[dependencies]
+bevy_headless_render = "0.2"
+```
+
### Using git URL in Cargo.toml
```toml
-[dependencies.bevy_framebuffer_extract]
-git = "https://github.com/exvacuum/bevy_framebuffer_extract.git"
+[dependencies.bevy_headless_render]
+git = "https://github.com/exvacuum/bevy_headless_render.git"
```
## Usage
@@ -28,13 +35,13 @@ git = "https://github.com/exvacuum/bevy_framebuffer_extract.git"
In `main.rs`:
```rs
use bevy::prelude::*;
-use bevy_framebuffer_extract;
+use bevy_headless_render;
fn main() {
App::new()
.add_plugins((
DefaultPlugins,
- bevy_framebuffer_extract::FramebufferExtractPlugin,
+ bevy_headless_render::HeadlessRenderPlugin,
))
.run();
}
@@ -76,11 +83,16 @@ commands.spawn((
},
..Default::default()
},
- bevy_framebuffer_extract::ExtractFramebufferBundle {
- source: framebuffer_extract_sources.add(FramebufferExtractSource(image_handle.clone())), // ResMut<Assets<FramebufferExtractSource>>
- destination: FramebufferExtractDestination::default(),
+ bevy_headless_render::HeadlessRenderBundle {
+ source: headless_render_sources.add(HeadlessRenderSource(image_handle.clone())), // ResMut<Assets<HeadlessRenderSource>>
+ destination: HeadlessRenderDestination::default(),
},
));
```
-The FramebufferExtractDestination component will contain the extracted image which can be used or saved for whatever you need.
+The HeadlessRenderDestination component will contain the extracted image which can be used or saved for whatever you need.
+
+## License
+
+This crate is licensed under your choice of 0BSD, Apache-2.0, or MIT license.
+
diff --git a/src/components.rs b/src/components.rs
index f9fe912..8e25530 100644
--- a/src/components.rs
+++ b/src/components.rs
@@ -2,18 +2,18 @@ use std::sync::{Arc, Mutex};
use bevy::{ecs::query::QueryItem, prelude::*, render::extract_component::ExtractComponent};
-use crate::render_assets::FramebufferExtractSource;
+use crate::render_assets::HeadlessRenderSource;
-/// Framebuffer extraction destination. Contains the image which the framebuffer is extracted to.
+/// Headless render destination. Contains the image which the rendered frame is copied to.
#[derive(Component, Default, Clone)]
-pub struct FramebufferExtractDestination(pub Arc<Mutex<Image>>);
+pub struct HeadlessRenderDestination(pub Arc<Mutex<Image>>);
-impl ExtractComponent for FramebufferExtractDestination {
- type QueryData = (&'static Self, &'static Handle<FramebufferExtractSource>);
+impl ExtractComponent for HeadlessRenderDestination {
+ type QueryData = (&'static Self, &'static Handle<HeadlessRenderSource>);
type QueryFilter = ();
- type Out = (Self, Handle<FramebufferExtractSource>);
+ type Out = (Self, Handle<HeadlessRenderSource>);
fn extract_component(
(destination, source_handle): QueryItem<'_, Self::QueryData>,
@@ -22,11 +22,11 @@ impl ExtractComponent for FramebufferExtractDestination {
}
}
-/// Bundle containing both a source and destination for framebuffer extraction.
+/// Bundle containing both a source and destination for headless rendering.
#[derive(Bundle)]
-pub struct ExtractFramebufferBundle {
+pub struct HeadlessRenderBundle {
/// Source
- pub source: Handle<FramebufferExtractSource>,
+ pub source: Handle<HeadlessRenderSource>,
/// Destination
- pub dest: FramebufferExtractDestination,
+ pub dest: HeadlessRenderDestination,
}
diff --git a/src/lib.rs b/src/lib.rs
index 29a5896..9fadebe 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,6 @@
#![warn(missing_docs)]
-//! Plugin for the Bevy game engine which provides the ability to extract the frambuffer image after rendering
-//! to use for whatever you want.
+//! Plugin for the Bevy game engine which provides the ability to render to an image headlessly.
use bevy::{
prelude::*,
@@ -10,9 +9,9 @@ use bevy::{
render_asset::RenderAssetPlugin, render_graph::RenderGraph, Render, RenderApp, RenderSet,
},
};
-use components::FramebufferExtractDestination;
-use nodes::{FramebufferExtractLabel, FramebufferExtractNode};
-use render_assets::FramebufferExtractSource;
+use components::HeadlessRenderDestination;
+use nodes::{HeadlessRenderCopyLabel, HeadlessRenderCopyNode};
+use render_assets::{HeadlessRenderSource, GpuHeadlessRenderSource};
/// Components used by this plugin.
pub mod components;
@@ -22,28 +21,28 @@ pub mod render_assets;
mod nodes;
mod systems;
-/// Plugin which handles framebuffer extraction.
-pub struct FramebufferExtractPlugin;
+/// Plugin which handles headless rendering.
+pub struct HeadlessRenderPlugin;
-impl Plugin for FramebufferExtractPlugin {
+impl Plugin for HeadlessRenderPlugin {
fn build(&self, app: &mut App) {
- app.register_type::<FramebufferExtractSource>()
- .init_asset::<FramebufferExtractSource>()
- .register_asset_reflect::<FramebufferExtractSource>()
+ app.register_type::<HeadlessRenderSource>()
+ .init_asset::<HeadlessRenderSource>()
+ .register_asset_reflect::<HeadlessRenderSource>()
.add_plugins((
- RenderAssetPlugin::<FramebufferExtractSource>::default(),
- ExtractComponentPlugin::<FramebufferExtractDestination>::default(),
+ RenderAssetPlugin::<GpuHeadlessRenderSource>::default(),
+ ExtractComponentPlugin::<HeadlessRenderDestination>::default(),
));
let render_app = app.sub_app_mut(RenderApp);
render_app.add_systems(
Render,
- systems::extract_framebuffers
+ systems::copy_buffers
.after(RenderSet::Render)
.before(RenderSet::Cleanup),
);
- let mut graph = render_app.world.resource_mut::<RenderGraph>();
- graph.add_node(FramebufferExtractLabel, FramebufferExtractNode);
- graph.add_node_edge(CameraDriverLabel, FramebufferExtractLabel);
+ let mut graph = render_app.world_mut().resource_mut::<RenderGraph>();
+ graph.add_node(HeadlessRenderCopyLabel, HeadlessRenderCopyNode);
+ graph.add_node_edge(CameraDriverLabel, HeadlessRenderCopyLabel);
}
}
diff --git a/src/nodes.rs b/src/nodes.rs
index 9791ad1..4e2ddd3 100644
--- a/src/nodes.rs
+++ b/src/nodes.rs
@@ -4,19 +4,19 @@ use bevy::{
render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext, RenderLabel},
render_resource::{ImageCopyBuffer, ImageDataLayout},
- renderer::RenderContext,
+ renderer::RenderContext, texture::GpuImage,
},
};
-use crate::render_assets::FramebufferExtractSource;
+use crate::render_assets::GpuHeadlessRenderSource;
#[derive(RenderLabel, Clone, PartialEq, Eq, Debug, Hash)]
-pub struct FramebufferExtractLabel;
+pub struct HeadlessRenderCopyLabel;
#[derive(Default)]
-pub struct FramebufferExtractNode;
+pub struct HeadlessRenderCopyNode;
-impl Node for FramebufferExtractNode {
+impl Node for HeadlessRenderCopyNode {
fn run(
&self,
_graph: &mut RenderGraphContext,
@@ -24,12 +24,12 @@ impl Node for FramebufferExtractNode {
world: &World,
) -> Result<(), NodeRunError> {
for (_, source) in world
- .resource::<RenderAssets<FramebufferExtractSource>>()
+ .resource::<RenderAssets<GpuHeadlessRenderSource>>()
.iter()
{
let Some(gpu_image) = world
- .resource::<RenderAssets<Image>>()
- .get(&source.source_handle)
+ .resource::<RenderAssets<GpuImage>>()
+ .get(source.source_handle.id())
else {
return Ok(());
};
diff --git a/src/render_assets.rs b/src/render_assets.rs
index e5277d7..48efdd0 100644
--- a/src/render_assets.rs
+++ b/src/render_assets.rs
@@ -2,14 +2,14 @@ use bevy::{
ecs::system::{lifetimeless::SRes, SystemParamItem},
prelude::*,
render::{
- render_asset::{PrepareAssetError, RenderAsset, RenderAssetUsages, RenderAssets},
+ render_asset::{PrepareAssetError, RenderAsset, RenderAssets},
render_resource::{Buffer, BufferDescriptor, BufferUsages, Extent3d, TextureFormat},
- renderer::RenderDevice,
+ renderer::RenderDevice, texture::GpuImage,
},
};
-/// Render-world version of FramebufferExtractSource
-pub struct GpuFramebufferExtractSource {
+/// Render-world version of HeadlessRenderSource
+pub struct GpuHeadlessRenderSource {
pub(crate) buffer: Buffer,
pub(crate) source_handle: Handle<Image>,
pub(crate) source_size: Extent3d,
@@ -18,26 +18,22 @@ pub struct GpuFramebufferExtractSource {
pub(crate) format: TextureFormat,
}
-/// Framebuffer extraction source. Contains a handle to the render texture which will be extracted
+/// Headless render source. Contains a handle to the render texture which will be copied
/// from.
#[derive(Asset, Reflect, Clone, Default)]
-pub struct FramebufferExtractSource(pub Handle<Image>);
+pub struct HeadlessRenderSource(pub Handle<Image>);
-impl RenderAsset for FramebufferExtractSource {
- type PreparedAsset = GpuFramebufferExtractSource;
- type Param = (SRes<RenderDevice>, SRes<RenderAssets<Image>>);
-
- fn asset_usage(&self) -> RenderAssetUsages {
- RenderAssetUsages::default()
- }
+impl RenderAsset for GpuHeadlessRenderSource {
+ type SourceAsset = HeadlessRenderSource;
+ type Param = (SRes<RenderDevice>, SRes<RenderAssets<GpuImage>>);
fn prepare_asset(
- self,
+ source_asset: Self::SourceAsset,
(device, images): &mut SystemParamItem<Self::Param>,
- ) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
- let Some(gpu_image) = images.get(&self.0) else {
+ ) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
+ let Some(gpu_image) = images.get(source_asset.0.id()) else {
warn!("Failed to get GPU image");
- return Err(PrepareAssetError::RetryNextUpdate(self));
+ return Err(PrepareAssetError::RetryNextUpdate(source_asset));
};
let size = gpu_image.texture.size();
@@ -47,18 +43,19 @@ impl RenderAsset for FramebufferExtractSource {
let padded_bytes_per_row =
RenderDevice::align_copy_bytes_per_row(bytes_per_row as usize) as u32;
- Ok(GpuFramebufferExtractSource {
+ Ok(GpuHeadlessRenderSource {
buffer: device.create_buffer(&BufferDescriptor {
label: Some("framebuffer_extract_buffer"),
size: (size.height * padded_bytes_per_row) as u64,
usage: BufferUsages::COPY_DST | BufferUsages::MAP_READ,
mapped_at_creation: false,
}),
- source_handle: self.0.clone(),
+ source_handle: source_asset.0.clone(),
source_size: size,
bytes_per_row,
padded_bytes_per_row,
format,
})
}
+
}
diff --git a/src/systems.rs b/src/systems.rs
index 74f8dc8..bb0efc7 100644
--- a/src/systems.rs
+++ b/src/systems.rs
@@ -9,17 +9,17 @@ use bevy::{
use pollster::FutureExt;
-use crate::{components::FramebufferExtractDestination, render_assets::FramebufferExtractSource};
+use crate::{components::HeadlessRenderDestination, render_assets::{HeadlessRenderSource, GpuHeadlessRenderSource}};
-pub fn extract_framebuffers(
- mut extract_bundles: Query<(
- &Handle<FramebufferExtractSource>,
- &mut FramebufferExtractDestination,
+pub fn copy_buffers(
+ mut headless_render_query: Query<(
+ &Handle<HeadlessRenderSource>,
+ &mut HeadlessRenderDestination,
)>,
- sources: Res<RenderAssets<FramebufferExtractSource>>,
+ sources: Res<RenderAssets<GpuHeadlessRenderSource>>,
device: Res<RenderDevice>,
) {
- for (source_handle, destination_handle) in extract_bundles.iter_mut() {
+ for (source_handle, destination_handle) in headless_render_query.iter_mut() {
let Some(gpu_source) = sources.get(source_handle) else {
continue;
};