diff options
Diffstat (limited to 'engine/src/renderer.rs')
| -rw-r--r-- | engine/src/renderer.rs | 317 |
1 files changed, 72 insertions, 245 deletions
diff --git a/engine/src/renderer.rs b/engine/src/renderer.rs index 68e8aed..bdbbe0c 100644 --- a/engine/src/renderer.rs +++ b/engine/src/renderer.rs @@ -3,40 +3,34 @@ use std::collections::VecDeque; use std::sync::atomic::{AtomicU64, Ordering}; use bitflags::bitflags; -use ecs::actions::Actions; use ecs::entity::obtainer::Obtainer as EntityObtainer; +use ecs::event::component::Changed; use ecs::pair::{ChildOf, Pair, Wildcard}; use ecs::phase::{POST_UPDATE as POST_UPDATE_PHASE, Phase}; -use ecs::query::term::{With, Without}; use ecs::sole::Single; +use ecs::system::observer::Observe; use ecs::uid::Uid; use ecs::{Component, Query, Sole, declare_entity}; -use crate::asset::{Assets, Handle as AssetHandle}; +use crate::asset::Handle as AssetHandle; use crate::builder; use crate::data_types::dimens::Dimens; -use crate::draw_flags::{DrawFlags, NoDraw, PolygonModeConfig}; +use crate::draw_flags::PolygonModeConfig; use crate::mesh::Mesh; -use crate::model::{MaterialSearchResult, Model}; use crate::renderer::blending::Config as BlendingConfig; -use crate::renderer::object::{Id as ObjectId, Store as ObjectStore}; +use crate::renderer::object::Id as ObjectId; +use crate::shader::Program as ShaderProgram; use crate::shader::cursor::{ BindingLocation as ShaderBindingLocation, BindingValue as ShaderBindingValue, Cursor as ShaderCursor, }; -use crate::shader::default::ASSET_LABEL as DEFAULT_SHADER_ASSET_LABEL; -use crate::shader::{ - Context as ShaderContext, - ModuleSource as ShaderModuleSource, - Program as ShaderProgram, - Shader, -}; -use crate::texture::{Texture, WHITE_1X1_ASSET_LABEL as TEXTURE_WHITE_1X1_ASSET_LABEL}; +use crate::texture::Texture; use crate::vector::Vec2; use crate::windowing::window::Window; pub mod blending; +pub mod main_render_pass; pub mod object; pub mod opengl; @@ -64,6 +58,11 @@ declare_entity!( ) ); +declare_entity!( + pub POST_RENDER_PHASE, + (Phase, Pair::builder().relation::<ChildOf>().target_id(*RENDER_PHASE).build()) +); + builder! { /// Window graphics properties. #[builder(name=GraphicsPropertiesBuilder, derives=(Debug, Clone))] @@ -191,8 +190,14 @@ pub enum Command mesh: Mesh, usage: MeshUsage, }, + RemoveMesh(ObjectId), DrawMesh(ObjectId, DrawMeshOptions), UpdateDrawProperties(DrawProperties, DrawPropertiesUpdateFlags), + SetViewport + { + size: Dimens<u32>, + position: Vec2<u32>, + }, } builder! { @@ -354,237 +359,6 @@ pub struct WindowUsingRendererCtx; #[derive(Debug, Component)] pub struct CtxUsedByWindow; -type RenderableEntity<'a> = ( - &'a Model, - Option<&'a DrawFlags>, - Option<&'a Shader>, - Option<&'a mut PendingShaderBindings>, -); - -#[tracing::instrument(skip_all)] -pub fn add_main_render_passes( - renderer_ctx_query: Query< - (&ObjectStore, &[Pair<CtxUsedByWindow, Wildcard>]), - (With<CommandQueue>,), - >, - renderable_query: Query<RenderableEntity<'_>, (Without<NoDraw>,)>, - assets: Single<Assets>, - shader_context: Single<ShaderContext>, - mut render_passes: Single<RenderPasses>, - mut actions: Actions, -) -{ - let Some(default_shader_asset) = assets - .get_handle_to_loaded::<ShaderModuleSource>(DEFAULT_SHADER_ASSET_LABEL.clone()) - else { - tracing::error!("Default shader asset is not loaded"); - return; - }; - - for (renderer_ctx_ent_id, (object_store, used_by_windows)) in - renderer_ctx_query.iter_with_euids() - { - for ctx_used_by_window in used_by_windows { - let window_ent_id = ctx_used_by_window.id().target_entity(); - - let Some(window_ent) = ctx_used_by_window.get_target_ent() else { - tracing::error!("Window entity does not exist"); - continue; - }; - - if window_ent.get::<Window>().is_none() { - tracing::debug!( - window_entity_id=%window_ent_id, - "Window entity does not have a {} component", - type_name::<Window>() - ); - - actions.remove_components( - renderer_ctx_ent_id, - [Pair::builder() - .relation::<CtxUsedByWindow>() - .target_id(window_ent_id) - .build() - .id()], - ); - - continue; - }; - - let Some(surface_spec) = window_ent.get::<SurfaceSpec>() else { - tracing::debug!( - window_entity_id=%window_ent_id, - "Window entity does not have a {} component", - type_name::<SurfaceSpec>() - ); - continue; - }; - - render_passes.passes.push_front(RenderPass { - renderer_ctx_ent_id, - surface_id: surface_spec.id, - commands: Vec::with_capacity(30), - draw_properties: DrawProperties::default(), - }); - - let render_pass = render_passes.passes.front_mut().expect("Not possible"); - - render_pass - .commands - .push(Command::MakeCurrent(surface_spec.id)); - - let default_texture_asset = assets - .get_handle_to_loaded::<Texture>(TEXTURE_WHITE_1X1_ASSET_LABEL.clone()) - .expect("Not possible"); - - if !object_store - .contains_with_id(&ObjectId::Asset(default_texture_asset.id())) - { - render_pass - .commands - .push(Command::CreateTexture(default_texture_asset)); - } - - render_pass.commands.push(Command::ClearBuffers( - BufferClearMask::COLOR | BufferClearMask::DEPTH, - )); - - for (model, draw_flags, shader, mut pending_shader_bindings) in - &renderable_query - { - let shader_asset = match &shader { - Some(shader) => &shader.asset_handle, - None => &default_shader_asset, - }; - - if pending_shader_bindings.as_ref().map_or_else( - || true, - |pending_shader_bindings| pending_shader_bindings.bindings.is_empty(), - ) { - continue; - } - - let Some(model_spec) = assets.get(&model.spec_asset) else { - continue; - }; - - let Some(mesh_asset) = &model_spec.mesh_asset else { - continue; - }; - - if assets.get(mesh_asset).is_none() { - continue; - } - - debug_assert!(model_spec.material_names.len() <= 1); - - let model_material_asset = match model_spec.find_first_material(&assets) { - MaterialSearchResult::Found(model_material_asset) => { - model_material_asset.clone() - // Some(model_material_asset.clone()) - } - MaterialSearchResult::NotFound - | MaterialSearchResult::NoMaterials => { - // MaterialSearchResult::NotFound => { - continue; - } // MaterialSearchResult::NoMaterials => None, - }; - - if !object_store.contains_with_id(&ObjectId::Asset(shader_asset.id())) { - let Some(shader_program) = - shader_context.get_program(&shader_asset.id()) - else { - tracing::error!( - "Shader context doesn't have a program for shader asset {:?}", - assets.get_label(&shader_asset) - ); - continue; - }; - - render_pass.commands.push(Command::CreateShaderProgram( - ObjectId::Asset(shader_asset.id()), - shader_program.clone(), - )); - } - - render_pass - .commands - .push(Command::ActivateShader(ObjectId::Asset(shader_asset.id()))); - - let Some(model_material) = assets.get(&model_material_asset) else { - // TODO: Handle this case since it may occur - unreachable!(); - }; - - for texture_asset in [ - &model_material.ambient_map, - &model_material.diffuse_map, - &model_material.specular_map, - ] - .into_iter() - .flatten() - { - if !object_store - .contains_with_id(&ObjectId::Asset(texture_asset.id())) - { - render_pass - .commands - .push(Command::CreateTexture(texture_asset.clone())); - } - } - - if let Some(pending_shader_bindings) = &mut pending_shader_bindings { - for (shader_binding_loc, shader_binding_val) in - pending_shader_bindings.bindings.drain(..) - { - render_pass.commands.push(Command::SetShaderBinding( - shader_binding_loc, - shader_binding_val, - )); - } - } - - if let Some(draw_flags) = draw_flags.as_deref() - && draw_flags.polygon_mode_config != PolygonModeConfig::default() - { - render_pass.commands.push(Command::UpdateDrawProperties( - DrawProperties { - polygon_mode_config: draw_flags.polygon_mode_config.clone(), - ..Default::default() - }, - DrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG, - )); - } - - if !object_store.contains_with_id(&ObjectId::Asset(mesh_asset.id())) { - render_pass.commands.push(Command::CreateMesh { - obj_id: ObjectId::Asset(mesh_asset.id()), - mesh: None, - usage: MeshUsage::Static, - }); - } - - render_pass.commands.push(Command::DrawMesh( - ObjectId::Asset(mesh_asset.id()), - DrawMeshOptions::default(), - )); - - if let Some(draw_flags) = draw_flags.as_deref() - && draw_flags.polygon_mode_config != PolygonModeConfig::default() - { - render_pass.commands.push(Command::UpdateDrawProperties( - DrawProperties { - polygon_mode_config: PolygonModeConfig::default(), - ..Default::default() - }, - DrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG, - )); - } - } - } - } -} - #[tracing::instrument(skip_all)] pub fn enqueue_commands_from_render_passes( renderer_ctx_query: Query<( @@ -678,6 +452,59 @@ pub fn enqueue_commands_from_render_passes( } } +#[tracing::instrument(skip_all)] +fn handle_window_changed( + observe: Observe<Pair<Changed, Window>>, + entity_obtainer: EntityObtainer, +) +{ + for evt_match in &observe { + let window_ent = evt_match.get_ent_infallible(); + + let Some(window_surface_spec) = window_ent.get::<SurfaceSpec>() else { + continue; + }; + + let Some(renderer_ctx_ent_id) = window_ent + .get_matching_components( + Pair::builder() + .relation::<WindowUsingRendererCtx>() + .target_id(Wildcard::uid()) + .build() + .id(), + ) + .next() + .map(|comp_ref| comp_ref.id().target_entity()) + else { + continue; + }; + + let Some(renderer_ctx_ent) = entity_obtainer.get_entity(renderer_ctx_ent_id) + else { + tracing::error!("Renderer context entity does not exist"); + continue; + }; + + let Some(mut command_queue) = renderer_ctx_ent.get_mut::<CommandQueue>() else { + tracing::error!( + "Renderer context entity does not have a {} component", + type_name::<CommandQueue>() + ); + continue; + }; + + command_queue.queue.push_front(Command::SetViewport { + position: Vec2 { x: 0, y: 0 }, + size: *evt_match.get_changed_comp().inner_size(), + }); + + command_queue + .queue + .push_front(Command::MakeCurrent(window_surface_spec.id)); + } +} + +// TODO: Maybe move this struct to somewhere more appropriate #[derive(Default, Clone, Component)] pub struct PendingShaderBindings { |
