Support async texture loading
This commit is contained in:
parent
35adad6556
commit
bf7f222318
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
@ -993,6 +993,7 @@
|
|||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug example 'sprite'",
|
"name": "Debug example 'sprite'",
|
||||||
|
"env": { "CARGO_MANIFEST_DIR": "${workspaceFolder}" },
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
|
@ -13,7 +13,7 @@ Bevy is still in the _very_ early stages of development. APIs can and will chang
|
|||||||
|
|
||||||
## Design Goals
|
## Design Goals
|
||||||
|
|
||||||
* Provide a first class user-experience for both 2D and 3D games.
|
* Provide a first class developer experience for both 2D and 3D games.
|
||||||
* Easy for newbies to pick up, but infinitely flexible for power users.
|
* Easy for newbies to pick up, but infinitely flexible for power users.
|
||||||
* Fast iterative compile times. Ideally less than 1 second for small to medium sized projects.
|
* Fast iterative compile times. Ideally less than 1 second for small to medium sized projects.
|
||||||
* Data-first game development using ECS (Entity Component System)
|
* Data-first game development using ECS (Entity Component System)
|
||||||
|
@ -174,6 +174,7 @@ impl AppBuilder {
|
|||||||
self.add_startup_stage(stage::STARTUP)
|
self.add_startup_stage(stage::STARTUP)
|
||||||
.add_stage(stage::FIRST)
|
.add_stage(stage::FIRST)
|
||||||
.add_stage(stage::EVENT_UPDATE)
|
.add_stage(stage::EVENT_UPDATE)
|
||||||
|
.add_stage(stage::PRE_UPDATE)
|
||||||
.add_stage(stage::UPDATE)
|
.add_stage(stage::UPDATE)
|
||||||
.add_stage(stage::POST_UPDATE)
|
.add_stage(stage::POST_UPDATE)
|
||||||
.add_stage(stage::LAST)
|
.add_stage(stage::LAST)
|
||||||
|
@ -7,10 +7,13 @@ pub const FIRST: &str = "first";
|
|||||||
/// Name of app stage that updates events. Generally this should run before UPDATE
|
/// Name of app stage that updates events. Generally this should run before UPDATE
|
||||||
pub const EVENT_UPDATE: &str = "event_update";
|
pub const EVENT_UPDATE: &str = "event_update";
|
||||||
|
|
||||||
|
/// Name of app stage responsible for performing setup before an update. Runs before UPDATE.
|
||||||
|
pub const PRE_UPDATE: &str = "pre_update";
|
||||||
|
|
||||||
/// Name of app stage responsible for doing most app logic. Systems should be registered here by default.
|
/// Name of app stage responsible for doing most app logic. Systems should be registered here by default.
|
||||||
pub const UPDATE: &str = "update";
|
pub const UPDATE: &str = "update";
|
||||||
|
|
||||||
/// Name of app stage responsible for processing the results of UPDATE. Runs immediately after UPDATE.
|
/// Name of app stage responsible for processing the results of UPDATE. Runs after UPDATE.
|
||||||
pub const POST_UPDATE: &str = "post_update";
|
pub const POST_UPDATE: &str = "post_update";
|
||||||
|
|
||||||
/// Name of app stage that runs after all other app stages
|
/// Name of app stage that runs after all other app stages
|
||||||
|
@ -32,3 +32,4 @@ smallvec = "1.4.0"
|
|||||||
once_cell = "1.3.1"
|
once_cell = "1.3.1"
|
||||||
downcast-rs = "1.1.1"
|
downcast-rs = "1.1.1"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
anyhow = "1.0"
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
pass::RenderPass,
|
pass::RenderPass,
|
||||||
pipeline::{PipelineAssignments, PipelineDescriptor},
|
pipeline::{PipelineAssignments, PipelineDescriptor},
|
||||||
render_resource::{
|
render_resource::{
|
||||||
resource_name, EntityRenderResourceAssignments, RenderResourceAssignments, ResourceInfo,
|
resource_name, EntityRenderResourceAssignments, RenderResourceAssignments, ResourceInfo, EntitiesWaitingForAssets,
|
||||||
},
|
},
|
||||||
renderer::RenderContext,
|
renderer::RenderContext,
|
||||||
Renderable,
|
Renderable,
|
||||||
@ -28,6 +28,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||||||
let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
|
let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
|
||||||
let entity_render_resource_assignments =
|
let entity_render_resource_assignments =
|
||||||
resources.get::<EntityRenderResourceAssignments>().unwrap();
|
resources.get::<EntityRenderResourceAssignments>().unwrap();
|
||||||
|
let entities_waiting_for_assets = resources.get::<EntitiesWaitingForAssets>().unwrap();
|
||||||
let mut current_mesh_handle = None;
|
let mut current_mesh_handle = None;
|
||||||
let mut current_mesh_index_len = 0;
|
let mut current_mesh_index_len = 0;
|
||||||
let global_render_resource_assignments =
|
let global_render_resource_assignments =
|
||||||
@ -45,7 +46,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||||||
.get(*assignment_id)
|
.get(*assignment_id)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let renderable = world.get_component::<Renderable>(*entity).unwrap();
|
let renderable = world.get_component::<Renderable>(*entity).unwrap();
|
||||||
if !renderable.is_visible || renderable.is_instanced {
|
if !renderable.is_visible || renderable.is_instanced || entities_waiting_for_assets.contains(entity) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,9 @@ use bevy_app::{stage, AppBuilder, AppPlugin};
|
|||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use mesh::mesh_resource_provider_system;
|
use mesh::mesh_resource_provider_system;
|
||||||
use render_graph::RenderGraph;
|
use render_graph::RenderGraph;
|
||||||
|
use texture::PngTextureLoader;
|
||||||
|
use render_resource::EntitiesWaitingForAssets;
|
||||||
|
use legion::prelude::IntoSystem;
|
||||||
|
|
||||||
pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
|
pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
|
||||||
pub static RENDER_STAGE: &str = "render";
|
pub static RENDER_STAGE: &str = "render";
|
||||||
@ -75,16 +78,19 @@ impl AppPlugin for RenderPlugin {
|
|||||||
.add_asset::<Texture>()
|
.add_asset::<Texture>()
|
||||||
.add_asset::<Shader>()
|
.add_asset::<Shader>()
|
||||||
.add_asset::<PipelineDescriptor>()
|
.add_asset::<PipelineDescriptor>()
|
||||||
|
.add_asset_loader(PngTextureLoader::default())
|
||||||
.add_resource(render_graph)
|
.add_resource(render_graph)
|
||||||
.init_resource::<PipelineAssignments>()
|
.init_resource::<PipelineAssignments>()
|
||||||
.init_resource::<PipelineCompiler>()
|
.init_resource::<PipelineCompiler>()
|
||||||
.init_resource::<RenderResourceAssignments>()
|
.init_resource::<RenderResourceAssignments>()
|
||||||
.init_resource::<VertexBufferDescriptors>()
|
.init_resource::<VertexBufferDescriptors>()
|
||||||
.init_resource::<EntityRenderResourceAssignments>()
|
.init_resource::<EntityRenderResourceAssignments>()
|
||||||
|
.init_resource::<EntitiesWaitingForAssets>()
|
||||||
// core systems
|
// core systems
|
||||||
.add_system(entity_render_resource_assignments_system())
|
.add_system(entity_render_resource_assignments_system())
|
||||||
.init_system_to_stage(stage::POST_UPDATE, camera::camera_update_system)
|
.init_system_to_stage(stage::POST_UPDATE, camera::camera_update_system)
|
||||||
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_specializer_system())
|
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_specializer_system())
|
||||||
|
.add_system_to_stage(stage::PRE_UPDATE, EntitiesWaitingForAssets::clear_system.system())
|
||||||
// render resource provider systems
|
// render resource provider systems
|
||||||
.init_system_to_stage(RENDER_RESOURCE_STAGE, mesh_resource_provider_system);
|
.init_system_to_stage(RENDER_RESOURCE_STAGE, mesh_resource_provider_system);
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ use crate::{
|
|||||||
pipeline::VertexBufferDescriptors,
|
pipeline::VertexBufferDescriptors,
|
||||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||||
render_resource::{
|
render_resource::{
|
||||||
BufferInfo, BufferUsage, RenderResource, RenderResourceAssignment,
|
BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResource,
|
||||||
RenderResourceAssignments, RenderResourceAssignmentsId,
|
RenderResourceAssignment, RenderResourceAssignments, RenderResourceAssignmentsId,
|
||||||
},
|
},
|
||||||
renderer::{RenderContext, RenderResourceContext, RenderResources},
|
renderer::{RenderContext, RenderResourceContext, RenderResources},
|
||||||
shader::{AsUniforms, FieldBindType},
|
shader::{AsUniforms, FieldBindType},
|
||||||
@ -400,13 +400,14 @@ where
|
|||||||
))
|
))
|
||||||
.read_resource::<Assets<Texture>>()
|
.read_resource::<Assets<Texture>>()
|
||||||
.read_resource::<RenderResources>()
|
.read_resource::<RenderResources>()
|
||||||
|
.read_resource::<EntitiesWaitingForAssets>()
|
||||||
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||||
.with_query(<(Read<T>, Read<Renderable>)>::query())
|
.with_query(<(Read<T>, Read<Renderable>)>::query())
|
||||||
.with_query(<(Read<T>, Write<Renderable>)>::query())
|
.with_query(<(Read<T>, Write<Renderable>)>::query())
|
||||||
.build(
|
.build(
|
||||||
move |_,
|
move |_,
|
||||||
world,
|
world,
|
||||||
(textures, render_resources),
|
(textures, render_resources, entities_waiting_for_assets),
|
||||||
(read_uniform_query, write_uniform_query)| {
|
(read_uniform_query, write_uniform_query)| {
|
||||||
let render_resource_context = &*render_resources.context;
|
let render_resource_context = &*render_resources.context;
|
||||||
|
|
||||||
@ -428,7 +429,9 @@ where
|
|||||||
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
||||||
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||||
|
|
||||||
for (uniforms, mut renderable) in write_uniform_query.iter_mut(world) {
|
for (entity, (uniforms, mut renderable)) in
|
||||||
|
write_uniform_query.iter_entities_mut(world)
|
||||||
|
{
|
||||||
if !renderable.is_visible {
|
if !renderable.is_visible {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -437,10 +440,12 @@ where
|
|||||||
panic!("instancing not currently supported");
|
panic!("instancing not currently supported");
|
||||||
} else {
|
} else {
|
||||||
setup_uniform_texture_resources::<T>(
|
setup_uniform_texture_resources::<T>(
|
||||||
|
entity,
|
||||||
&uniforms,
|
&uniforms,
|
||||||
&mut command_queue,
|
&mut command_queue,
|
||||||
textures,
|
textures,
|
||||||
render_resource_context,
|
render_resource_context,
|
||||||
|
entities_waiting_for_assets,
|
||||||
&mut renderable.render_resource_assignments,
|
&mut renderable.render_resource_assignments,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -554,19 +559,20 @@ where
|
|||||||
.read_resource::<Assets<T>>()
|
.read_resource::<Assets<T>>()
|
||||||
.read_resource::<Assets<Texture>>()
|
.read_resource::<Assets<Texture>>()
|
||||||
.read_resource::<RenderResources>()
|
.read_resource::<RenderResources>()
|
||||||
|
.read_resource::<EntitiesWaitingForAssets>()
|
||||||
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||||
.with_query(<(Read<Handle<T>>, Read<Renderable>)>::query())
|
.with_query(<(Read<Handle<T>>, Read<Renderable>)>::query())
|
||||||
.with_query(<(Read<Handle<T>>, Write<Renderable>)>::query())
|
.with_query(<(Read<Handle<T>>, Write<Renderable>)>::query())
|
||||||
.build(
|
.build(
|
||||||
move |_,
|
move |_,
|
||||||
world,
|
world,
|
||||||
(assets, textures, render_resources),
|
(assets, textures, render_resources, entities_waiting_for_assets),
|
||||||
(read_handle_query, write_handle_query)| {
|
(read_handle_query, write_handle_query)| {
|
||||||
let render_resource_context = &*render_resources.context;
|
let render_resource_context = &*render_resources.context;
|
||||||
uniform_buffer_arrays.reset_new_item_counts();
|
uniform_buffer_arrays.reset_new_item_counts();
|
||||||
|
|
||||||
// update uniform handles info
|
// update uniform handles info
|
||||||
for (handle, renderable) in read_handle_query.iter(world) {
|
for (entity, (handle, renderable)) in read_handle_query.iter_entities(world) {
|
||||||
if !renderable.is_visible {
|
if !renderable.is_visible {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -574,11 +580,12 @@ where
|
|||||||
if renderable.is_instanced {
|
if renderable.is_instanced {
|
||||||
panic!("instancing not currently supported");
|
panic!("instancing not currently supported");
|
||||||
} else {
|
} else {
|
||||||
let uniforms = assets
|
if let Some(uniforms) = assets.get(&handle) {
|
||||||
.get(&handle)
|
|
||||||
.expect("Handle points to a non-existent resource");
|
|
||||||
// TODO: only increment count if we haven't seen this uniform handle before
|
// TODO: only increment count if we haven't seen this uniform handle before
|
||||||
uniform_buffer_arrays.increment_uniform_counts(&uniforms);
|
uniform_buffer_arrays.increment_uniform_counts(&uniforms);
|
||||||
|
} else {
|
||||||
|
entities_waiting_for_assets.add(entity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,7 +593,9 @@ where
|
|||||||
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
||||||
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||||
|
|
||||||
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
|
for (entity, (handle, mut renderable)) in
|
||||||
|
write_handle_query.iter_entities_mut(world)
|
||||||
|
{
|
||||||
if !renderable.is_visible {
|
if !renderable.is_visible {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -594,18 +603,19 @@ where
|
|||||||
if renderable.is_instanced {
|
if renderable.is_instanced {
|
||||||
panic!("instancing not currently supported");
|
panic!("instancing not currently supported");
|
||||||
} else {
|
} else {
|
||||||
let uniforms = assets
|
if let Some(uniforms) = assets.get(&handle) {
|
||||||
.get(&handle)
|
|
||||||
.expect("Handle points to a non-existent resource");
|
|
||||||
setup_uniform_texture_resources::<T>(
|
setup_uniform_texture_resources::<T>(
|
||||||
|
entity,
|
||||||
&uniforms,
|
&uniforms,
|
||||||
&mut command_queue,
|
&mut command_queue,
|
||||||
textures,
|
textures,
|
||||||
render_resource_context,
|
render_resource_context,
|
||||||
|
entities_waiting_for_assets,
|
||||||
&mut renderable.render_resource_assignments,
|
&mut renderable.render_resource_assignments,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if staging_buffer_size == 0 {
|
if staging_buffer_size == 0 {
|
||||||
let mut staging_buffer: [u8; 0] = [];
|
let mut staging_buffer: [u8; 0] = [];
|
||||||
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
|
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
|
||||||
@ -615,9 +625,7 @@ where
|
|||||||
if renderable.is_instanced {
|
if renderable.is_instanced {
|
||||||
panic!("instancing not currently supported");
|
panic!("instancing not currently supported");
|
||||||
} else {
|
} else {
|
||||||
let uniforms = assets
|
if let Some(uniforms) = assets.get(&handle) {
|
||||||
.get(&handle)
|
|
||||||
.expect("Handle points to a non-existent resource");
|
|
||||||
// TODO: only setup buffer if we haven't seen this handle before
|
// TODO: only setup buffer if we haven't seen this handle before
|
||||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||||
&uniforms,
|
&uniforms,
|
||||||
@ -628,6 +636,7 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let staging_buffer = render_resource_context.create_buffer_mapped(
|
let staging_buffer = render_resource_context.create_buffer_mapped(
|
||||||
BufferInfo {
|
BufferInfo {
|
||||||
@ -643,9 +652,7 @@ where
|
|||||||
if renderable.is_instanced {
|
if renderable.is_instanced {
|
||||||
panic!("instancing not currently supported");
|
panic!("instancing not currently supported");
|
||||||
} else {
|
} else {
|
||||||
let uniforms = assets
|
if let Some(uniforms) = assets.get(&handle) {
|
||||||
.get(&handle)
|
|
||||||
.expect("Handle points to a non-existent resource");
|
|
||||||
// TODO: only setup buffer if we haven't seen this handle before
|
// TODO: only setup buffer if we haven't seen this handle before
|
||||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||||
&uniforms,
|
&uniforms,
|
||||||
@ -656,6 +663,7 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -684,10 +692,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn setup_uniform_texture_resources<T>(
|
fn setup_uniform_texture_resources<T>(
|
||||||
|
entity: Entity,
|
||||||
uniforms: &T,
|
uniforms: &T,
|
||||||
command_queue: &mut CommandQueue,
|
command_queue: &mut CommandQueue,
|
||||||
textures: &Assets<Texture>,
|
textures: &Assets<Texture>,
|
||||||
render_resource_context: &dyn RenderResourceContext,
|
render_resource_context: &dyn RenderResourceContext,
|
||||||
|
entities_waiting_for_assets: &EntitiesWaitingForAssets,
|
||||||
render_resource_assignments: &mut RenderResourceAssignments,
|
render_resource_assignments: &mut RenderResourceAssignments,
|
||||||
) where
|
) where
|
||||||
T: AsUniforms,
|
T: AsUniforms,
|
||||||
@ -709,13 +719,10 @@ fn setup_uniform_texture_resources<T>(
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
None => {
|
None => {
|
||||||
let texture = textures.get(&texture_handle).unwrap();
|
if let Some(texture) = textures.get(&texture_handle) {
|
||||||
|
|
||||||
let texture_descriptor: TextureDescriptor = texture.into();
|
let texture_descriptor: TextureDescriptor = texture.into();
|
||||||
let texture_resource =
|
let texture_resource =
|
||||||
render_resource_context.create_texture(texture_descriptor);
|
render_resource_context.create_texture(texture_descriptor);
|
||||||
// TODO: queue texture copy
|
|
||||||
// .create_texture_with_data(&texture_descriptor, &texture.data);
|
|
||||||
let texture_buffer = render_resource_context.create_buffer_with_data(
|
let texture_buffer = render_resource_context.create_buffer_with_data(
|
||||||
BufferInfo {
|
BufferInfo {
|
||||||
buffer_usage: BufferUsage::COPY_SRC,
|
buffer_usage: BufferUsage::COPY_SRC,
|
||||||
@ -751,6 +758,10 @@ fn setup_uniform_texture_resources<T>(
|
|||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
(texture_resource, sampler_resource)
|
(texture_resource, sampler_resource)
|
||||||
|
} else {
|
||||||
|
entities_waiting_for_assets.add(entity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
use legion::prelude::{Entity, Res};
|
||||||
|
use std::{sync::RwLock, collections::HashSet};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct EntitiesWaitingForAssets {
|
||||||
|
pub entities: RwLock<HashSet<Entity>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntitiesWaitingForAssets {
|
||||||
|
pub fn add(&self, entity: Entity) {
|
||||||
|
self.entities.write().expect("RwLock poisoned").insert(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, entity: &Entity) -> bool {
|
||||||
|
self.entities.read().expect("RwLock poisoned").contains(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.entities.write().expect("RwLock poisoned").clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_system(entities_waiting_for_assets: Res<EntitiesWaitingForAssets>) {
|
||||||
|
entities_waiting_for_assets.clear();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
mod buffer;
|
mod buffer;
|
||||||
mod entity_render_resource_assignments;
|
mod entity_render_resource_assignments;
|
||||||
|
mod entities_waiting_for_assets;
|
||||||
mod render_resource;
|
mod render_resource;
|
||||||
mod render_resource_assignments;
|
mod render_resource_assignments;
|
||||||
mod resource_info;
|
mod resource_info;
|
||||||
@ -7,6 +8,7 @@ pub mod resource_name;
|
|||||||
|
|
||||||
pub use buffer::*;
|
pub use buffer::*;
|
||||||
pub use entity_render_resource_assignments::*;
|
pub use entity_render_resource_assignments::*;
|
||||||
|
pub use entities_waiting_for_assets::*;
|
||||||
pub use render_resource::*;
|
pub use render_resource::*;
|
||||||
pub use render_resource_assignments::*;
|
pub use render_resource_assignments::*;
|
||||||
pub use resource_info::*;
|
pub use resource_info::*;
|
||||||
|
@ -2,8 +2,10 @@ mod sampler_descriptor;
|
|||||||
mod texture;
|
mod texture;
|
||||||
mod texture_descriptor;
|
mod texture_descriptor;
|
||||||
mod texture_dimension;
|
mod texture_dimension;
|
||||||
|
mod png_texture_loader;
|
||||||
|
|
||||||
pub use sampler_descriptor::*;
|
pub use sampler_descriptor::*;
|
||||||
pub use texture::*;
|
pub use texture::*;
|
||||||
pub use texture_descriptor::*;
|
pub use texture_descriptor::*;
|
||||||
pub use texture_dimension::*;
|
pub use texture_dimension::*;
|
||||||
|
pub use png_texture_loader::*;
|
26
crates/bevy_render/src/texture/png_texture_loader.rs
Normal file
26
crates/bevy_render/src/texture/png_texture_loader.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use bevy_asset::{AssetPath, AssetLoader};
|
||||||
|
use super::Texture;
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct PngTextureLoader;
|
||||||
|
|
||||||
|
impl AssetLoader<Texture> for PngTextureLoader {
|
||||||
|
fn from_bytes(&self, _asset_path: &AssetPath, bytes: Vec<u8>) -> Result<Texture> {
|
||||||
|
let decoder = png::Decoder::new(bytes.as_slice());
|
||||||
|
let (info, mut reader) = decoder.read_info()?;
|
||||||
|
let mut data = vec![0; info.buffer_size()];
|
||||||
|
reader.next_frame(&mut data)?;
|
||||||
|
Ok(Texture {
|
||||||
|
data,
|
||||||
|
width: info.width as usize,
|
||||||
|
height: info.height as usize,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn extensions(&self) -> &[&str] {
|
||||||
|
static EXTENSIONS: &[&str] = &[
|
||||||
|
"png"
|
||||||
|
];
|
||||||
|
EXTENSIONS
|
||||||
|
}
|
||||||
|
}
|
@ -25,11 +25,12 @@ pub fn sprite_system() -> Box<dyn Schedulable> {
|
|||||||
for (sprite, handle, mut rect) in query.iter_mut(world) {
|
for (sprite, handle, mut rect) in query.iter_mut(world) {
|
||||||
let material = materials.get(&handle).unwrap();
|
let material = materials.get(&handle).unwrap();
|
||||||
if let Some(texture_handle) = material.texture {
|
if let Some(texture_handle) = material.texture {
|
||||||
let texture = textures.get(&texture_handle).unwrap();
|
if let Some(texture) = textures.get(&texture_handle) {
|
||||||
let aspect = texture.aspect();
|
let aspect = texture.aspect();
|
||||||
*rect.size.x_mut() = texture.width as f32 * sprite.scale;
|
*rect.size.x_mut() = texture.width as f32 * sprite.scale;
|
||||||
*rect.size.y_mut() = rect.size.x() * aspect;
|
*rect.size.y_mut() = rect.size.x() * aspect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -557,7 +557,6 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||||||
return Some(render_resource_set.id);
|
return Some(render_resource_set.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,10 @@ fn main() {
|
|||||||
|
|
||||||
fn setup(
|
fn setup(
|
||||||
command_buffer: &mut CommandBuffer,
|
command_buffer: &mut CommandBuffer,
|
||||||
mut textures: ResMut<Assets<Texture>>,
|
asset_server: Res<AssetServer>,
|
||||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
) {
|
) {
|
||||||
let texture = Texture::load(TextureType::Png("assets/branding/icon.png".to_string()));
|
let texture_handle = asset_server.load("assets/branding/icon.png").unwrap();
|
||||||
let texture_handle = textures.add(texture);
|
|
||||||
|
|
||||||
command_buffer
|
command_buffer
|
||||||
.build()
|
.build()
|
||||||
.add_entity(Camera2dEntity::default())
|
.add_entity(Camera2dEntity::default())
|
||||||
|
@ -10,16 +10,15 @@ fn main() {
|
|||||||
/// sets up a scene with textured entities
|
/// sets up a scene with textured entities
|
||||||
fn setup(
|
fn setup(
|
||||||
command_buffer: &mut CommandBuffer,
|
command_buffer: &mut CommandBuffer,
|
||||||
|
asset_server: Res<AssetServer>,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut textures: ResMut<Assets<Texture>>,
|
mut textures: ResMut<Assets<Texture>>,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
) {
|
) {
|
||||||
// load a texture
|
// load a texture
|
||||||
let texture = Texture::load(TextureType::Png(
|
let texture_handle = asset_server.load_sync(&mut textures, "assets/branding/bevy_logo_dark_big.png").unwrap();
|
||||||
"assets/branding/bevy_logo_dark_big.pn".to_string(),
|
let texture = textures.get(&texture_handle).unwrap();
|
||||||
));
|
|
||||||
let aspect = texture.aspect();
|
let aspect = texture.aspect();
|
||||||
let texture_handle = textures.add(texture);
|
|
||||||
|
|
||||||
// create a new quad mesh. this is what we will apply the texture to
|
// create a new quad mesh. this is what we will apply the texture to
|
||||||
let quad_width = 8.0;
|
let quad_width = 8.0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#[cfg(feature = "asset")]
|
#[cfg(feature = "asset")]
|
||||||
pub use crate::asset::{AddAsset, AssetEvent, Assets, Handle};
|
pub use crate::asset::{AddAsset, AssetEvent, Assets, Handle, AssetServer};
|
||||||
#[cfg(feature = "core")]
|
#[cfg(feature = "core")]
|
||||||
pub use crate::core::{
|
pub use crate::core::{
|
||||||
time::Time,
|
time::Time,
|
||||||
|
Loading…
Reference in New Issue
Block a user