use crate::{
fyrox::{
asset::untyped::ResourceKind,
core::{algebra::Matrix4, math::Matrix4Ext, pool::Handle, sstorage::ImmutableString, Uuid},
graphics::{
buffer::BufferUsage, error::FrameworkError, geometry_buffer::GpuGeometryBuffer,
server::GraphicsServer,
},
renderer::{
cache::shader::{
binding, property, PropertyGroup, RenderMaterial, RenderPassContainer,
},
framework::GeometryBufferExt,
RenderPassStatistics, SceneRenderPass, SceneRenderPassContext,
},
resource::texture::{
CompressionOptions, TextureImportOptions, TextureMinificationFilter, TextureResource,
TextureResourceExtension,
},
scene::{mesh::surface::SurfaceData, Scene},
},
Editor,
};
use std::{any::TypeId, cell::RefCell, rc::Rc};
pub struct OverlayRenderPass {
quad: GpuGeometryBuffer,
shader: RenderPassContainer,
sound_icon: TextureResource,
light_icon: TextureResource,
pub pictogram_size: f32,
pub scene_handle: Handle<Scene>,
}
impl OverlayRenderPass {
pub fn new(server: &dyn GraphicsServer) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self {
quad: GpuGeometryBuffer::from_surface_data(
"Quad",
&SurfaceData::make_collapsed_xy_quad(),
BufferUsage::StaticDraw,
server,
)
.unwrap(),
shader: RenderPassContainer::from_str(
server,
include_str!("../resources/shaders/overlay.shader"),
)
.unwrap(),
sound_icon: TextureResource::load_from_memory(
Uuid::new_v4(),
ResourceKind::Embedded,
include_bytes!("../resources/sound_source.png"),
TextureImportOptions::default()
.with_compression(CompressionOptions::NoCompression)
.with_minification_filter(TextureMinificationFilter::Linear),
)
.unwrap(),
light_icon: TextureResource::load_from_memory(
Uuid::new_v4(),
ResourceKind::Embedded,
include_bytes!("../resources/light_source.png"),
TextureImportOptions::default()
.with_compression(CompressionOptions::NoCompression)
.with_minification_filter(TextureMinificationFilter::Linear),
)
.unwrap(),
pictogram_size: 0.33,
scene_handle: Default::default(),
}))
}
}
impl SceneRenderPass for OverlayRenderPass {
fn on_hdr_render(
&mut self,
ctx: SceneRenderPassContext,
) -> Result<RenderPassStatistics, FrameworkError> {
let mut stats = RenderPassStatistics::default();
if ctx.scene_handle != self.scene_handle {
return Ok(stats);
}
let view_projection = ctx.observer.position.view_projection_matrix;
let inv_view = ctx.observer.position.view_matrix.try_inverse().unwrap();
let camera_up = -inv_view.up();
let camera_side = inv_view.side();
let sound_icon = ctx
.texture_cache
.get(ctx.server, ctx.resource_manager, &self.sound_icon)
.cloned()
.unwrap();
let light_icon = ctx
.texture_cache
.get(ctx.server, ctx.resource_manager, &self.light_icon)
.unwrap();
for node in ctx.scene.graph.linear_iter() {
let icon =
if node.is_directional_light() || node.is_spot_light() || node.is_point_light() {
light_icon.clone()
} else if node.is_sound() {
sound_icon.clone()
} else {
continue;
};
let position = node.global_position();
let world_matrix = Matrix4::new_translation(&position);
let properties = PropertyGroup::from([
property("viewProjectionMatrix", &view_projection),
property("worldMatrix", &world_matrix),
property("cameraSideVector", &camera_side),
property("cameraUpVector", &camera_up),
property("size", &self.pictogram_size),
]);
let material = RenderMaterial::from([
binding("diffuseTexture", (&icon.gpu_texture, &icon.gpu_sampler)),
binding("properties", &properties),
]);
stats += self.shader.run_pass(
1,
&ImmutableString::new("Primary"),
ctx.framebuffer,
&self.quad,
ctx.observer.viewport,
&material,
ctx.uniform_buffer_cache,
Default::default(),
None,
)?;
}
Ok(stats)
}
fn source_type_id(&self) -> TypeId {
TypeId::of::<Editor>()
}
}