text: immediate-mode atlased text rendering works, but theres no character positioning/layout yet

This commit is contained in:
Carter Anderson 2020-06-19 13:45:26 -07:00
parent a3c1b7930e
commit da3d6983a7
5 changed files with 95 additions and 56 deletions

View file

@ -126,7 +126,6 @@ pub struct DrawContext<'a> {
pub pipeline_compiler: ResMut<'a, PipelineCompiler>,
pub render_resource_context: Res<'a, Box<dyn RenderResourceContext>>,
pub vertex_buffer_descriptors: Res<'a, VertexBufferDescriptors>,
pub asset_render_resource_bindings: Res<'a, AssetRenderResourceBindings>,
pub shared_buffers: Res<'a, SharedBuffers>,
pub current_pipeline: Option<Handle<PipelineDescriptor>>,
}
@ -145,12 +144,6 @@ impl<'a> ResourceSet for DrawContext<'a> {
resources.get::<VertexBufferDescriptors>().unwrap().deref()
as *const VertexBufferDescriptors,
),
asset_render_resource_bindings: Res::new(
resources
.get::<AssetRenderResourceBindings>()
.unwrap()
.deref() as *const AssetRenderResourceBindings,
),
shared_buffers: Res::new(
resources.get::<SharedBuffers>().unwrap().deref() as *const SharedBuffers
),
@ -277,6 +270,26 @@ impl<'a> DrawContext<'a> {
Ok(())
}
pub fn create_bind_group_resource(
&self,
index: u32,
bind_group: &BindGroup,
) -> Result<(), DrawError> {
let pipeline = self
.current_pipeline
.ok_or_else(|| DrawError::NoPipelineSet)?;
let pipeline_descriptor = self
.pipelines
.get(&pipeline)
.ok_or_else(|| DrawError::NonExistentPipeline)?;
let layout = pipeline_descriptor
.get_layout()
.ok_or_else(|| DrawError::PipelineHasNoLayout)?;
let bind_group_descriptor = &layout.bind_groups[index as usize];
self.render_resource_context.create_bind_group(bind_group_descriptor.id, bind_group);
Ok(())
}
pub fn set_vertex_buffers_from_bindings(
&self,
draw: &mut Draw,

View file

@ -1,13 +1,17 @@
use crate::{Font, FontAtlasSet};
use bevy_asset::Assets;
use bevy_render::{
draw::{DrawContext, DrawError, Drawable, Draw},
draw::{Draw, DrawContext, DrawError, Drawable},
mesh,
render_resource::{BindGroup, BufferUsage, RenderResourceId},
Color, pipeline::PipelineSpecialization,
pipeline::PipelineSpecialization,
render_resource::{
AssetRenderResourceBindings, BindGroup, BufferUsage, RenderResourceBindings,
RenderResourceId,
},
Color,
};
use bevy_sprite::{TextureAtlas, TextureAtlasSprite};
use glam::{Vec2, Vec3};
use glam::Vec3;
pub struct TextStyle {
pub font_size: f32,
@ -19,7 +23,9 @@ pub struct DrawableText<'a> {
font: &'a Font,
font_atlas_set: &'a FontAtlasSet,
texture_atlases: &'a Assets<TextureAtlas>,
position: Vec2,
render_resource_bindings: &'a mut RenderResourceBindings,
asset_render_resource_bindings: &'a mut AssetRenderResourceBindings,
position: Vec3,
style: &'a TextStyle,
text: &'a str,
}
@ -29,7 +35,9 @@ impl<'a> DrawableText<'a> {
font: &'a Font,
font_atlas_set: &'a FontAtlasSet,
texture_atlases: &'a Assets<TextureAtlas>,
position: Vec2,
render_resource_bindings: &'a mut RenderResourceBindings,
asset_render_resource_bindings: &'a mut AssetRenderResourceBindings,
position: Vec3,
style: &'a TextStyle,
text: &'a str,
) -> Self {
@ -37,6 +45,8 @@ impl<'a> DrawableText<'a> {
font,
font_atlas_set,
texture_atlases,
render_resource_bindings,
asset_render_resource_bindings,
position,
style,
text,
@ -46,7 +56,12 @@ impl<'a> DrawableText<'a> {
impl<'a> Drawable for DrawableText<'a> {
fn draw(&mut self, draw: &mut Draw, context: &mut DrawContext) -> Result<(), DrawError> {
context.set_pipeline(draw, bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE, PipelineSpecialization::empty())?;
context.set_pipeline(
draw,
bevy_sprite::SPRITE_SHEET_PIPELINE_HANDLE,
PipelineSpecialization::empty(),
)?;
let render_resource_context = &**context.render_resource_context;
if let Some(RenderResourceId::Buffer(quad_vertex_buffer)) = render_resource_context
.get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::VERTEX_BUFFER_ASSET_INDEX)
@ -58,17 +73,16 @@ impl<'a> Drawable for DrawableText<'a> {
.get_asset_resource(bevy_sprite::QUAD_HANDLE, mesh::INDEX_BUFFER_ASSET_INDEX)
{
draw.set_index_buffer(quad_index_buffer, 0);
if let Some(buffer_info) = render_resource_context
.get_buffer_info(quad_index_buffer)
{
if let Some(buffer_info) = render_resource_context.get_buffer_info(quad_index_buffer) {
indices = 0..(buffer_info.size / 2) as u32;
} else {
panic!("expected buffer type");
}
}
let current_position = Vec3::new(0.0, 0.0, 0.0);
// set global bindings
// context.set_bind_groups_from_bindings(draw, &mut[context.render_resource_bindings])?;
context.set_bind_groups_from_bindings(draw, &mut [self.render_resource_bindings])?;
// set local per-character bindings
for character in self.text.chars() {
@ -76,21 +90,24 @@ impl<'a> Drawable for DrawableText<'a> {
.font_atlas_set
.get_glyph_atlas_info(self.style.font_size, character)
{
// let atlas_render_resource_bindings = context
// .asset_render_resource_bindings
// .get_mut(glyph_atlas_info.texture_atlas)
// .unwrap();
// context.set_bind_groups_from_bindings(draw, &mut[atlas_render_resource_bindings])?;
let atlas_render_resource_bindings = self
.asset_render_resource_bindings
.get_mut(glyph_atlas_info.texture_atlas)
.unwrap();
context
.set_bind_groups_from_bindings(draw, &mut [atlas_render_resource_bindings])?;
let sprite_buffer = TextureAtlasSprite {
index: glyph_atlas_info.char_index,
position: Vec3::new(300.0, 300.0, 0.0),
scale: 5.0,
position: current_position,
scale: 1.0,
};
let sprite_buffer = context
.shared_buffers
.get_buffer(&sprite_buffer, BufferUsage::UNIFORM)
.unwrap();
let sprite_bind_group = BindGroup::build().add_binding(0, sprite_buffer).finish();
context.create_bind_group_resource(2, &sprite_bind_group)?;
draw.set_bind_group(2, &sprite_bind_group);
draw.draw_indexed(indices.clone(), 0, 0..1);
}

View file

@ -1,8 +1,14 @@
use bevy_asset::{Assets, Handle};
use bevy_render::{draw::{DrawContext, Draw}, texture::Texture, Color};
use bevy_render::{
draw::{Draw, DrawContext, Drawable},
render_resource::{AssetRenderResourceBindings, RenderResourceBindings},
texture::Texture,
Color,
};
use bevy_sprite::{ColorMaterial, ComMut, Quad, TextureAtlas};
use bevy_text::{Font, FontAtlasSet, TextStyle};
use bevy_text::{DrawableText, Font, FontAtlasSet, TextStyle};
use legion::prelude::{Com, Res, ResMut};
use glam::Vec3;
pub struct Label {
pub text: String,
@ -51,6 +57,11 @@ impl Label {
label.style.font_size,
&label.text,
);
let material = color_materials.get_or_insert_with(*color_material_handle, || {
ColorMaterial::from(Handle::<Texture>::new())
});
let texture = font.render_text(
&label.text,
label.style.color,
@ -59,36 +70,33 @@ impl Label {
height as usize,
);
let material = color_materials.get_or_insert_with(*color_material_handle, || {
ColorMaterial::from(Handle::<Texture>::new())
});
if let Some(texture_handle) = material.texture {
textures.set(texture_handle, texture);
} else {
material.texture = Some(textures.add(texture));
}
material.texture = Some(textures.add(texture));
}
}
pub fn draw_label_system(
mut _draw_context: DrawContext,
_fonts: Res<Assets<Font>>,
_font_atlas_sets: Res<Assets<FontAtlasSet>>,
_texture_atlases: Res<Assets<TextureAtlas>>,
mut _draw: ComMut<Draw>,
_label: Com<Label>,
_quad: Com<Quad>,
mut draw_context: DrawContext,
fonts: Res<Assets<Font>>,
font_atlas_sets: Res<Assets<FontAtlasSet>>,
texture_atlases: Res<Assets<TextureAtlas>>,
mut render_resource_bindings: ResMut<RenderResourceBindings>,
mut asset_render_resource_bindings: ResMut<AssetRenderResourceBindings>,
mut draw: ComMut<Draw>,
label: Com<Label>,
quad: Com<Quad>,
) {
// let mut drawable_text = DrawableText::new(
// fonts.get(&label.font).unwrap(),
// font_atlas_sets
// .get(&label.font.as_handle::<FontAtlasSet>())
// .unwrap(),
// &texture_atlases,
// quad.position,
// &label.style,
// &label.text,
// );
// drawable_text.draw(&mut draw, &mut draw_context).unwrap();
let mut drawable_text = DrawableText::new(
fonts.get(&label.font).unwrap(),
font_atlas_sets
.get(&label.font.as_handle::<FontAtlasSet>())
.unwrap(),
&texture_atlases,
&mut render_resource_bindings,
&mut asset_render_resource_bindings,
Vec3::new(quad.position.x(), quad.position.y(), 0.0),
&label.style,
&label.text,
);
drawable_text.draw(&mut draw, &mut draw_context).unwrap();
}
}

View file

@ -37,11 +37,11 @@ fn atlas_render_system(
return;
}
if let Some(set) = font_atlas_sets.get(&state.handle.as_handle::<FontAtlasSet>()) {
for (_size, atlas) in set.iter() {
for (_size, font_atlas) in set.iter() {
state.added = true;
let atlas = texture_atlases.get(&atlas.texture_atlas).unwrap();
let texture_atlas = texture_atlases.get(&font_atlas.texture_atlas).unwrap();
command_buffer.build().add_entity(SpriteEntity {
material: materials.add(atlas.texture.into()),
material: materials.add(texture_atlas.texture.into()),
quad: Quad {
position: Vec2::new(-300.0, 0.),
..Default::default()

View file

@ -25,6 +25,7 @@ fn setup(command_buffer: &mut CommandBuffer, asset_server: Res<AssetServer>) {
command_buffer
.build()
// 2d camera
.add_entity(OrthographicCameraEntity::default())
.add_entity(OrthographicCameraEntity::ui())
// texture
.add_entity(LabelEntity {