1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use glin;
use graphics::{self, Vertex3DNormal};
use renderer::{Renderer3d, CreationContext};
use glin::CreationContext as GlinCreationContext;
use std::borrow::Borrow;
use glin::RenderSurface;

pub struct Skybox<C = glin::CubeMap>{
    cubemap: C,
    geometry: glin::SimpleVao<Vertex3DNormal>,
    level: f32,
}

pub struct Builder{
    pub(crate) gl: ::CreationProxy
}

impl Builder{
    pub fn from_cubemap<C: Borrow<glin::CubeMap>>(&self, cubemap: C, radius: f32) -> Skybox<C> {
        let sphere = graphics::sphere(radius, 30, 30);
        let geometry = self.gl.to_simple_vao(&sphere).unwrap();
        Skybox{
            cubemap,
            geometry,
            level: 0.,
        }
    }

    pub fn from_cubemap_level<C: Borrow<glin::CubeMap>>(&self, cubemap: C, radius: f32, level: f32) -> Skybox<C> {
        let sphere = graphics::sphere(radius, 30, 30);
        let geometry = self.gl.to_simple_vao(&sphere).unwrap();
        Skybox{
            cubemap,
            geometry,
            level,
        }
    }

    pub fn from_cubemap_faces<I: glin::Image>(&self, faces: &glin::cubemap::Faces<I>, radius: f32) -> Skybox {
        let cubemap = self.gl.new_cubemap().from_faces(faces).unwrap();
        let sphere = graphics::sphere(radius, 30, 30);
        let geometry = self.gl.to_simple_vao(&sphere).unwrap();
        Skybox{
            cubemap,
            geometry,
            level: 0.,
        }
    }

    pub fn from_cubemap_image<I: glin::CubemapImage>(&self, image: &I, radius: f32) -> Skybox {
        let cubemap = self.gl.new_cubemap().from_cubemap_image(image).unwrap();
        let sphere = graphics::sphere(radius, 30, 30);
        let geometry = self.gl.to_simple_vao(&sphere).unwrap();
        Skybox{
            cubemap,
            geometry,
            level: 0.,
        }
    }

    pub fn from_cubemap_image_level<I: glin::CubemapImage>(&self, image: &I, radius: f32, level: f32) -> Skybox {
        let cubemap = self.gl.new_cubemap().from_cubemap_image(image).unwrap();
        let sphere = graphics::sphere(radius, 30, 30);
        let geometry = self.gl.to_simple_vao(&sphere).unwrap();
        Skybox{
            cubemap,
            geometry,
            level,
        }
    }
}

impl Skybox{
    pub fn level(&self) -> f32{
        self.level
    }

    pub fn set_level(&mut self, level: f32){
        self.level = level;
    }
}

impl<C: Borrow<glin::CubeMap>> ::Render3d for Skybox<C>{
    fn render<R: RenderSurface>(&self, gl: &::Renderer<R>){
        let program = shaders::get_program(gl);
        let uniforms = uniforms!{
            cubemap_tex: self.cubemap.borrow(),
            level: self.level,
        };

        let properties = &[
            glin::Property::CullFace(Some(glin::gl::FRONT)),
            glin::Property::DepthFunc(glin::gl::LEQUAL),
            glin::Property::TextureCubemapSeamless(true),
        ];

        gl.with_properties(properties)
            .draw_vao(&self.geometry, program, &uniforms);

    }
}

mod shaders{
    program_cache!("shaders/skybox.vs.glsl", "shaders/skybox.fs.glsl", get_program, SHADER);
}