sge_rendering 1.2.0

Rendering functionality for SGE
Documentation
use d2::{DrawQueue2D, Renderer2D};
use d3::DrawQueue3D;
use glium::{
    Rect, Surface, Texture2d,
    framebuffer::{DepthRenderBuffer, RenderBuffer, SimpleFrameBuffer},
    texture::{DepthTexture2d, TextureCreationError},
    uniform,
};
use materials::init_materials;
use pipeline::{RenderPipeline, RenderTarget, RenderTexture, empty_render_texture};
use post_processing::render_fullscreen_quad;
use sge_image::Image;
use sge_programs::COPY_PROGRAM;
use sge_textures::{SgeTexture, TextureRef};
use sge_types::MetaballBatch;
use sge_vectors::UVec2;
use sge_window::{get_display, window_size};

pub mod api;
pub mod d2;
pub mod d3;
pub mod materials;
pub mod object_3d;
pub mod pipeline;
pub mod post_processing;
pub mod scissor;
pub mod shapes_3d;

pub struct DrawQueues {
    pub draw_queue_2d: DrawQueue2D,
    pub world_draw_queue_2d: DrawQueue2D,
    pub draw_queue_3d: DrawQueue3D,
}

pub struct RenderState {
    pub render_pipeline: RenderPipeline,
    pub texture_pipeline: Option<RenderPipeline>,
    pub scissor_stack: Vec<Rect>,
    pub a: RenderTexture,
    pub b: RenderTexture,
}

impl RenderState {
    fn rts(output: RenderTarget) -> Result<(RenderTexture, RenderTexture), TextureCreationError> {
        let (w, h) = match output {
            RenderTarget::Screen => {
                let size = window_size().round();
                (size.x as u32, size.y as u32)
            }
            RenderTarget::Texture(rt) => {
                let dimensions = rt.color_texture.get().dimensions;
                (dimensions.x, dimensions.y)
            }
        };
        Ok((empty_render_texture(w, h)?, empty_render_texture(w, h)?))
    }

    fn update_rts<T: Surface>(&mut self, frame: &mut T) {
        let dimensions = frame.get_dimensions();
        let (w, h) = (dimensions.0, dimensions.1);
        let facade = get_display();
        let samples = 4;

        if self.a.dimensions.x != w || self.a.dimensions.y != h {
            for tex in [&mut self.a, &mut self.b] {
                tex.color_texture.gl_texture = Texture2d::empty(facade, w, h).unwrap();
                tex.depth_texture = DepthTexture2d::empty(facade, w, h).unwrap();
                tex.msaa_color = RenderBuffer::new_multisample(
                    facade,
                    glium::texture::UncompressedFloatFormat::U8U8U8U8,
                    w,
                    h,
                    samples,
                )
                .unwrap();
                tex.msaa_depth = DepthRenderBuffer::new_multisample(
                    facade,
                    glium::texture::DepthFormat::I24,
                    w,
                    h,
                    samples,
                )
                .unwrap();
                tex.dimensions = UVec2::new(w, h);
                tex.color_texture.normalized_dimensions =
                    SgeTexture::create_normalized_dimensions(w, h);
                tex.color_texture.dimensions = UVec2::new(w, h);
            }
        }
    }
}

sge_global::global!(RenderState, render_state);

pub fn init() {
    object_3d::init();
    pipeline::init();

    let (a, b) = RenderState::rts(RenderTarget::Screen).unwrap();
    set_render_state(RenderState {
        render_pipeline: RenderPipeline::screen(),
        texture_pipeline: None,
        scissor_stack: vec![],
        a,
        b,
    });
    log::info!("Initialized render state");
    init_materials();
    log::info!("Initialized materials");
    unsafe { MetaballBatch::init_storage() };
}

pub fn dq2d() -> Renderer2D {
    get_render_state()
        .render_pipeline
        .draw_queue_2d()
        .renderer()
}

pub fn wdq2d() -> Renderer2D {
    get_render_state()
        .render_pipeline
        .world_draw_queue_2d()
        .renderer()
}

pub fn take_screenshot() -> TextureRef {
    texture_create_clone(get_render_state().a.color_texture)
}

pub fn take_screenshot_image() -> Image {
    get_render_state().a.color_texture.download_to_image()
}

pub fn window_texture() -> TextureRef {
    get_render_state().a.color_texture
}

pub fn texture_create_clone(texture: TextureRef) -> TextureRef {
    let facade = get_display();
    let w = texture.gl_texture.width();
    let h = texture.gl_texture.height();

    let new_texture = Texture2d::empty(facade, w, h).unwrap();

    {
        let mut fb = SimpleFrameBuffer::new(facade, &new_texture).unwrap();
        let uniforms = uniform! { tex: texture.gl_texture.sampled() };
        render_fullscreen_quad(&mut fb, COPY_PROGRAM.get(), &uniforms).unwrap();
    }

    SgeTexture {
        gl_texture: new_texture,
        dimensions: texture.dimensions,
        normalized_dimensions: texture.normalized_dimensions,
        magnify_filter: texture.magnify_filter,
        minify_filter: texture.minify_filter,
    }
    .create()
}