use std::ops::{Deref, DerefMut};
use rin_graphics::mvp;
use rin_gl as gl;
use rin_gl::types::*;
use rin_math::{vec2, Vec2, Mat4};
use rin_material::{MaterialRef, ShadowMaterialRef};
use super::geometry::GpuGeometryRef;
use densevec::KeyedDenseVec;
use std::rc::Rc;
use glin::OffscreenBuffer;
use std::cell::{UnsafeCell, Cell, RefCell};
use super::memory::VaoId;
#[cfg(feature="async")]
use rin_util::async_fs;
#[cfg(feature="async")]
use std::sync::Arc;
#[cfg(feature="async")]
use std::sync::RwLock;
#[cfg(feature="async")]
use std::pin::Pin;
#[cfg(feature="async")]
use futures::task::{Poll, Context, Waker};
#[cfg(feature="async")]
use futures::{Future, FutureExt, future::FusedFuture, channel::mpsc::*, stream::StreamExt};
#[cfg(feature = "async")]
use rinecs::{CreationProxy, CreationSystemAsync};
use std::hash::{Hash, Hasher};
use hashbrown::HashSet;
pub struct CameraUBO{
pub ubo: gl::Buffer<mvp::CameraData>,
pub reversed_z: bool,
#[cfg(not(any(feature="webgl", feature="gles")))]
pub zero_to_one: bool,
pub clamp_depth: bool,
pub dirty: bool,
}
impl Deref for CameraUBO{
type Target = gl::Buffer<mvp::CameraData>;
fn deref(&self) -> &gl::Buffer<mvp::CameraData>{
&self.ubo
}
}
impl DerefMut for CameraUBO{
fn deref_mut(&mut self) -> &mut gl::Buffer<mvp::CameraData>{
&mut self.ubo
}
}
pub struct LightingUBO{
pub ubo: gl::Buffer<u8>,
pub dirty: bool,
}
impl Deref for LightingUBO{
type Target = gl::Buffer<u8>;
fn deref(&self) -> &gl::Buffer<u8>{
&self.ubo
}
}
impl DerefMut for LightingUBO{
fn deref_mut(&mut self) -> &mut gl::Buffer<u8>{
&mut self.ubo
}
}
#[derive(Debug)]
pub struct LightingTexture{
pub name: String,
pub texture: u32,
pub target: GLenum,
}
#[derive(Debug)]
pub struct LightingSampler{
pub shadow_sampler_idx: i32,
pub texture: u32,
pub sampler: u32,
pub pcf_sampler: u32,
pub target: GLenum,
}
impl Hash for LightingSampler{
fn hash<H: Hasher>(&self, state: &mut H) {
self.texture.hash(state);
self.sampler.hash(state);
self.pcf_sampler.hash(state);
self.target.hash(state);
}
}
impl PartialEq for LightingSampler{
fn eq(&self, other: &LightingSampler) -> bool {
self.texture == other.texture
&& self.sampler == other.sampler
&& self.pcf_sampler == other.pcf_sampler
&& self.target == other.target
}
}
impl Eq for LightingSampler{}
impl LightingSampler{
pub fn sampler_name(&self) -> String{
format!("shadow_map[{}]", self.shadow_sampler_idx)
}
pub fn pcf_sampler_name(&self) -> String{
format!("shadow_map_pcf[{}]", self.shadow_sampler_idx)
}
pub fn offset_uniform_name(&self) -> String{
format!("shadow_map_offset[{}]", self.shadow_sampler_idx)
}
pub fn factor_uniform_name(&self) -> String{
format!("shadow_map_factor[{}]", self.shadow_sampler_idx)
}
}
#[derive(Debug, Default)]
pub struct LightingTextures{
pub ibl: Vec<LightingTexture>,
pub shadow_maps: HashSet<LightingSampler>,
pub has_changed: bool,
pub num_shadow_maps_changed: bool,
}
impl LightingTextures{
pub fn new() -> LightingTextures{
Self::default()
}
}
pub struct LightData(pub std140_data::Data);
impl Deref for LightData{
type Target = std140_data::Data;
fn deref(&self) -> &std140_data::Data{
&self.0
}
}
impl DerefMut for LightData{
fn deref_mut(&mut self) -> &mut std140_data::Data{
&mut self.0
}
}
#[cfg(feature="async")]
struct FutureData<T>{
payload: Option<rin_util::Result<T>>,
done: bool,
waker: Option<Waker>
}
#[cfg(feature = "async")]
#[derive(Clone)]
pub struct ResourceFuture<T>{
data: Arc<RwLock<FutureData<T>>>,
}
#[cfg(feature="async")]
impl<T> Future for ResourceFuture<T>{
type Output = rin_util::Result<T>;
fn poll(self: Pin<&mut Self>, cw: &mut Context) -> Poll<Self::Output>{
let mut data = self.data.write().unwrap();
let res = data.payload.take();
match res {
Some(res) => {
data.done = true;
Poll::Ready(res)
},
None if !data.done => {
data.waker = Some(cw.waker().clone());
Poll::Pending
},
None => {
Poll::Ready(Err(rin_util::Error::new("Texture already loaded")))
}
}
}
}
#[cfg(feature="async")]
impl<T> FusedFuture for ResourceFuture<T>{
fn is_terminated(&self) -> bool {
self.data.read().unwrap().done
}
}
#[cfg(feature = "async")]
impl<T> ResourceFuture<T>{
pub fn new() -> ResourceFuture<T>{
ResourceFuture{
data: Arc::new(RwLock::new(FutureData{
payload: None,
done: false,
waker: None
}))
}
}
pub fn with(ready: rin_util::Result<T>) -> ResourceFuture<T>{
ResourceFuture{
data: Arc::new(RwLock::new(FutureData{
payload: Some(ready),
done: false,
waker: None,
}))
}
}
pub fn ready(&mut self, ready: rin_util::Result<T>){
let mut data = self.data.write().unwrap();
data.payload = Some(ready);
if let Some(waker) = data.waker.take(){
waker.wake()
}
}
}
pub struct ModelMatricesData{
pub data: Vec<(Mat4, Mat4)>,
pub has_changed: bool,
}
impl Deref for ModelMatricesData{
type Target = Vec<(Mat4, Mat4)>;
fn deref(&self) -> &Vec<(Mat4, Mat4)>{
&self.data
}
}
impl DerefMut for ModelMatricesData{
fn deref_mut(&mut self) -> &mut Vec<(Mat4, Mat4)>{
&mut self.data
}
}
pub struct AllModelMatricesData{
pub data: Vec<Mat4>,
pub has_changed: bool,
}
impl Deref for AllModelMatricesData{
type Target = Vec<Mat4>;
fn deref(&self) -> &Vec<Mat4>{
&self.data
}
}
impl DerefMut for AllModelMatricesData{
fn deref_mut(&mut self) -> &mut Vec<Mat4>{
&mut self.data
}
}
pub struct StaticModelMatricesData{
pub data: Vec<Mat4>,
pub has_changed: bool,
}
impl Deref for StaticModelMatricesData{
type Target = Vec<Mat4>;
fn deref(&self) -> &Vec<Mat4>{
&self.data
}
}
impl DerefMut for StaticModelMatricesData{
fn deref_mut(&mut self) -> &mut Vec<Mat4>{
&mut self.data
}
}
pub struct DynamicModelMatricesData{
pub data: Vec<Mat4>,
pub has_changed: bool,
}
impl Deref for DynamicModelMatricesData{
type Target = Vec<Mat4>;
fn deref(&self) -> &Vec<Mat4>{
&self.data
}
}
impl DerefMut for DynamicModelMatricesData{
fn deref_mut(&mut self) -> &mut Vec<Mat4>{
&mut self.data
}
}
pub struct ModelMatricesBuffer(pub gl::SharedBuffer<(Mat4, Mat4)>);
pub struct AllModelMatricesBuffer(pub gl::SharedBuffer<Mat4>);
pub struct StaticModelMatricesBuffer(pub gl::SharedBuffer<Mat4>);
pub struct DynamicModelMatricesBuffer(pub gl::SharedBuffer<Mat4>);
impl Deref for ModelMatricesBuffer{
type Target = gl::SharedBuffer<(Mat4, Mat4)>;
fn deref(&self) -> &gl::SharedBuffer<(Mat4, Mat4)>{
&self.0
}
}
impl DerefMut for ModelMatricesBuffer{
fn deref_mut(&mut self) -> &mut gl::SharedBuffer<(Mat4, Mat4)>{
&mut self.0
}
}
impl Deref for StaticModelMatricesBuffer{
type Target = gl::SharedBuffer<Mat4>;
fn deref(&self) -> &gl::SharedBuffer<Mat4>{
&self.0
}
}
impl DerefMut for StaticModelMatricesBuffer{
fn deref_mut(&mut self) -> &mut gl::SharedBuffer<Mat4>{
&mut self.0
}
}
impl Deref for DynamicModelMatricesBuffer{
type Target = gl::SharedBuffer<Mat4>;
fn deref(&self) -> &gl::SharedBuffer<Mat4>{
&self.0
}
}
impl DerefMut for DynamicModelMatricesBuffer{
fn deref_mut(&mut self) -> &mut gl::SharedBuffer<Mat4>{
&mut self.0
}
}
impl Deref for AllModelMatricesBuffer{
type Target = gl::SharedBuffer<Mat4>;
fn deref(&self) -> &gl::SharedBuffer<Mat4>{
&self.0
}
}
impl DerefMut for AllModelMatricesBuffer{
fn deref_mut(&mut self) -> &mut gl::SharedBuffer<Mat4>{
&mut self.0
}
}
#[derive(Clone)]
pub struct GeometryIndex{
pub entities: Vec<rinecs::Entity>,
pub geometryref: rinecs::Entity,
pub materialref: MaterialRef,
pub submesh: usize,
pub vao_id: VaoId,
pub renderplane: Option<rinecs::Entity>,
}
impl GeometryIndex{
pub fn num_instances(&self) -> usize{
self.entities.len()
}
}
#[derive(Clone, Debug)]
pub struct ShadowGeometryIndex{
pub entities: Vec<rinecs::Entity>,
pub geometryref: GpuGeometryRef,
pub materialref: Option<ShadowMaterialRef>,
pub submesh: Option<usize>,
pub vao_id: VaoId,
pub primitive_type: GLenum,
}
impl ShadowGeometryIndex{
pub fn num_instances(&self) -> usize{
self.entities.len()
}
}
#[derive(Clone)]
pub struct OpaqueSortedGeometry{
index: Vec<GeometryIndex>,
has_changed: bool,
}
impl OpaqueSortedGeometry{
pub fn new() -> OpaqueSortedGeometry{
OpaqueSortedGeometry{
index: vec![],
has_changed: false,
}
}
pub fn geometryrefs(&self) -> impl Iterator<Item = rinecs::Entity> + '_ {
self.index.iter().map(|geom| geom.geometryref)
}
pub fn reset_has_changed(&mut self) {
self.has_changed = false
}
pub fn has_changed(&self) -> bool {
self.has_changed
}
}
impl Deref for OpaqueSortedGeometry {
type Target = Vec<GeometryIndex>;
fn deref(&self) -> &Vec<GeometryIndex>{
&self.index
}
}
impl DerefMut for OpaqueSortedGeometry {
fn deref_mut(&mut self) -> &mut Vec<GeometryIndex>{
self.has_changed = true;
&mut self.index
}
}
#[derive(Clone)]
pub struct TranslucentSortedGeometry{
index: Vec<GeometryIndex>,
has_changed: bool,
}
impl TranslucentSortedGeometry{
pub fn new() -> TranslucentSortedGeometry{
TranslucentSortedGeometry{
index: vec![],
has_changed: false,
}
}
pub fn geometryrefs(&self) -> impl Iterator<Item = rinecs::Entity> + '_ {
self.index.iter().map(|geom| geom.geometryref)
}
pub fn reset_has_changed(&mut self) {
self.has_changed = false
}
pub fn has_changed(&self) -> bool {
self.has_changed
}
}
impl Deref for TranslucentSortedGeometry {
type Target = Vec<GeometryIndex>;
fn deref(&self) -> &Vec<GeometryIndex>{
&self.index
}
}
impl DerefMut for TranslucentSortedGeometry {
fn deref_mut(&mut self) -> &mut Vec<GeometryIndex>{
self.has_changed = true;
&mut self.index
}
}
#[cfg(feature = "debug_geometry")]
#[derive(Clone)]
pub struct DebugSortedGeometry{
index: Vec<GeometryIndex>,
has_changed: bool,
}
#[cfg(feature = "debug_geometry")]
impl DebugSortedGeometry{
pub fn new() -> DebugSortedGeometry{
DebugSortedGeometry{
index: vec![],
has_changed: false,
}
}
pub fn geometryrefs(&self) -> impl Iterator<Item = &rinecs::Entity> + '_ {
self.index.iter().map(|geom| &geom.geometryref)
}
pub fn reset_has_changed(&mut self) {
self.has_changed = false
}
pub fn has_changed(&self) -> bool {
self.has_changed
}
}
#[cfg(feature = "debug_geometry")]
impl Deref for DebugSortedGeometry {
type Target = Vec<GeometryIndex>;
fn deref(&self) -> &Vec<GeometryIndex>{
&self.index
}
}
#[cfg(feature = "debug_geometry")]
impl DerefMut for DebugSortedGeometry {
fn deref_mut(&mut self) -> &mut Vec<GeometryIndex>{
self.has_changed = true;
&mut self.index
}
}
#[derive(Clone, Debug)]
pub struct DynamicShadowsSortedGeometry{
index: Vec<ShadowGeometryIndex>,
has_changed: bool,
}
impl DynamicShadowsSortedGeometry{
pub fn new() -> DynamicShadowsSortedGeometry{
DynamicShadowsSortedGeometry{
index: vec![],
has_changed: false,
}
}
pub fn geometryrefs(&self) -> impl Iterator<Item = &GpuGeometryRef> + '_ {
self.index.iter().map(|geom| &geom.geometryref)
}
pub fn has_changed(&self) -> bool {
self.has_changed
}
pub fn reset_has_changed(&mut self) {
self.has_changed = false
}
pub fn is_empty(&self) -> bool{
self.index.is_empty()
}
}
impl Deref for DynamicShadowsSortedGeometry {
type Target = Vec<ShadowGeometryIndex>;
fn deref(&self) -> &Vec<ShadowGeometryIndex>{
&self.index
}
}
impl DerefMut for DynamicShadowsSortedGeometry {
fn deref_mut(&mut self) -> &mut Vec<ShadowGeometryIndex>{
self.has_changed = true;
&mut self.index
}
}
#[derive(Clone, Debug)]
pub struct StaticShadowsSortedGeometry{
index: Vec<ShadowGeometryIndex>,
has_changed: bool,
}
impl StaticShadowsSortedGeometry{
pub fn new() -> StaticShadowsSortedGeometry{
StaticShadowsSortedGeometry{
index: vec![],
has_changed: false,
}
}
pub fn geometryrefs(&self) -> impl Iterator<Item = &GpuGeometryRef> + '_ {
self.index.iter().map(|geom| &geom.geometryref)
}
pub fn has_changed(&self) -> bool {
self.has_changed
}
pub fn reset_has_changed(&mut self) {
self.has_changed = false
}
pub fn is_empty(&self) -> bool {
self.index.is_empty()
}
}
impl Deref for StaticShadowsSortedGeometry {
type Target = Vec<ShadowGeometryIndex>;
fn deref(&self) -> &Vec<ShadowGeometryIndex>{
&self.index
}
}
impl DerefMut for StaticShadowsSortedGeometry {
fn deref_mut(&mut self) -> &mut Vec<ShadowGeometryIndex>{
self.has_changed = true;
&mut self.index
}
}
#[derive(Clone, Debug)]
pub struct AllShadowsSortedGeometry{
index: Vec<ShadowGeometryIndex>,
has_changed: bool,
}
impl AllShadowsSortedGeometry{
pub fn new() -> AllShadowsSortedGeometry{
AllShadowsSortedGeometry{
index: vec![],
has_changed: false,
}
}
pub fn geometryrefs(&self) -> impl Iterator<Item = &GpuGeometryRef> + '_ {
self.index.iter().map(|geom| &geom.geometryref)
}
pub fn has_changed(&self) -> bool {
self.has_changed
}
pub fn reset_has_changed(&mut self) {
self.has_changed = false
}
pub fn is_empty(&self) -> bool {
self.index.is_empty()
}
}
impl Deref for AllShadowsSortedGeometry {
type Target = Vec<ShadowGeometryIndex>;
fn deref(&self) -> &Vec<ShadowGeometryIndex>{
&self.index
}
}
impl DerefMut for AllShadowsSortedGeometry {
fn deref_mut(&mut self) -> &mut Vec<ShadowGeometryIndex>{
self.has_changed = true;
&mut self.index
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
enum RenderBuffers{
Color = 0,
Normals = 1,
Position = 2,
LinearDepth = 3,
AmbientColor = 4,
}
impl densevec::Key for RenderBuffers{
fn to_usize(self) -> usize{
self as usize
}
fn from_usize(uid: usize) -> Self{
match uid{
0 => RenderBuffers::Color,
1 => RenderBuffers::Normals,
2 => RenderBuffers::Position,
3 => RenderBuffers::LinearDepth,
4 => RenderBuffers::AmbientColor,
_ => panic!("Non exisiting uid")
}
}
}
fn add_alpha(format: glin::fbo::ColorFormat) -> glin::fbo::ColorFormat{
use glin::fbo::ColorFormat;
match format {
ColorFormat::R8 => ColorFormat::RG8,
ColorFormat::RG8 => ColorFormat::RG8,
ColorFormat::RGB8 => ColorFormat::RGBA8,
ColorFormat::RGBA8 => ColorFormat::RGBA8,
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
ColorFormat::R16 => ColorFormat::RG16,
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
ColorFormat::RG16 => ColorFormat::RG16,
ColorFormat::R16F => ColorFormat::RG16F,
ColorFormat::RG16F => ColorFormat::RG16F,
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
ColorFormat::RGB16 => ColorFormat::RGBA16,
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
ColorFormat::RGBA16 => ColorFormat::RGBA16,
ColorFormat::RGB16F => ColorFormat::RGBA16F,
ColorFormat::RGBA16F => ColorFormat::RGBA16F,
ColorFormat::R32F => ColorFormat::RG32F,
ColorFormat::RG32F => ColorFormat::RG32F,
ColorFormat::RGB32F => ColorFormat::RGBA32F,
ColorFormat::RGBA32F => ColorFormat::RGBA32F,
}
}
pub(crate) struct ScreenRenderBufferStaticBuilder{
w: u32,
h: u32,
samples: Option<u32>,
color_format: glin::fbo::ColorFormat,
depth_format: glin::fbo::DepthFormat,
depth_prepass: bool,
output_normals: bool,
output_position: bool,
output_separate_ambient: bool,
output_linear_depth: bool,
depth_as_texture: bool,
resolve_base_color: bool,
resolve_normals: bool,
resolve_position: bool,
resolve_separate_ambient: bool,
resolve_linear_depth: bool,
resolve_depth: bool,
}
impl ScreenRenderBufferStaticBuilder {
pub(crate) fn new(w: u32, h: u32, format: glin::fbo::ColorFormat) -> ScreenRenderBufferStaticBuilder{
ScreenRenderBufferStaticBuilder{
w, h,
samples: None,
color_format: format,
depth_format: glin::fbo::DepthFormat::_24,
output_normals: false,
output_position: false,
output_separate_ambient: false,
output_linear_depth: false,
depth_prepass: false,
depth_as_texture: false,
resolve_base_color: true,
resolve_normals: true,
resolve_position: true,
resolve_separate_ambient: true,
resolve_linear_depth: true,
resolve_depth: true,
}
}
pub(crate) fn size(&mut self, w: u32, h: u32) -> &mut Self {
self.w = w;
self.h = h;
self
}
pub(crate) fn color_format(&mut self, format: gl::fbo::ColorFormat) -> &mut Self {
self.color_format = format;
self
}
pub(crate) fn normals_buffer(&mut self) -> &mut Self{
self.output_normals = true;
self
}
pub(crate) fn position_buffer(&mut self) -> &mut Self{
self.output_position = true;
self
}
pub(crate) fn separate_ambient_buffer(&mut self) -> &mut Self{
self.output_separate_ambient = true;
self
}
pub(crate) fn linear_depth_buffer(&mut self) -> &mut Self{
self.output_linear_depth = true;
self
}
pub(crate) fn depth_format(&mut self, depth_format: glin::fbo::DepthFormat) -> &mut Self{
self.depth_format = depth_format;
self
}
pub(crate) fn disable_resolve_base_color(&mut self) -> &mut Self{
self.resolve_base_color = false;
self
}
pub(crate) fn disable_normals_resolve(&mut self) -> &mut Self{
self.resolve_normals = false;
self
}
pub(crate) fn disable_position_resolve(&mut self) -> &mut Self{
self.resolve_position = false;
self
}
pub(crate) fn disable_separate_ambient_resolve(&mut self) -> &mut Self{
self.resolve_separate_ambient = false;
self
}
pub(crate) fn disable_linear_depth_resolve(&mut self) -> &mut Self{
self.resolve_linear_depth = false;
self
}
pub(crate) fn disable_depth_resolve(&mut self) -> &mut Self{
self.resolve_depth = false;
self
}
pub(crate) fn samples(&mut self, samples: u32) -> &mut Self{
self.samples = Some(samples);
self
}
pub(crate) fn depth_prepass(&mut self) -> &mut Self{
self.depth_prepass = true;
self
}
pub(crate) fn depth_as_texture(&mut self) -> &mut Self{
self.depth_as_texture = true;
self
}
pub(crate) fn build<'r>(&mut self, gl: &gl::Renderer<'r>) -> glin::Result<ScreenRenderBuffer>{
let color;
let depth;
if let Some(samples) = self.samples {
color = gl.new_fbo_color_attachment()
.render_buffer_multisampled(self.w, self.h, samples, self.color_format)?;
if self.depth_as_texture && !self.resolve_depth {
#[cfg(not(any(feature="gles", feature="webgl")))]
{
depth = gl.new_fbo_depth_attachment()
.texture_multisampled(self.w, self.h, samples, self.depth_format)?;
}
#[cfg(any(feature="gles", feature="webgl"))]
unimplemented!("Multisampled textures are not supported in GLES / WebGL, please use another format")
}else{
depth = gl.new_fbo_depth_attachment()
.render_buffer_multisampled(self.w, self.h, samples, self.depth_format)?;
}
}else{
color = gl.new_fbo_color_attachment()
.texture(self.w, self.h, self.color_format)?;
depth = if self.depth_as_texture {
gl.new_fbo_depth_attachment()
.texture(self.w, self.h, self.depth_format)?
}else{
gl.new_fbo_depth_attachment()
.render_buffer(self.w, self.h, self.depth_format)?
};
}
let mut color = vec![Rc::new(color)];
let mut attachments_map = KeyedDenseVec::new();
let depth = Rc::new(depth);
attachments_map.insert(RenderBuffers::Color, 0);
let mut last_attachment_map = 1;
if self.output_normals {
let normals = if let Some(samples) = self.samples{
gl.new_fbo_color_attachment()
.render_buffer_multisampled(self.w, self.h, samples, self.color_format)?
}else{
gl.new_fbo_color_attachment()
.texture(self.w, self.h, self.color_format)?
};
color.push(Rc::new(normals));
attachments_map.insert(RenderBuffers::Normals, last_attachment_map);
last_attachment_map += 1;
}
if self.output_position {
let position = if let Some(samples) = self.samples{
gl.new_fbo_color_attachment()
.render_buffer_multisampled(self.w, self.h, samples, self.color_format)?
}else{
gl.new_fbo_color_attachment()
.texture(self.w, self.h, self.color_format)?
};
color.push(Rc::new(position));
attachments_map.insert(RenderBuffers::Position, last_attachment_map);
last_attachment_map += 1;
}
let linear_depth_format = match self.depth_format{
#[cfg(not(any(feature="gles", feature="webgl")))]
glin::fbo::DepthFormat::_16 => glin::fbo::ColorFormat::R16,
#[cfg(any(feature="gles", feature="webgl"))]
glin::fbo::DepthFormat::_16 => glin::fbo::ColorFormat::R32F,
glin::fbo::DepthFormat::_24 => glin::fbo::ColorFormat::R32F,
glin::fbo::DepthFormat::_32 => glin::fbo::ColorFormat::R32F,
};
if self.output_linear_depth {
let linear_depth = if let Some(samples) = self.samples{
gl.new_fbo_color_attachment()
.render_buffer_multisampled(self.w, self.h, samples, linear_depth_format)?
}else{
gl.new_fbo_color_attachment()
.texture(self.w, self.h, linear_depth_format)?
};
color.push(Rc::new(linear_depth));
attachments_map.insert(RenderBuffers::LinearDepth, last_attachment_map);
last_attachment_map += 1;
}
let ambient_format = add_alpha(self.color_format);
if self.output_separate_ambient {
let ambient = if let Some(samples) = self.samples{
gl.new_fbo_color_attachment()
.render_buffer_multisampled(self.w, self.h, samples, ambient_format)?
}else{
gl.new_fbo_color_attachment()
.texture(self.w, self.h, ambient_format)?
};
color.push(Rc::new(ambient));
attachments_map.insert(RenderBuffers::AmbientColor, last_attachment_map);
}
let render_buffer = Rc::new(gl.new_fbo().from_colors_depth(color, depth.clone())?);
let depth_prepass = if self.depth_prepass{
Some(gl.new_fbo().from_depth(depth)?)
}else{
None
};
let mut blit_buffers = KeyedDenseVec::new();
let mut depth_blit_buffer = None;
if self.samples.is_some(){
if self.resolve_base_color {
let blit_color = gl.new_fbo_color_attachment()
.texture(self.w, self.h, self.color_format)?;
let blit_buffer = gl.new_fbo().from_color_no_depth(blit_color)?;
blit_buffers.insert(RenderBuffers::Color, blit_buffer);
}
if self.resolve_depth {
let blit_depth = gl.new_fbo_depth_attachment()
.texture(self.w, self.h, self.depth_format)?;
let mut blit_buffer = gl.new_fbo().from_depth(blit_depth)?;
blit_buffer.depth_tex_mut().unwrap().set_min_mag_filters(gl::NEAREST, gl::NEAREST);
depth_blit_buffer = Some(UnsafeCell::new(blit_buffer));
}
if self.output_normals && self.resolve_normals {
let blit_color = gl.new_fbo_color_attachment()
.texture(self.w, self.h, self.color_format)?;
let mut blit_buffer = gl.new_fbo().from_color_no_depth(blit_color)?;
blit_buffer.color_tex_mut(0).unwrap().set_min_mag_filters(gl::NEAREST, gl::NEAREST);
blit_buffers.insert(RenderBuffers::Normals, blit_buffer);
}
if self.output_position && self.resolve_position {
let blit_color = gl.new_fbo_color_attachment()
.texture(self.w, self.h, self.color_format)?;
let mut blit_buffer = gl.new_fbo().from_color_no_depth(blit_color)?;
blit_buffer.color_tex_mut(0).unwrap().set_min_mag_filters(gl::NEAREST, gl::NEAREST);
blit_buffers.insert(RenderBuffers::Position, blit_buffer);
}
if self.output_linear_depth && self.resolve_linear_depth {
let blit_color = gl.new_fbo_color_attachment()
.texture(self.w, self.h, linear_depth_format)?;
let mut blit_buffer = gl.new_fbo().from_color_no_depth(blit_color)?;
blit_buffer.color_tex_mut(0).unwrap().set_min_mag_filters(gl::NEAREST, gl::NEAREST);
blit_buffers.insert(RenderBuffers::LinearDepth, blit_buffer);
}
if self.output_separate_ambient && self.resolve_separate_ambient {
let blit_color = gl.new_fbo_color_attachment()
.texture(self.w, self.h, ambient_format)?;
let mut blit_buffer = gl.new_fbo().from_color_no_depth(blit_color)?;
blit_buffer.color_tex_mut(0).unwrap().set_min_mag_filters(gl::NEAREST, gl::NEAREST);
blit_buffers.insert(RenderBuffers::AmbientColor, blit_buffer);
}
}
let mut changed = KeyedDenseVec::new();
changed.insert(RenderBuffers::Color, Cell::new(false));
if self.output_normals{
changed.insert(RenderBuffers::Normals, Cell::new(false));
}
if self.output_position{
changed.insert(RenderBuffers::Position, Cell::new(false));
}
if self.output_linear_depth{
changed.insert(RenderBuffers::LinearDepth, Cell::new(false));
}
if self.output_separate_ambient{
changed.insert(RenderBuffers::AmbientColor, Cell::new(false));
}
let aux_fbo = gl.new_fbo().empty().unwrap();
Ok(ScreenRenderBuffer{
render_buffer,
blit_buffers: UnsafeCell::new(blit_buffers),
depth_blit_buffer,
changed,
depth_changed: Cell::new(false),
depth_prepass,
attachments_map,
aux_fbo,
color_format: self.color_format,
last_stage: RenderStage::Opaque,
})
}
}
pub struct ScreenRenderBufferBuilder<'a, 'r>{
gl: &'a gl::Renderer<'r>,
builder: ScreenRenderBufferStaticBuilder,
}
impl<'a, 'r> ScreenRenderBufferBuilder<'a, 'r>{
pub fn new(gl: &'a gl::Renderer<'r>, w: u32, h: u32, format: glin::fbo::ColorFormat) -> ScreenRenderBufferBuilder<'a, 'r>{
ScreenRenderBufferBuilder{
gl,
builder: ScreenRenderBufferStaticBuilder::new(w, h, format)
}
}
pub fn normals_buffer(&mut self) -> &mut Self{
self.builder.normals_buffer();
self
}
pub fn position_buffer(&mut self) -> &mut Self{
self.builder.position_buffer();
self
}
pub fn separate_ambient_buffer(&mut self) -> &mut Self{
self.builder.separate_ambient_buffer();
self
}
pub fn linear_depth_buffer(&mut self) -> &mut Self{
self.builder.linear_depth_buffer();
self
}
pub fn depth_format(&mut self, depth_format: glin::fbo::DepthFormat) -> &mut Self{
self.builder.depth_format(depth_format);
self
}
pub fn disable_resolve_base_color(&mut self) -> &mut Self{
self.builder.disable_resolve_base_color();
self
}
pub fn disable_normals_resolve(&mut self) -> &mut Self{
self.builder.disable_normals_resolve();
self
}
pub fn disable_position_resolve(&mut self) -> &mut Self{
self.builder.disable_position_resolve();
self
}
pub fn disable_separate_ambient_resolve(&mut self) -> &mut Self{
self.builder.disable_separate_ambient_resolve();
self
}
pub fn disable_linear_depth_resolve(&mut self) -> &mut Self{
self.builder.disable_linear_depth_resolve();
self
}
pub fn disable_depth_resolve(&mut self) -> &mut Self{
self.builder.disable_depth_resolve();
self
}
pub fn samples(&mut self, samples: u32) -> &mut Self{
self.builder.samples(samples);
self
}
pub fn depth_prepass(&mut self) -> &mut Self{
self.builder.depth_prepass();
self
}
pub fn depth_as_texture(&mut self) -> &mut Self{
self.builder.depth_as_texture();
self
}
pub fn build(&mut self) -> glin::Result<ScreenRenderBuffer>{
self.builder.build(self.gl)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RenderStage{
Opaque,
AfterOpaque,
AfterOpaquePostprocess,
Translucent,
AfterTranslucent,
AfterFinalPostprocess,
}
pub struct ScreenRenderBuffer{
render_buffer: Rc<glin::Fbo<Rc<glin::fbo::ColorAttachment>, Rc<glin::fbo::DepthAttachment>>>,
blit_buffers: UnsafeCell<KeyedDenseVec<RenderBuffers, glin::Fbo>>,
depth_blit_buffer: Option<UnsafeCell<glin::Fbo>>,
changed: KeyedDenseVec<RenderBuffers, Cell<bool>>,
attachments_map: KeyedDenseVec<RenderBuffers, u32>,
depth_changed: Cell<bool>,
depth_prepass: Option<glin::Fbo<glin::fbo::ColorAttachment, Rc<glin::fbo::DepthAttachment>>>,
aux_fbo: glin::Fbo<(),()>,
last_stage: RenderStage,
color_format: glin::fbo::ColorFormat,
}
impl ScreenRenderBuffer{
fn resolved_attachment(&self, buffer: RenderBuffers) -> Option<&glin::fbo::ColorAttachment> {
let blit_buffers = unsafe{ &mut *self.blit_buffers.get() };
if let Some(blit_buffer) = blit_buffers.get_mut(buffer) {
self.changed[buffer].set(false);
let attachment_idx = self.attachments_map[buffer];
self.render_buffer.blit_color_attachment(attachment_idx,
blit_buffer,
&self.render_buffer.viewport(),
&blit_buffer.viewport());
blit_buffer.color_attachment(0)
}else{
let attachment_idx = *self.attachments_map.get(buffer)?;
self.render_buffer.color_attachment(attachment_idx as usize).map(|r| r.deref())
}
}
fn attachment(&self, buffer: RenderBuffers) -> Option<&glin::fbo::ColorAttachment> {
let blit_buffers = unsafe{ &mut *self.blit_buffers.get() };
if let Some(blit_buffer) = blit_buffers.get_mut(buffer) {
if self.changed[buffer].get() {
self.changed[buffer].set(false);
let attachment_idx = self.attachments_map[buffer];
self.render_buffer.blit_color_attachment(attachment_idx,
blit_buffer,
&self.render_buffer.viewport(),
&blit_buffer.viewport())
}
blit_buffer.color_attachment(0)
}else{
let attachment_idx = *self.attachments_map.get(buffer)?;
self.render_buffer.color_attachment(attachment_idx as usize).map(|r| r.deref())
}
}
fn unresolved_attachment(&self, buffer: RenderBuffers) -> Option<&Rc<glin::fbo::ColorAttachment>>{
let attachment_idx = *self.attachments_map.get(buffer)?;
self.render_buffer.color_attachment(attachment_idx as usize)
}
pub fn width(&self) -> u32{
self.render_buffer.width()
}
pub fn height(&self) -> u32{
self.render_buffer.height()
}
pub fn size(&self) -> Vec2<u32>{
vec2(self.render_buffer.width(), self.render_buffer.height())
}
pub fn color_format(&self) -> glin::fbo::ColorFormat {
self.color_format
}
pub fn aspect_ratio(&self) -> f32{
self.render_buffer.aspect_ratio()
}
pub fn color_attachment(&self) -> &glin::fbo::ColorAttachment{
self.attachment(RenderBuffers::Color).unwrap()
}
pub fn color_attachment_force_resolve(&self) -> &glin::fbo::ColorAttachment{
self.resolved_attachment(RenderBuffers::Color).unwrap()
}
pub fn color_unresolved_attachment(&self) -> &Rc<glin::fbo::ColorAttachment>{
self.unresolved_attachment(RenderBuffers::Color).unwrap()
}
pub fn depth_attachment(&self) -> &glin::fbo::DepthAttachment{
if let Some(blit_buffer) = self.depth_blit_buffer.as_ref() {
let blit_buffer = unsafe{ &mut *blit_buffer.get() };
if self.depth_changed.get() {
self.depth_changed.set(false);
self.render_buffer.blit_depth(blit_buffer,
&self.render_buffer.viewport(),
&blit_buffer.viewport())
}
blit_buffer.depth_attachment().unwrap()
}else{
self.render_buffer.depth_attachment().map(|r| r.deref()).unwrap()
}
}
pub fn depth_unresolved_attachment(&self) -> &Rc<glin::fbo::DepthAttachment>{
self.render_buffer.depth().as_ref().unwrap()
}
pub fn normals_attachment(&self) -> Option<&glin::fbo::ColorAttachment>{
self.attachment(RenderBuffers::Normals)
}
pub fn position_attachment(&self) -> Option<&glin::fbo::ColorAttachment>{
self.attachment(RenderBuffers::Position)
}
pub fn linear_depth_attachment(&self) -> Option<&glin::fbo::ColorAttachment>{
self.attachment(RenderBuffers::LinearDepth)
}
pub fn separate_ambient_attachment(&self) -> Option<&glin::fbo::ColorAttachment>{
self.attachment(RenderBuffers::AmbientColor)
}
pub fn normals_unresolved_attachment(&self) -> Option<&Rc<glin::fbo::ColorAttachment>>{
self.unresolved_attachment(RenderBuffers::Normals)
}
pub fn position_unresolved_attachment(&self) -> Option<&Rc<glin::fbo::ColorAttachment>>{
self.unresolved_attachment(RenderBuffers::Position)
}
pub fn linear_depth_unresolved_attachment(&self) -> Option<&Rc<glin::fbo::ColorAttachment>>{
self.unresolved_attachment(RenderBuffers::LinearDepth)
}
pub fn separate_ambient_unresolved_attachment(&self) -> Option<&Rc<glin::fbo::ColorAttachment>>{
self.unresolved_attachment(RenderBuffers::AmbientColor)
}
pub fn depth_prepass(&self) -> Option<&glin::Fbo<glin::fbo::ColorAttachment, Rc<glin::fbo::DepthAttachment>>>{
self.depth_prepass.as_ref()
}
pub fn normals_location(&self) -> Option<u32>{
self.attachments_map.get(RenderBuffers::Normals).cloned()
}
pub fn position_location(&self) -> Option<u32>{
self.attachments_map.get(RenderBuffers::Position).cloned()
}
pub fn linear_depth_location(&self) -> Option<u32>{
self.attachments_map.get(RenderBuffers::LinearDepth).cloned()
}
pub fn separate_ambient_location(&self) -> Option<u32>{
self.attachments_map.get(RenderBuffers::AmbientColor).cloned()
}
pub fn outputs_fragment(&self) -> String{
const OUTPUT_FS: &str = include_str!("shaders/outputs.fs.glsl");
let output_position = self.attachments_map.contains_key(RenderBuffers::Position);
let output_normal = self.attachments_map.contains_key(RenderBuffers::Normals);
let output_linear_depth = self.attachments_map.contains_key(RenderBuffers::LinearDepth);
let output_ambient = self.attachments_map.contains_key(RenderBuffers::AmbientColor);
let position_location = self.attachments_map.get(RenderBuffers::Position)
.cloned().unwrap_or(0);
let normal_location = self.attachments_map.get(RenderBuffers::Normals)
.cloned().unwrap_or(0);
let linear_depth_location = self.attachments_map.get(RenderBuffers::LinearDepth)
.cloned().unwrap_or(0);
let ambient_location = self.attachments_map.get(RenderBuffers::AmbientColor)
.cloned().unwrap_or(0);
OUTPUT_FS
.replace("${output_position}", &(output_position as u8).to_string())
.replace("${output_normal}", &(output_normal as u8).to_string())
.replace("${output_linear_depth}", &(output_linear_depth as u8).to_string())
.replace("${output_ambient}", &(output_ambient as u8).to_string())
.replace("${position_location}", &position_location.to_string())
.replace("${normal_location}", &normal_location.to_string())
.replace("${linear_depth_location}", &linear_depth_location.to_string())
.replace("${ambient_location}", &ambient_location.to_string())
}
pub fn render_buffer(&mut self, stage: RenderStage) -> &Rc<super::OpaqueRenderSurface>{
for changed in self.changed.values(){
changed.set(true);
}
self.depth_changed.set(true);
self.last_stage = stage;
&self.render_buffer
}
pub fn color_depth_only_fbo(&mut self, stage: RenderStage) -> super::OtherRenderSurface{
self.changed[RenderBuffers::Color].set(true);
self.depth_changed.set(true);
self.last_stage = stage;
let color = self.color_unresolved_attachment();
let depth = self.depth_unresolved_attachment();
self.aux_fbo.with(vec![&**color], &**depth).unwrap()
}
pub fn last_stage(&self) -> RenderStage {
self.last_stage
}
pub fn viewport(&self) -> glin::Rect{
self.render_buffer.viewport()
}
}
pub(crate) struct DepthPrepass;
pub struct GeometryWithModelsIndex(pub Vec<(Rc<RefCell<glin::Vao>>, GLenum)>);
impl Deref for GeometryWithModelsIndex {
type Target = Vec<(Rc<RefCell<glin::Vao>>, GLenum)>;
fn deref(&self) -> &Vec<(Rc<RefCell<glin::Vao>>, GLenum)>{
&self.0
}
}
impl DerefMut for GeometryWithModelsIndex {
fn deref_mut(&mut self) -> &mut Vec<(Rc<RefCell<glin::Vao>>, GLenum)>{
&mut self.0
}
}