mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Support async texture loading
This commit is contained in:
parent
35adad6556
commit
bf7f222318
17 changed files with 179 additions and 103 deletions
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
|
@ -993,6 +993,7 @@
|
|||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug example 'sprite'",
|
||||
"env": { "CARGO_MANIFEST_DIR": "${workspaceFolder}" },
|
||||
"cargo": {
|
||||
"args": [
|
||||
"build",
|
||||
|
|
|
@ -13,7 +13,7 @@ Bevy is still in the _very_ early stages of development. APIs can and will chang
|
|||
|
||||
## 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.
|
||||
* Fast iterative compile times. Ideally less than 1 second for small to medium sized projects.
|
||||
* Data-first game development using ECS (Entity Component System)
|
||||
|
|
|
@ -174,6 +174,7 @@ impl AppBuilder {
|
|||
self.add_startup_stage(stage::STARTUP)
|
||||
.add_stage(stage::FIRST)
|
||||
.add_stage(stage::EVENT_UPDATE)
|
||||
.add_stage(stage::PRE_UPDATE)
|
||||
.add_stage(stage::UPDATE)
|
||||
.add_stage(stage::POST_UPDATE)
|
||||
.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
|
||||
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.
|
||||
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";
|
||||
|
||||
/// Name of app stage that runs after all other app stages
|
||||
|
|
|
@ -31,4 +31,5 @@ smallvec = "1.4.0"
|
|||
# TODO: replace once_cell with std equivalent if/when this lands: https://github.com/rust-lang/rfcs/pull/2788
|
||||
once_cell = "1.3.1"
|
||||
downcast-rs = "1.1.1"
|
||||
thiserror = "1.0"
|
||||
thiserror = "1.0"
|
||||
anyhow = "1.0"
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
pass::RenderPass,
|
||||
pipeline::{PipelineAssignments, PipelineDescriptor},
|
||||
render_resource::{
|
||||
resource_name, EntityRenderResourceAssignments, RenderResourceAssignments, ResourceInfo,
|
||||
resource_name, EntityRenderResourceAssignments, RenderResourceAssignments, ResourceInfo, EntitiesWaitingForAssets,
|
||||
},
|
||||
renderer::RenderContext,
|
||||
Renderable,
|
||||
|
@ -28,6 +28,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||
let shader_pipeline_assignments = resources.get::<PipelineAssignments>().unwrap();
|
||||
let entity_render_resource_assignments =
|
||||
resources.get::<EntityRenderResourceAssignments>().unwrap();
|
||||
let entities_waiting_for_assets = resources.get::<EntitiesWaitingForAssets>().unwrap();
|
||||
let mut current_mesh_handle = None;
|
||||
let mut current_mesh_index_len = 0;
|
||||
let global_render_resource_assignments =
|
||||
|
@ -45,7 +46,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
|
|||
.get(*assignment_id)
|
||||
.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;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@ use bevy_app::{stage, AppBuilder, AppPlugin};
|
|||
use bevy_asset::AddAsset;
|
||||
use mesh::mesh_resource_provider_system;
|
||||
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_STAGE: &str = "render";
|
||||
|
@ -75,16 +78,19 @@ impl AppPlugin for RenderPlugin {
|
|||
.add_asset::<Texture>()
|
||||
.add_asset::<Shader>()
|
||||
.add_asset::<PipelineDescriptor>()
|
||||
.add_asset_loader(PngTextureLoader::default())
|
||||
.add_resource(render_graph)
|
||||
.init_resource::<PipelineAssignments>()
|
||||
.init_resource::<PipelineCompiler>()
|
||||
.init_resource::<RenderResourceAssignments>()
|
||||
.init_resource::<VertexBufferDescriptors>()
|
||||
.init_resource::<EntityRenderResourceAssignments>()
|
||||
.init_resource::<EntitiesWaitingForAssets>()
|
||||
// core systems
|
||||
.add_system(entity_render_resource_assignments_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::PRE_UPDATE, EntitiesWaitingForAssets::clear_system.system())
|
||||
// render resource provider systems
|
||||
.init_system_to_stage(RENDER_RESOURCE_STAGE, mesh_resource_provider_system);
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ use crate::{
|
|||
pipeline::VertexBufferDescriptors,
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{
|
||||
BufferInfo, BufferUsage, RenderResource, RenderResourceAssignment,
|
||||
RenderResourceAssignments, RenderResourceAssignmentsId,
|
||||
BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResource,
|
||||
RenderResourceAssignment, RenderResourceAssignments, RenderResourceAssignmentsId,
|
||||
},
|
||||
renderer::{RenderContext, RenderResourceContext, RenderResources},
|
||||
shader::{AsUniforms, FieldBindType},
|
||||
|
@ -400,13 +400,14 @@ where
|
|||
))
|
||||
.read_resource::<Assets<Texture>>()
|
||||
.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
|
||||
.with_query(<(Read<T>, Read<Renderable>)>::query())
|
||||
.with_query(<(Read<T>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_,
|
||||
world,
|
||||
(textures, render_resources),
|
||||
(textures, render_resources, entities_waiting_for_assets),
|
||||
(read_uniform_query, write_uniform_query)| {
|
||||
let render_resource_context = &*render_resources.context;
|
||||
|
||||
|
@ -428,7 +429,9 @@ where
|
|||
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
||||
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 {
|
||||
return;
|
||||
}
|
||||
|
@ -437,10 +440,12 @@ where
|
|||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
setup_uniform_texture_resources::<T>(
|
||||
entity,
|
||||
&uniforms,
|
||||
&mut command_queue,
|
||||
textures,
|
||||
render_resource_context,
|
||||
entities_waiting_for_assets,
|
||||
&mut renderable.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
|
@ -554,19 +559,20 @@ where
|
|||
.read_resource::<Assets<T>>()
|
||||
.read_resource::<Assets<Texture>>()
|
||||
.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
|
||||
.with_query(<(Read<Handle<T>>, Read<Renderable>)>::query())
|
||||
.with_query(<(Read<Handle<T>>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_,
|
||||
world,
|
||||
(assets, textures, render_resources),
|
||||
(assets, textures, render_resources, entities_waiting_for_assets),
|
||||
(read_handle_query, write_handle_query)| {
|
||||
let render_resource_context = &*render_resources.context;
|
||||
uniform_buffer_arrays.reset_new_item_counts();
|
||||
|
||||
// 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 {
|
||||
return;
|
||||
}
|
||||
|
@ -574,11 +580,12 @@ where
|
|||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
// TODO: only increment count if we haven't seen this uniform handle before
|
||||
uniform_buffer_arrays.increment_uniform_counts(&uniforms);
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
// TODO: only increment count if we haven't seen this uniform handle before
|
||||
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);
|
||||
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 {
|
||||
return;
|
||||
}
|
||||
|
@ -594,16 +603,17 @@ where
|
|||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
setup_uniform_texture_resources::<T>(
|
||||
&uniforms,
|
||||
&mut command_queue,
|
||||
textures,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
)
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
setup_uniform_texture_resources::<T>(
|
||||
entity,
|
||||
&uniforms,
|
||||
&mut command_queue,
|
||||
textures,
|
||||
render_resource_context,
|
||||
entities_waiting_for_assets,
|
||||
&mut renderable.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if staging_buffer_size == 0 {
|
||||
|
@ -615,17 +625,16 @@ where
|
|||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -643,17 +652,16 @@ where
|
|||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -684,10 +692,12 @@ where
|
|||
}
|
||||
|
||||
fn setup_uniform_texture_resources<T>(
|
||||
entity: Entity,
|
||||
uniforms: &T,
|
||||
command_queue: &mut CommandQueue,
|
||||
textures: &Assets<Texture>,
|
||||
render_resource_context: &dyn RenderResourceContext,
|
||||
entities_waiting_for_assets: &EntitiesWaitingForAssets,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
) where
|
||||
T: AsUniforms,
|
||||
|
@ -709,48 +719,49 @@ fn setup_uniform_texture_resources<T>(
|
|||
.unwrap(),
|
||||
),
|
||||
None => {
|
||||
let texture = textures.get(&texture_handle).unwrap();
|
||||
if let Some(texture) = textures.get(&texture_handle) {
|
||||
let texture_descriptor: TextureDescriptor = texture.into();
|
||||
let texture_resource =
|
||||
render_resource_context.create_texture(texture_descriptor);
|
||||
let texture_buffer = render_resource_context.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&texture.data,
|
||||
);
|
||||
// TODO: bytes_per_row could be incorrect for some texture formats
|
||||
command_queue.copy_buffer_to_texture(
|
||||
texture_buffer,
|
||||
0,
|
||||
(4 * texture.width) as u32,
|
||||
texture_resource,
|
||||
[0, 0, 0],
|
||||
0,
|
||||
0,
|
||||
texture_descriptor.size.clone(),
|
||||
);
|
||||
command_queue.free_buffer(texture_buffer);
|
||||
|
||||
let texture_descriptor: TextureDescriptor = texture.into();
|
||||
let texture_resource =
|
||||
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(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&texture.data,
|
||||
);
|
||||
// TODO: bytes_per_row could be incorrect for some texture formats
|
||||
command_queue.copy_buffer_to_texture(
|
||||
texture_buffer,
|
||||
0,
|
||||
(4 * texture.width) as u32,
|
||||
texture_resource,
|
||||
[0, 0, 0],
|
||||
0,
|
||||
0,
|
||||
texture_descriptor.size.clone(),
|
||||
);
|
||||
command_queue.free_buffer(texture_buffer);
|
||||
let sampler_descriptor: SamplerDescriptor = texture.into();
|
||||
let sampler_resource =
|
||||
render_resource_context.create_sampler(&sampler_descriptor);
|
||||
|
||||
let sampler_descriptor: SamplerDescriptor = texture.into();
|
||||
let sampler_resource =
|
||||
render_resource_context.create_sampler(&sampler_descriptor);
|
||||
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
texture_resource,
|
||||
0,
|
||||
);
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
sampler_resource,
|
||||
1,
|
||||
);
|
||||
(texture_resource, sampler_resource)
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
texture_resource,
|
||||
0,
|
||||
);
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
sampler_resource,
|
||||
1,
|
||||
);
|
||||
(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 entity_render_resource_assignments;
|
||||
mod entities_waiting_for_assets;
|
||||
mod render_resource;
|
||||
mod render_resource_assignments;
|
||||
mod resource_info;
|
||||
|
@ -7,6 +8,7 @@ pub mod resource_name;
|
|||
|
||||
pub use buffer::*;
|
||||
pub use entity_render_resource_assignments::*;
|
||||
pub use entities_waiting_for_assets::*;
|
||||
pub use render_resource::*;
|
||||
pub use render_resource_assignments::*;
|
||||
pub use resource_info::*;
|
||||
|
|
|
@ -2,8 +2,10 @@ mod sampler_descriptor;
|
|||
mod texture;
|
||||
mod texture_descriptor;
|
||||
mod texture_dimension;
|
||||
mod png_texture_loader;
|
||||
|
||||
pub use sampler_descriptor::*;
|
||||
pub use texture::*;
|
||||
pub use texture_descriptor::*;
|
||||
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,10 +25,11 @@ pub fn sprite_system() -> Box<dyn Schedulable> {
|
|||
for (sprite, handle, mut rect) in query.iter_mut(world) {
|
||||
let material = materials.get(&handle).unwrap();
|
||||
if let Some(texture_handle) = material.texture {
|
||||
let texture = textures.get(&texture_handle).unwrap();
|
||||
let aspect = texture.aspect();
|
||||
*rect.size.x_mut() = texture.width as f32 * sprite.scale;
|
||||
*rect.size.y_mut() = rect.size.x() * aspect;
|
||||
if let Some(texture) = textures.get(&texture_handle) {
|
||||
let aspect = texture.aspect();
|
||||
*rect.size.x_mut() = texture.width as f32 * sprite.scale;
|
||||
*rect.size.y_mut() = rect.size.x() * aspect;
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -557,7 +557,6 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
return Some(render_resource_set.id);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,10 @@ fn main() {
|
|||
|
||||
fn setup(
|
||||
command_buffer: &mut CommandBuffer,
|
||||
mut textures: ResMut<Assets<Texture>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||
) {
|
||||
let texture = Texture::load(TextureType::Png("assets/branding/icon.png".to_string()));
|
||||
let texture_handle = textures.add(texture);
|
||||
|
||||
let texture_handle = asset_server.load("assets/branding/icon.png").unwrap();
|
||||
command_buffer
|
||||
.build()
|
||||
.add_entity(Camera2dEntity::default())
|
||||
|
|
|
@ -10,16 +10,15 @@ fn main() {
|
|||
/// sets up a scene with textured entities
|
||||
fn setup(
|
||||
command_buffer: &mut CommandBuffer,
|
||||
asset_server: Res<AssetServer>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
mut textures: ResMut<Assets<Texture>>,
|
||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||
) {
|
||||
// load a texture
|
||||
let texture = Texture::load(TextureType::Png(
|
||||
"assets/branding/bevy_logo_dark_big.pn".to_string(),
|
||||
));
|
||||
let texture_handle = asset_server.load_sync(&mut textures, "assets/branding/bevy_logo_dark_big.png").unwrap();
|
||||
let texture = textures.get(&texture_handle).unwrap();
|
||||
let aspect = texture.aspect();
|
||||
let texture_handle = textures.add(texture);
|
||||
|
||||
// create a new quad mesh. this is what we will apply the texture to
|
||||
let quad_width = 8.0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#[cfg(feature = "asset")]
|
||||
pub use crate::asset::{AddAsset, AssetEvent, Assets, Handle};
|
||||
pub use crate::asset::{AddAsset, AssetEvent, Assets, Handle, AssetServer};
|
||||
#[cfg(feature = "core")]
|
||||
pub use crate::core::{
|
||||
time::Time,
|
||||
|
|
Loading…
Reference in a new issue