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
106
107
108
109
110
111
use std::ffi::CString;
use std::{ptr, str};

pub enum ShaderType {
    Vertex,
    Fragment,
}

fn compile_shader(shader_type: ShaderType, source: String) -> u32 {
    let shader_name;

    let shader = unsafe {
        let shader_type = match shader_type {
            ShaderType::Vertex => {
                shader_name = "Vertex Shader: ";
                gl::VERTEX_SHADER
            },
            ShaderType::Fragment => {
                shader_name = "Fragment Shader: ";
                gl::FRAGMENT_SHADER
            }
        };

        let shader = gl::CreateShader(shader_type);

        let source = CString::new(source.as_str().as_bytes()).unwrap();
        gl::ShaderSource(shader, 1, &source.as_ptr(), ptr::null());
        gl::CompileShader(shader);

        let mut success: i32 = 0;
        gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut success);

        if success != (gl::TRUE as i32) {
            let mut len: i32 = 0;
            gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);

            let mut info_log = Vec::with_capacity(len as usize);
            info_log.set_len((len as usize) - 1);

            gl::GetShaderInfoLog(
                shader,
                len,
                ptr::null_mut(),
                info_log.as_mut_ptr() as *mut i8
            );

            panic!(
                "{}{}",
                shader_name,
                str::from_utf8(&info_log)
                    .ok()
                    .expect("ShaderInfoLog not valid utf8")
            );
        }

        shader
    };

    shader
}

pub fn compile_program(vertex_shader: String, fragment_shader: String) -> u32 {
    let program = unsafe {
        let program = gl::CreateProgram();

        gl::AttachShader(
            program,
            compile_shader(
                ShaderType::Vertex,
                vertex_shader
            )
        );
        gl::AttachShader(
            program,
            compile_shader(
                ShaderType::Fragment,
                fragment_shader
            )
        );
        gl::LinkProgram(program);

        let mut success: i32 = 0;
        gl::GetProgramiv(program, gl::LINK_STATUS, &mut success);

        if success != (gl::TRUE as i32) {
            let mut len: i32 = 0;
            gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);

            let mut info_log = Vec::with_capacity(len as usize);
            info_log.set_len((len as usize) - 1);

            gl::GetProgramInfoLog(
                program,
                len,
                ptr::null_mut(),
                info_log.as_mut_ptr() as *mut i8
            );

            panic!(
                "{}",
                str::from_utf8(&info_log)
                    .ok()
                    .expect("ProgramInfoLog not valid utf8")
            );
        }

        program
    };

    program
}