#[macro_use] mod material;
pub mod light;
mod renderer;
pub mod components;
pub mod shadow;
pub mod geometry;
mod camera;
pub mod resources;
mod transformation;
mod depth_prepass;
pub mod memory;
#[cfg(not(feature="gl_continuous_allocator"))]
pub mod individual_allocator;
#[cfg(not(feature="gl_continuous_allocator"))]
pub use individual_allocator as allocator;
#[cfg(feature="gl_continuous_allocator")]
pub mod allocator;
pub use self::material::{
MaterialCache, MaterialPool, ShadowMaterialPool, ShadowMaterialCache,
Material, FullMaterial, PostFragmentMaterial, PostFragmentMaterialBuilder,
MaterialTransparency, PropertyChanged, ProgramSettings, PostFragment,
Materials, ToGlinShaderPrecision,
ProgramCache, TexturesPool,
ShaderMaterial, ShaderMaterialBuilder, Image, std140_data,
UBOBindingPoints
};
#[cfg(image_enabled)]
pub use self::material::water;
pub use self::light::{
ImageBasedLightBuilder
};
pub use self::shadow::ShadowMapPool;
pub use self::resources::{
ScreenRenderBuffer, ScreenRenderBufferBuilder,
};
pub use self::memory::Allocator;
use std::collections::HashMap;
use rinecs::{EntitiesThreadLocal, ResourcesThreadLocal, SystemThreadLocal, World, system_thread_local};
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Debug;
use crate::DeferredScene;
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
use rin_window::{self as window, WindowExt, Events, WindowEvents};
use rin_events::{Property, Stream, StreamExt};
use rin_math::{Pnt2, Rect};
use rin_gl as gl;
use renderer::RendererType;
#[cfg(feature="gui")]
use rin_gui::ParameterGroup;
use self::resources::ScreenRenderBufferStaticBuilder;
pub fn default_attribute_bindings() -> rin_gl::HashMap<String, u32>{
rin_gl::hash_map![
"position".to_string() => 0,
"color".to_string() => 1,
"texcoord".to_string() => 2,
"normal".to_string() => 3,
"material_offset".to_string() => 4,
"model_matrix".to_string() => 5,
"normal_atrix".to_string() => 9,
]
}
pub type OpaqueRenderSurface<'a> = glin::Fbo<Rc<glin::fbo::ColorAttachment>, Rc<glin::fbo::DepthAttachment>>;
pub type OtherRenderSurface<'a> = glin::Fbo<&'a glin::fbo::ColorAttachment, &'a glin::fbo::DepthAttachment>;
pub enum AttributeBufferIndex{
Vertex = 0,
Matrices = 1,
MaterialOffsets = 2,
}
#[cfg(feature="gles")]
pub(crate) const fn default_glsl_version() -> usize{
300
}
#[cfg(feature="webgl")]
pub(crate) const fn default_glsl_version() -> usize{
300
}
#[cfg(not(any(feature="gles", feature="webgl")))]
pub(crate) const fn default_glsl_version() -> usize{
410
}
pub(crate) const fn use_model_as_attribute() -> bool{
true
}
pub struct ForwardRendererBuilder{
renderer: gl::Renderer<'static>,
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
window: window::Window,
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
impl ForwardRendererBuilder {
pub fn new(renderer: gl::Renderer<'static>, window: window::Window) -> ForwardRendererBuilder {
ForwardRendererBuilder {
renderer,
window,
}
}
pub fn with_render_surface(mut self) -> ForwardRendererWithSurfaceBuilder {
ForwardRendererWithSurfaceBuilder {
render_surface_builder: ScreenRenderBufferStaticBuilder::new(
self.window.width() as u32,
self.window.height() as u32,
gl::fbo::ColorFormat::RGBA16F,
),
renderer: self.renderer,
window: self.window,
}
}
pub fn build(self) -> ForwardRenderer {
ForwardRenderer::new(self.renderer, self.window)
}
}
pub struct ForwardRendererWithSurfaceBuilder {
render_surface_builder: ScreenRenderBufferStaticBuilder,
renderer: gl::Renderer<'static>,
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
window: window::Window,
}
impl ForwardRendererWithSurfaceBuilder {
pub fn size(mut self, w: u32, h: u32) -> Self {
self.render_surface_builder.size(w, h);
self
}
pub fn color_format(mut self, format: gl::fbo::ColorFormat) -> Self {
self.render_surface_builder.color_format(format);
self
}
pub fn normals_buffer(mut self) -> Self{
self.render_surface_builder.normals_buffer();
self
}
pub fn position_buffer(mut self) -> Self{
self.render_surface_builder.position_buffer();
self
}
pub fn separate_ambient_buffer(mut self) -> Self{
self.render_surface_builder.separate_ambient_buffer();
self
}
pub fn linear_depth_buffer(mut self) -> Self{
self.render_surface_builder.linear_depth_buffer();
self
}
pub fn depth_format(mut self, depth_format: glin::fbo::DepthFormat) -> Self{
self.render_surface_builder.depth_format(depth_format);
self
}
pub fn disable_resolve_base_color(mut self) -> Self{
self.render_surface_builder.disable_resolve_base_color();
self
}
pub fn disable_normals_resolve(mut self) -> Self{
self.render_surface_builder.disable_normals_resolve();
self
}
pub fn disable_position_resolve(mut self) -> Self{
self.render_surface_builder.disable_position_resolve();
self
}
pub fn disable_separate_ambient_resolve(mut self) -> Self{
self.render_surface_builder.disable_separate_ambient_resolve();
self
}
pub fn disable_linear_depth_resolve(mut self) -> Self{
self.render_surface_builder.disable_linear_depth_resolve();
self
}
pub fn disable_depth_resolve(mut self) -> Self{
self.render_surface_builder.disable_depth_resolve();
self
}
pub fn samples(mut self, samples: u32) -> Self{
self.render_surface_builder.samples(samples);
self
}
pub fn depth_prepass(mut self) -> Self{
self.render_surface_builder.depth_prepass();
self
}
pub fn depth_as_texture(mut self) -> Self{
self.render_surface_builder.depth_as_texture();
self
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
pub fn build(mut self) -> rin_util::Result<ForwardRenderer> {
let render_surface = self.render_surface_builder
.build(&self.renderer)
.map_err(|err| rin_util::Error::with_cause("Can't create render surface", err))?;
let viewport = Property::new(render_surface.viewport().into());
let renderer_type = renderer::choose_renderer_type(&self.renderer);
let needs_indexing_hack = renderer::needs_indexing_hack(&self.renderer);
log::trace!("needs_indexing_hack: {}", needs_indexing_hack);
Ok(ForwardRenderer{
renderer: self.renderer,
window: self.window,
viewport,
render_surface: Some(render_surface),
program_cache: None,
#[cfg(not(any(feature = "webgl", feature = "gles")))]
use_unified_material_ubo: renderer_type == RendererType::MultiDrawIndirect,
renderer_type,
needs_indexing_hack,
parameters: Parameters::new(),
})
}
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
pub struct ForwardRenderer{
renderer: gl::Renderer<'static>,
window: window::Window,
render_surface: Option<ScreenRenderBuffer>,
viewport: Property<'static, Rect<i32>>,
program_cache: Option<material::ProgramCache>,
renderer_type: RendererType,
#[cfg(not(any(feature = "webgl", feature = "gles")))]
use_unified_material_ubo: bool,
needs_indexing_hack: bool,
parameters: Parameters,
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
impl ForwardRenderer{
pub fn new(renderer: gl::Renderer<'static>, mut window: window::Window) -> ForwardRenderer{
let viewport = window.event_stream().window().resized().map(|size| Rect{
pos: Pnt2::origin(),
width: size.x,
height: size.y,
}).to_property(window.viewport());
let renderer_type = renderer::choose_renderer_type(&renderer);
let needs_indexing_hack = renderer::needs_indexing_hack(&renderer);
log::trace!("needs_indexing_hack: {}", needs_indexing_hack);
ForwardRenderer{
renderer,
window,
viewport,
render_surface: None,
program_cache: None,
#[cfg(not(any(feature = "webgl", feature = "gles")))]
use_unified_material_ubo: renderer_type == RendererType::MultiDrawIndirect,
renderer_type,
needs_indexing_hack,
parameters: Parameters::new(),
}
}
pub fn new_with_render_surface(
renderer: gl::Renderer<'static>,
window: window::Window,
render_surface: ScreenRenderBuffer) -> ForwardRenderer
{
let viewport = Property::new(render_surface.viewport().into());
let renderer_type = renderer::choose_renderer_type(&renderer);
let needs_indexing_hack = renderer::needs_indexing_hack(&renderer);
log::trace!("needs_indexing_hack: {}", needs_indexing_hack);
ForwardRenderer{
renderer,
window,
viewport,
render_surface: Some(render_surface),
program_cache: None,
#[cfg(not(any(feature = "webgl", feature = "gles")))]
use_unified_material_ubo: renderer_type == RendererType::MultiDrawIndirect,
renderer_type,
needs_indexing_hack,
parameters: Parameters::new(),
}
}
pub fn set_program_cache(&mut self, cache: material::ProgramCache){
self.program_cache = Some(cache);
}
#[cfg(not(any(feature = "webgl", feature = "gles")))]
pub fn use_unified_material_ubo(&mut self){
self.use_unified_material_ubo = true;
}
fn into_resources(self, world: &mut DeferredScene) {
if let Some(render_surface) = self.render_surface {
world.add_resource_thread_local(render_surface);
}
let gl = &self.renderer;
let shadow_maps_pool = ShadowMapPool::new(gl);
let model_matrices_buffer = gl.new_shared_buffer().empty_target(gl::ARRAY_BUFFER).unwrap();
let static_matrices_buffer = gl.new_shared_buffer().empty_target(gl::ARRAY_BUFFER).unwrap();
let dynamic_matrices_buffer = gl.new_shared_buffer().empty_target(gl::ARRAY_BUFFER).unwrap();
let all_matrices_buffer = gl.new_shared_buffer().empty_target(gl::ARRAY_BUFFER).unwrap();
let camera_ubo = gl.new_buffer().empty_target(gl::UNIFORM_BUFFER).unwrap();
let lighting_ubo = gl.new_buffer().empty_target(gl::UNIFORM_BUFFER).unwrap();
#[cfg(not(any(feature = "webgl", feature = "gles")))]
let use_unified_material_ubo = self.use_unified_material_ubo;
#[cfg(any(feature = "webgl", feature = "gles"))]
let use_unified_material_ubo = false;
let deferred_vertex_register = DeferredVertexRegister::new(
&gl,
self.renderer_type,
use_unified_material_ubo);
let window = self.window;
let material_pool = MaterialPool::new(
use_unified_material_ubo,
world,
&self.renderer,
#[cfg(feature="gui")]
self.parameters.active_materials,
);
world.add_resource_thread_local(material_pool);
let shadow_material_pool = ShadowMaterialPool::new_shadows(
use_unified_material_ubo,
world,
&self.renderer,
#[cfg(feature="gui")]
self.parameters.active_shadow_materials
);
world.add_resource_thread_local(shadow_material_pool);
let needs_indexing_hack = self.needs_indexing_hack;
#[cfg(feature="gui")]
let active_programs = self.parameters.active_programs;
let program_cache = self.program_cache
.unwrap_or_else(|| ProgramCache::new(
use_unified_material_ubo,
needs_indexing_hack,
#[cfg(feature="gui")]
active_programs
));
world.add_resource_thread_local(program_cache);
world.add_resource_as_trait_thread_local(rinecs::cast!(window as dyn WindowExt));
world.add_resource_thread_local(resources::ModelMatricesBuffer(
model_matrices_buffer
));
world.add_resource_thread_local(resources::StaticModelMatricesBuffer(
static_matrices_buffer
));
world.add_resource_thread_local(resources::DynamicModelMatricesBuffer(
dynamic_matrices_buffer
));
world.add_resource_thread_local(resources::AllModelMatricesBuffer(
all_matrices_buffer
));
world.add_resource_thread_local(MaterialCache::new());
world.add_resource_thread_local(ShadowMaterialCache::new_shadows());
world.add_resource_thread_local(resources::CameraUBO{
ubo: camera_ubo,
reversed_z: false,
#[cfg(not(any(feature="webgl", feature="gles")))]
zero_to_one: false,
clamp_depth: false,
dirty: true,
});
world.add_resource_thread_local(resources::LightingUBO{
ubo: lighting_ubo,
dirty: true,
});
world.add_resource_thread_local(resources::LightingTextures::new());
world.add_resource(resources::LightData(std140_data::Data::default()));
world.add_resource(resources::ModelMatricesData{
data: vec![],
has_changed: true,
});
world.add_resource(resources::StaticModelMatricesData{
data: vec![],
has_changed: true,
});
world.add_resource(resources::DynamicModelMatricesData{
data: vec![],
has_changed: true,
});
world.add_resource(resources::AllModelMatricesData{
data: vec![],
has_changed: true,
});
#[cfg(not(any(feature = "webgl", feature = "gles")))]
if self.renderer_type == RendererType::MultiDrawIndirect {
world.add_resource(geometry::CommandBufferData::default());
world.add_resource(geometry::ShadowsCommandBufferData::default());
world.add_resource(geometry::StaticShadowsCommandBufferData::default());
world.add_resource(geometry::AllShadowsCommandBufferData::default());
let command_buffer = gl.new_buffer()
.empty_target(gl::DRAW_INDIRECT_BUFFER)
.unwrap();
let static_shadows_command_buffer = gl.new_buffer()
.empty_target(gl::DRAW_INDIRECT_BUFFER)
.unwrap();
let dynamic_shadows_command_buffer = gl.new_buffer()
.empty_target(gl::DRAW_INDIRECT_BUFFER)
.unwrap();
let all_shadows_command_buffer = gl.new_buffer()
.empty_target(gl::DRAW_INDIRECT_BUFFER)
.unwrap();
world.add_resource_thread_local(geometry::CommandBuffer(
command_buffer
));
world.add_resource_thread_local(geometry::ShadowsCommandBuffer(
dynamic_shadows_command_buffer
));
world.add_resource_thread_local(geometry::StaticShadowsCommandBuffer(
static_shadows_command_buffer
));
world.add_resource_thread_local(geometry::AllShadowsCommandBuffer(
all_shadows_command_buffer
));
}
world.add_resource_thread_local(self.renderer);
world.add_resource(resources::OpaqueSortedGeometry::new());
world.add_resource(resources::TranslucentSortedGeometry::new());
#[cfg(feature="debug_geometry")]
world.add_resource(resources::DebugSortedGeometry::new());
world.add_resource(resources::DynamicShadowsSortedGeometry::new());
world.add_resource(resources::StaticShadowsSortedGeometry::new());
world.add_resource(resources::AllShadowsSortedGeometry::new());
world.add_resource_thread_local(deferred_vertex_register);
world.add_resource_thread_local(shadow_maps_pool);
world.add_resource_thread_local(resources::GeometryWithModelsIndex(vec![]));
world.add_resource_thread_local(renderer::OpaqueInstances::new());
let depth_prepass = world.resource::<resources::ScreenRenderBuffer>()
.map(|s| s.depth_prepass().is_some())
.unwrap_or(false);
if depth_prepass {
world.add_resource(resources::DepthPrepass);
}
world.add_resource_thread_local(memory::AllocatorsIndex::new());
}
}
#[cfg_attr(feature="gui", derive(ParameterGroup))]
pub struct Parameters {
#[cfg_attr(feature="gui", gui(as_control = rin_gui::Label))]
#[cfg_attr(feature="gui", gui(style{
hide_label: false,
}))]
active_materials: Property<'static, usize>,
#[cfg_attr(feature="gui", gui(as_control = rin_gui::Label))]
#[cfg_attr(feature="gui", gui(style{
hide_label: false,
}))]
active_shadow_materials: Property<'static, usize>,
#[cfg_attr(feature="gui", gui(as_control = rin_gui::Label))]
#[cfg_attr(feature="gui", gui(style{
hide_label: false,
}))]
active_programs: Property<'static, usize>,
}
impl Parameters {
fn new() -> Parameters {
Parameters {
active_materials: Property::new(0),
active_shadow_materials: Property::new(0),
active_programs: Property::new(0),
}
}
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
impl crate::RendererBundle for ForwardRenderer{
type Parameters = Parameters;
fn parameters(&self) -> Option<&Parameters>{
Some(&self.parameters)
}
fn name(&self) -> &str {
"forward renderer"
}
fn setup(mut self, world: &mut DeferredScene){
let renderer_type = self.renderer_type;
#[cfg(not(any(feature = "webgl", feature = "gles")))]
let use_unified_material_ubo = self.use_unified_material_ubo;
#[cfg(any(feature = "webgl", feature = "gles"))]
let use_unified_material_ubo = false;
let viewport = self.viewport.clone();
let has_render_surface = self.render_surface.is_some();
let window_size = self.window.event_stream()
.window()
.resized()
.to_property(self.window.size());
self.into_resources(world);
world.add_system(crate::light::check_lights_changed_system);
world.add_system(geometry::geometryref_changed_updater);
world.add_system(geometry::update_visible_changed);
world.add_system(geometry::update_materialrefs_changed);
world.add_system_thread_local(camera::camera_ubo_updater);
world.add_system_thread_local(material::material_pool_updater);
world.add_system_thread_local(material::shadow_material_pool_updater);
world.add_system_thread_local(material::program_cache_updater);
world.add_creation_system(light::create_missing_light_matrices);
world.add_system_thread_local(light::update_lights_data);
world.add_system(geometry::geometry_sort);
world.add_system(geometry::dynamic_shadows_geometry_sort);
world.add_system(geometry::static_shadows_geometry_sort);
world.add_system(geometry::all_shadows_geometry_sort);
if use_unified_material_ubo{
world.add_system_thread_local(material::material_offsets_updater);
world.add_system_thread_local(material::shadow_material_offsets_updater);
}
#[cfg(not(any(feature = "webgl", feature = "gles")))]
if renderer_type == RendererType::MultiDrawIndirect {
world.add_system_thread_local(geometry::update_command_buffer_data);
world.add_system_thread_local(geometry::update_shadows_command_buffer_data);
world.add_system_thread_local(geometry::update_static_shadows_command_buffer_data);
world.add_system_thread_local(geometry::update_all_shadows_command_buffer_data);
}
world.add_system(transformation::generate_model_matrices_data);
world.add_system(transformation::generate_static_model_matrices_data);
world.add_system(transformation::generate_dynamic_model_matrices_data);
world.add_system(transformation::generate_all_model_matrices_data);
#[cfg(not(any(feature = "webgl", feature = "gles")))]
if renderer_type == RendererType::MultiDrawIndirect {
world.add_system_thread_local(geometry::upload_command_buffer);
world.add_system_thread_local(geometry::upload_shadows_command_buffer);
world.add_system_thread_local(geometry::upload_static_shadows_command_buffer);
world.add_system_thread_local(geometry::upload_all_shadows_command_buffer);
}
world.add_system_thread_local(transformation::update_model_matrices_gpu);
world.add_system_thread_local(transformation::update_static_model_matrices_gpu);
world.add_system_thread_local(transformation::update_dynamic_model_matrices_gpu);
world.add_system_thread_local(transformation::update_all_model_matrices_gpu);
shadow::create_shadow_maps_updater(world, renderer_type);
if world.resource::<resources::DepthPrepass>().is_some(){
log::trace!("Initializing gl with depth prepass");
depth_prepass::create_depth_prepass(world, renderer_type);
}
renderer::create_opaque_renderer(renderer_type, use_unified_material_ubo, world);
renderer::create_translucent_renderer(
renderer_type,
use_unified_material_ubo,
world);
if has_render_surface {
world.add_system_thread_local(renderer::BlitToScreenSystem::new(window_size));
#[cfg(feature="postprocessing")]
world.add_system_thread_local(renderer::ResolveIntermediateSurfaces::new());
world.add_system_thread_local(ViewportSender{ viewport });
}
#[cfg(feature="gl_persistent_map")]
world.add_system_with_name_thread_local(
geometry::update_regions::<crate::blender::Vertex>,
"update dyn geometry regions");
}
fn window(&self) -> Option<&window::Window>{
Some(&self.window)
}
fn window_mut(&mut self) -> Option<&mut window::Window>{
Some(&mut self.window)
}
fn viewport(&mut self) -> Property<'static, Rect<i32>>{
self.viewport.clone()
}
fn event_stream(&mut self) -> Stream<'static, window::Event>{
self.window.event_stream()
}
}
#[cfg(not(any(feature="gles", feature="webgl")))]
fn create_indices_storage(gl: &gl::Renderer) -> Rc<RefCell<allocator::Allocator<glin::SharedBufferStorage<u8>>>>{
let indices_allocator = allocator::Allocator::new_storage(&*gl, 1024,
memory::storage_static_flags(),
gl::ELEMENT_ARRAY_BUFFER)
.unwrap();
Rc::new(RefCell::new(indices_allocator))
}
fn create_indices_buffer(gl: &gl::Renderer) -> Rc<RefCell<allocator::Allocator<glin::SharedBuffer<u8>>>>{
let indices_allocator = allocator::Allocator::new_buffer(&*gl, 1024,
memory::buffer_static_usage(),
gl::ELEMENT_ARRAY_BUFFER)
.unwrap();
Rc::new(RefCell::new(indices_allocator))
}
pub enum IndicesAllocator{
#[cfg(not(any(feature="gles", feature="webgl")))]
Storage(Rc<RefCell<allocator::Allocator<glin::SharedBufferStorage<u8>>>>),
Buffer(Rc<RefCell<allocator::Allocator<glin::SharedBuffer<u8>>>>),
}
impl IndicesAllocator{
pub fn new(gl: &gl::Renderer) -> IndicesAllocator {
#[cfg(not(any(feature="gles", feature="webgl")))]
{
let supports_storage =
unsafe{ gl.context().gl().BufferStorage.is_loaded() };
if supports_storage {
IndicesAllocator::Storage(create_indices_storage(gl))
}else{
IndicesAllocator::Buffer(create_indices_buffer(gl))
}
}
#[cfg(any(feature="gles", feature="webgl"))]
IndicesAllocator::Buffer(create_indices_buffer(gl))
}
}
pub struct DeferredVertexRegister{
indices_allocator: IndicesAllocator,
renderer_type: RendererType,
use_unified_material_ubo: bool,
}
impl DeferredVertexRegister{
pub fn new(
gl: &gl::Renderer,
renderer_type: RendererType,
use_unified_material_ubo: bool) -> DeferredVertexRegister
{
DeferredVertexRegister{
indices_allocator: IndicesAllocator::new(gl),
renderer_type,
use_unified_material_ubo,
}
}
pub fn register_vertex_type<T>(&mut self, world: &mut World)
where T: glin::VertexFormat + Send + Clone + Copy + Debug + 'static
{
world.add_system(geometry::geometry_changed_updater::<T>::new());
match &self.indices_allocator{
#[cfg(not(any(feature="gles", feature="webgl")))]
IndicesAllocator::Storage(indices_allocator) => {
let uploader = geometry::GeometryUploader::<T,_>::new(
world,
1024,
indices_allocator.clone(),
self.renderer_type,
self.use_unified_material_ubo,
);
let animated_upload = geometry::AnimatedGeometryGpuUpdater::<
T, gl::SharedBufferStorage<u8>>::new(uploader.allocator_handle);
world.add_creation_system(uploader);
world.add_system_thread_local(animated_upload);
}
IndicesAllocator::Buffer(indices_allocator) => {
let uploader = geometry::GeometryUploader::<T,_>::new(
world,
1024,
indices_allocator.clone(),
self.renderer_type,
self.use_unified_material_ubo,
);
let animated_upload = geometry::AnimatedGeometryGpuUpdater::<
T, gl::SharedBuffer<u8>>::new(uploader.allocator_handle);
world.add_creation_system(uploader);
world.add_system_thread_local(animated_upload);
}
};
}
}
gl::program_cache!(glin::program::Settings{
version: default_glsl_version(),
extensions: vec![],
precision: glin::program::ShaderPrecision::High,
defines: vec![
("USE_CAMERA_UBO", "1"),
("USE_MODEL_ATTR", "1"),
],
shaders: vec![
(glin::gl::VERTEX_SHADER, include_str!("shaders/shadow_render.vs.glsl")),
(glin::gl::FRAGMENT_SHADER, include_str!("shaders/shadow_render.fs.glsl")),
],
bindings: default_attribute_bindings(),
base_path: "",
includes: rin_gl::hash_map!{
"mvp_uniforms.glsl" => include_str!("shaders/mvp_uniforms.glsl")
},
}, get_shadow_render_shader, SHADOW_MAP_SHADER);
gl::program_cache!(glin::program::Settings{
version: default_glsl_version(),
extensions: vec![],
precision: glin::program::ShaderPrecision::High,
defines: vec![
("USE_CAMERA_UBO", "1"),
("USE_MODEL_ATTR", "1"),
],
shaders: vec![
(glin::gl::VERTEX_SHADER, include_str!("shaders/depth_only.vs.glsl")),
(glin::gl::FRAGMENT_SHADER, include_str!("shaders/depth_only.fs.glsl")),
],
bindings: default_attribute_bindings(),
base_path: "",
includes: rin_gl::hash_map!{
"mvp_uniforms.glsl" => include_str!("shaders/mvp_uniforms.glsl")
},
}, get_depth_only_shader, DEPTH_ONLY_SHADER);
gl::program_cache!(glin::program::Settings{
version: default_glsl_version(),
extensions: vec![],
precision: glin::program::ShaderPrecision::High,
defines: vec![
("USE_CAMERA_UBO", "1"),
("USE_MODEL_ATTR", "1"),
("EMULATE_DEPTH_CLAMP", "1"),
],
shaders: vec![
(glin::gl::VERTEX_SHADER, include_str!("shaders/depth_only.vs.glsl")),
(glin::gl::FRAGMENT_SHADER, include_str!("shaders/depth_only.fs.glsl")),
],
bindings: default_attribute_bindings(),
base_path: "",
includes: rin_gl::hash_map!{
"mvp_uniforms.glsl" => include_str!("shaders/mvp_uniforms.glsl")
},
}, get_depth_clamp_shader, DEPTH_CLAMP_SHADER);
struct ViewportSender{
viewport: Property<'static, Rect<i32>>
}
#[system_thread_local(name = "viewport sender")]
#[reads(ScreenRenderBuffer)]
impl SystemThreadLocal for ViewportSender {
fn run(&mut self, _entities: EntitiesThreadLocal, resources: ResourcesThreadLocal){
let render_surface = resources.get::<ScreenRenderBuffer>().unwrap();
self.viewport.set(render_surface.viewport().into())
}
}