summaryrefslogtreecommitdiff
path: root/webhogg/wasm/src/context/webgl.rs
blob: 8883835f3b97dec7413d26742251a6b71fc58e01 (plain)
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
pub use web_sys::{
    WebGl2RenderingContext as GlContext,
    WebGlProgram, WebGlShader,
    WebGlBuffer, WebGlVertexArrayObject,
};
use wasm_bindgen::prelude::*;
use std::fmt::Display;

pub struct Color4(f32, f32, f32, f32);

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace=Float32Array, js_name=of, variadic)]
    fn _create_f32_buffer(args: &[f32]) -> js_sys::Float32Array;
}

#[derive(Debug)]
pub enum ShaderType {
    Vertex,
    Fragment,
}

impl Display for ShaderType {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl ShaderType {
    pub fn to_id(&self) -> u32 {
        match self {
            ShaderType::Vertex => GlContext::VERTEX_SHADER,
            ShaderType::Fragment => GlContext::FRAGMENT_SHADER,
        }
    }
}

impl Color4 {
    pub fn new(r: f32, g: f32, b: f32, a: f32) -> Color4 {
        Color4(r, g, b, a)
    }
}

pub fn create_f32_buffer(buffer: &[f32]) -> js_sys::Float32Array {
    _create_f32_buffer(buffer)
}

pub struct WebGl2 {
    gl: GlContext,
}

impl WebGl2 {
    pub fn from_context(context: GlContext) -> Self {
        WebGl2 {
            gl: context,
        }
    }

    pub fn create_program(&self) -> Result<WebGlProgram, ()> {
        self.gl.create_program().ok_or(())
    }

    pub fn create_shader(&self, shader_type: &ShaderType) -> Result<WebGlShader, ()> {
        self.gl.create_shader(shader_type.to_id()).ok_or(())
    }

    pub fn get_error(&self) -> u32 { self.gl.get_error() }
    pub fn shader_source(&self, id: &WebGlShader, source: &str) { self.gl.shader_source(id, source) }
    pub fn compile_shader(&self, id: &WebGlShader) -> Result<(), String> {
        self.gl.compile_shader(id);
        if self.gl.get_shader_parameter(id, GlContext::COMPILE_STATUS) == JsValue::FALSE {
            Err(self.gl.get_shader_info_log(id)
                .unwrap_or("/could not retrieve program information/".to_string()))
        } else { Ok(()) }
    }
    pub fn link_program(&self, id: &WebGlProgram) -> Result<(), String> {
        self.gl.link_program(id);
        if self.gl.get_program_parameter(id, GlContext::LINK_STATUS) == JsValue::FALSE {
            Err(self.gl.get_program_info_log(id)
                .unwrap_or("/could not retrieve program information/".to_string()))
        } else { Ok(()) }
    }
    pub fn attach_shader(&self, program: &WebGlProgram, shader: &WebGlShader) {
        self.gl.attach_shader(program, shader)
    }

    pub fn clear(&self, color: &Color4) {
        self.gl.clear_color(color.0, color.1, color.2, color.3);
        self.gl.clear(GlContext::COLOR_BUFFER_BIT);
    }

    pub fn set_viewport(&self) {
        self.gl.viewport(0, 0, self.gl.drawing_buffer_width(), self.gl.drawing_buffer_height());
    }

    pub fn create_buffer(&self) -> Result<WebGlBuffer, ()> {
        self.gl.create_buffer().ok_or(())
    }

    pub fn bind_array_buffer(&self, buffer: &WebGlBuffer) {
        self.gl.bind_buffer(GlContext::ARRAY_BUFFER, Some(buffer))
    }
    pub fn unbind_array_buffer(&self) { self.gl.bind_buffer(GlContext::ARRAY_BUFFER, None) }

    pub fn array_buffer_data_f32(&self, data: &[f32]) {
        self.gl.buffer_data_with_opt_array_buffer(
            GlContext::ARRAY_BUFFER,
            Some(&create_f32_buffer(data).buffer()),
            GlContext::STATIC_DRAW)
    }

    pub fn create_vertex_array(&self) -> Result<WebGlVertexArrayObject, ()> {
        self.gl.create_vertex_array().ok_or(())
    }
    pub fn bind_vertex_array(&self, array: &WebGlVertexArrayObject) {
        self.gl.bind_vertex_array(Some(array))
    }
    pub fn unbind_vertex_array(&self) { self.gl.bind_vertex_array(None) }
    pub fn vertex_attrib_f32_pointer(&self, location: u32, dim: i32) {
        self.gl.vertex_attrib_pointer_with_i32(location, dim, GlContext::FLOAT, false, 0, 0)
    }

    pub fn draw_triangle_arrays(&self, count: i32) {
        self.gl.draw_arrays(GlContext::TRIANGLES, 0, count)
    }

    pub fn enable_vertex_attrib_array(&self, location: u32) {
        self.gl.enable_vertex_attrib_array(location)
    }

    pub fn use_program(&self, program: &WebGlProgram) {
        self.gl.use_program(Some(program))
    }
}