cafe/render/
render3D.rs

1extern crate tea;
2
3use tea::{DrawMode, GlUniform, GlUse, GlBind, GlTarget, GlObject, ClearFlags, EnableFlags, BlendFunc};
4use tea::vertex::{VertexArray, VertexData, VertexFormatBuilder, VertexFormat};
5use tea::impl_vertexdata;
6use tea::vec::*;
7use tea::glsl::{Program, ShaderBuilder, ShaderType};
8use tea::texture::{Sampler2D, Texture2D};
9use tea::buffer::{ArrayBuffer, ElementArrayBuffer, BufferUsage, GlBuffer};
10use tea::target::Framebuffer;
11
12use crate::render::{Render, Canvas, Camera, Buffer, Batch, Image, Effect, Movement};
13
14impl_vertexdata!(Vertex3D, Vec3, Vec2, Vec3, Vec4);
15
16pub type VertexBuffer = Buffer<ArrayBuffer, Vertex3D>;
17pub type IndexBuffer = Buffer<ElementArrayBuffer, u32>;
18
19impl VertexBuffer {
20    pub fn new(size: usize) -> Result<Self, String> {
21        let handle = ArrayBuffer::new();
22        let data: Vec<Vertex3D> = Vec::with_capacity(size);
23        handle.bind();
24        handle.data(&data, BufferUsage::DynamicDraw);
25        handle.unbind();
26        Ok(Self {
27            handle,
28            data
29        })
30    }
31}
32
33impl IndexBuffer {
34    pub fn new(size: usize) -> Result<Self, String> {
35        let handle = ElementArrayBuffer::new();
36        let data: Vec<u32> = Vec::with_capacity(size);
37        handle.bind();
38        handle.data(&data, BufferUsage::StaticDraw);
39        handle.unbind();
40        Ok(Self {
41            handle,
42            data
43        })
44    }
45}
46
47#[derive(Default, Debug, Copy, Clone)]
48pub struct Camera3D {
49    position: Vec3,
50    front: Vec3,
51    up: Vec3,
52    right: Vec3,
53    world_up: Vec3,
54
55    yaw: f32, pitch: f32,
56
57    move_speed: f32,
58    mouse_sensitivity: f32,
59    zoom: f32,
60
61    near: f32, far: f32,
62
63    width: f32, height: f32,
64}
65
66impl Camera for Camera3D {
67    fn position(&self) -> &Vec3 { &self.position }
68    fn set_position(&mut self, position: Vec3) { self.position = position; }
69
70    fn set_width(&mut self, width: f32) {
71        self.width = width;
72    }
73
74    fn set_height(&mut self, height: f32) {
75        self.height = height;
76    }
77
78    fn projection(&self) -> Mat4 {
79        Mat4::perspective(self.zoom.to_radians(), self.width / self.height, self.near, self.far)
80    }
81
82    fn view(&self) -> Mat4 {
83        Mat4::look_at(self.position, self.position + self.front, self.up)
84    }
85
86    fn move_camera(&mut self, dir: Movement, dt: f32) {
87        let velocity = self.move_speed * dt;
88        match dir {
89            Movement::Forward => { self.position += self.front.scalar(velocity); },
90            Movement::Backward => { self.position -= self.front.scalar(velocity); },
91            Movement::Right => { self.position += self.right.scalar(velocity); },
92            Movement::Left => { self.position -= self.right.scalar(velocity); },
93            Movement::Up => { self.position += self.up.scalar(velocity); },
94            Movement::Down => { self.position -= self.up.scalar(velocity); },
95        }
96    }
97}
98
99impl Camera3D {
100    pub fn new(position: Vec3) -> Self {
101        let up = Vec3::up();
102
103        let mut camera = Self::default();
104        camera.position = position;
105        camera.front = Vec3::front();
106        camera.up = up;
107        camera.world_up = up;
108        camera.yaw = -90.0;
109        camera.pitch = 0.0;
110        camera.move_speed = 2.5;
111        camera.mouse_sensitivity = 0.1;
112        camera.near = 0.1;
113        camera.far = 100.0;
114        camera.zoom = 45_f32;
115        camera.update();
116
117        camera
118    }
119
120    fn update(&mut self) {
121        let mut front: Vec3 = Vec3::zero();
122        front.x = self.yaw.to_radians().cos() * self.pitch.to_radians().cos();
123        front.y = self.pitch.to_radians().sin();
124        front.z = self.yaw.to_radians().sin() * self.pitch.to_radians().cos();
125        self.front = front.normalize();
126
127        self.right = self.front.cross(&self.world_up).normalize();
128        self.up = self.right.cross(&self.front).normalize();
129    }
130
131    pub fn view_projection(&self) -> Mat4 {
132        let projection = Mat4::perspective(self.zoom, 16.0 / 9.0, self.near, self.far);
133        let view = Mat4::look_at(self.position, self.position + self.front, self.up);
134        view * projection
135    }
136}
137
138
139pub trait Light {
140    fn ambient(&self) -> &Vec3;
141    fn diffuse(&self) -> &Vec3;
142    fn specular(&self) -> &Vec3;
143}
144
145#[repr(C)]
146#[derive(Default, Debug, Copy, Clone)]
147pub struct BaseLight {
148    ambient: Vec3,
149    diffuse: Vec3,
150    specular: Vec3,
151}
152
153impl Light for BaseLight {
154    fn ambient(&self) -> &Vec3 { &self.ambient }
155    fn diffuse(&self) -> &Vec3 { &self.diffuse }
156    fn specular(&self) -> &Vec3 { &self.specular }
157}
158
159#[repr(C)]
160#[derive(Default, Debug, Copy, Clone)]
161pub struct PointLight {
162    position: Vec3,
163    base: BaseLight,
164    
165    constant: f32,
166    linear: f32,
167    quadratic: f32,
168}
169
170impl Light for PointLight {
171    fn ambient(&self) -> &Vec3 { self.base.ambient() }
172    fn diffuse(&self) -> &Vec3 { self.base.diffuse() }
173    fn specular(&self) -> &Vec3 { self.base.specular() }
174}
175
176#[repr(C)]
177#[derive(Default, Debug, Copy, Clone)]
178pub struct DirectionalLight {
179    direction: Vec3,
180    base: BaseLight,
181}
182
183impl Light for DirectionalLight {
184    fn ambient(&self) -> &Vec3 { self.base.ambient() }
185    fn diffuse(&self) -> &Vec3 { self.base.diffuse() }
186    fn specular(&self) -> &Vec3 { self.base.specular() }
187}
188
189#[repr(C)]
190#[derive(Default, Debug, Copy, Clone)]
191pub struct Material {
192    ambient: Vec3,
193    diffuse: Vec3,
194    specular: Vec3,
195    shininess: f32,
196}
197
198#[allow(dead_code)]
199#[derive(Default, Debug)]
200pub struct Mesh {
201    vao: VertexArray,
202    vbo: VertexBuffer,
203    ibo: IndexBuffer,
204}
205
206#[derive(Default, Debug, PartialEq, PartialOrd)]
207pub struct Effect3D {
208    program: Program,
209    mvp: i32,
210}
211
212impl Effect3D {
213    pub fn new(position: Option<String>, pixel: Option<String>) -> Result<Effect3D, String> {
214        let mut pos = position.clone();
215        let mut pix = pixel.clone();
216        if position == None {
217            pos = Some("vec4 position(vec3 pos, vec3 normal, mat4 mvp) {
218                // return vec4(pos, 1.0);
219                return mvp * vec4(pos, 1.0);
220            }".to_string());
221        }
222        if pixel == None {
223            pix = Some("vec4 pixel(vec4 color, vec2 texcoord, sampler2D text) {
224                return color * texture(text, texcoord);
225            }".to_string());
226        }
227
228        let vertex = ShaderBuilder::new()
229            .add_input::<Vec3>("a_Position")
230            .add_input::<Vec2>("a_Texcoord")
231            .add_input::<Vec3>("a_Normal")
232            .add_input::<Vec4>("a_Color")
233            .add_output::<Vec4>("v_Color")
234            .add_output::<Vec2>("v_Texcoord")
235            .add_uniform::<Mat4>("u_MVP")
236            .push_pre_main(pos.unwrap().as_str())
237            .set_main("void main() {
238                gl_Position = position(a_Position, a_Normal, u_MVP);
239                v_Color = a_Color;
240                v_Texcoord = a_Texcoord;
241            }")
242            .build(ShaderType::VertexShader)
243            .unwrap();
244
245        let fragment = ShaderBuilder::new()
246            .add_input::<Vec4>("v_Color")
247            .add_input::<Vec2>("v_Texcoord")
248            .add_uniform::<Sampler2D>("u_Texture")
249            .push_pre_main(pix.unwrap().as_str())
250            .set_main("void main() {
251                gl_FragColor = pixel(v_Color, v_Texcoord, u_Texture);
252            }")
253            .build(ShaderType::FragmentShader)
254            .unwrap();
255
256        let program = Program::new().unwrap();
257        program.attach_shader(&vertex);
258        program.attach_shader(&fragment);
259        program.link().expect("Faied to link program");
260
261        let mvp = program.get_uniform_location("u_MVP");
262
263        // let projection = program.get_uniform_location("u_Projection");
264        // let modelview = program.get_uniform_location("u_Modelview");
265
266        Ok(Effect3D {
267            program,
268            mvp,
269        })
270    }
271}
272
273impl Effect for Effect3D {
274    fn send_uniform<T: GlUniform>(&self, name: &str, value: T) {
275        let location = self.program.get_uniform_location(name);
276        self.program.send_uniform(location, value);
277    }
278}
279
280#[derive(Default, Debug)]
281pub struct Render3D {
282    default_effect: Effect3D,
283    white_image: Image,
284    default_canvas: Canvas,
285    camera: Camera3D,
286
287    draw_mode: DrawMode,
288
289    clear_color: Vec4,
290    draw_color: Vec4,
291
292    plane_mesh: Mesh,
293    cube_mesh: Mesh,
294}
295
296impl Render3D {
297    pub fn clear_color(&mut self, color: Vec4) {
298        self.clear_color = color.clone();
299        tea::clear_color(color.x, color.y, color.z, color.w);
300    }
301
302    pub fn setup(&mut self) {
303        self.set_effect(None);
304        // self.white_texture();
305        tea::enable(&[EnableFlags::Blend, EnableFlags::DepthTest]);
306        tea::blend_func(BlendFunc::SrcAlpha, BlendFunc::OneMinusSrcAlpha);
307    }
308
309    fn set_draw_mode(&mut self, mode: DrawMode) {
310    }
311
312    fn set_image(&mut self, image: Option<&Image>) {
313        let i: &Image;
314        if image == None { i = &self.white_image; }
315        else { i = image.unwrap(); }
316        if Texture2D::current_bind() == i.texture.get_id() { return }
317        i.texture.bind();
318    }
319
320    pub fn white_texture(&mut self) {
321        self.white_image.texture.bind();
322    }
323
324    fn draw_mesh(&self, mesh: &Mesh, pos: Vec3) {
325        let model = Mat4::translation_matrix(pos);
326        let mvp = model * self.camera.view() * self.camera.projection();
327        mvp.send_uniform(0);
328        mesh.vao.bind();
329        tea::draw_elements(DrawMode::Triangles, 0, mesh.ibo.len() as i32);
330        mesh.vao.unbind();
331    }
332
333    pub fn draw_plane(&mut self, pos: Vec3) {
334        self.draw_mesh(&self.plane_mesh, pos);
335    }
336
337    pub fn draw_cube(&mut self, pos: Vec3) {
338        self.draw_mesh(&self.cube_mesh, pos);
339    }
340
341    pub fn draw(&self) {}
342}
343
344impl Render for Render3D {
345    type Effect = Effect3D;
346    fn new() -> Self {
347        let default_effect = Effect3D::new(None, None).unwrap();
348        let white_image = Image::new(1, 1, crate::render::PixelFormat::RGBA, vec![255, 255, 255, 255]).unwrap();
349        let clear_color = Vec4::new(0.0, 0.0, 0.0, 0.0);
350        let default_canvas = Canvas::default();
351        let cube_mesh = Mesh::cube();
352
353        let camera = Camera3D::new(Vec3::new(0.0, 0.0, 3.0));
354
355        tea::enable(&[EnableFlags::Blend, EnableFlags::DepthTest]);
356        Render3D {
357            default_effect,
358            white_image,
359            default_canvas,
360            clear_color,
361            cube_mesh,
362            camera,
363            ..Default::default()
364        }
365    }
366
367    fn clear(&self) { tea::clear(&[ClearFlags::ColorBufferBit, ClearFlags::DepthBufferBit]); }
368
369    fn camera(&mut self) -> &mut dyn Camera {
370        &mut self.camera
371    }
372
373    fn begin(&mut self) {
374        self.set_canvas(None);
375        self.set_effect(None);
376        self.set_image(None);
377    }
378
379    fn end(&self) {
380        self.draw();
381    }
382    
383    fn set_canvas(&mut self, canvas: Option<&Canvas>) {
384        let c: &Canvas;
385        if canvas == None { c = &self.default_canvas; }
386        else { c = canvas.unwrap(); }
387        if Framebuffer::current_bind() == c.framebuffer.get_id() { return }
388        c.framebuffer.bind();
389        let right = c.width as f32;
390        let bottom = c.height as f32;
391        self.camera.set_size(right, bottom);
392        tea::viewport(0, 0, c.width, c.height);
393    }
394
395    fn set_effect(&mut self, effect: Option<&Self::Effect>) {
396        let e: &Self::Effect;
397        if effect == None { e = &self.default_effect; }
398        else { e = effect.unwrap(); }
399        e.program.set_used();
400        (self.camera.view() * self.camera.projection()).send_uniform(0);
401    }
402
403    fn on_resize(&mut self, width: i32, height: i32) {
404        self.default_canvas.width = width;
405        self.default_canvas.height = height;
406        self.camera.set_size(width as f32, height as f32);
407
408        tea::viewport(0, 0, width, height);
409    }
410}
411
412// Mesh impl
413
414
415impl Mesh {
416    fn cube() -> Mesh {
417        let vao = VertexArray::new().unwrap();
418        let mut vbo = VertexBuffer::new(24).unwrap();
419        let mut ibo = IndexBuffer::new(36).unwrap();
420        let cube_positions: Vec<f32> = vec![
421            // Front face
422            -0.5, -0.5,  0.5,
423             0.5, -0.5,  0.5,
424             0.5,  0.5,  0.5,
425            -0.5,  0.5,  0.5,
426            
427            // Back face
428            -0.5, -0.5, -0.5,
429             0.5, -0.5, -0.5,
430             0.5,  0.5, -0.5,
431            -0.5,  0.5, -0.5,
432            
433            // Left face
434            -0.5, -0.5, -0.5,
435            -0.5, -0.5,  0.5,
436            -0.5,  0.5,  0.5,
437            -0.5,  0.5, -0.5,
438            
439            // Right face
440             0.5, -0.5, -0.5,
441             0.5, -0.5,  0.5,
442             0.5,  0.5,  0.5,
443             0.5,  0.5, -0.5,
444            
445            // Top face
446            -0.5,  0.5,  0.5,
447             0.5,  0.5,  0.5,
448             0.5,  0.5, -0.5,
449            -0.5,  0.5, -0.5,
450            
451            // Bottom face
452            -0.5, -0.5,  0.5,
453             0.5, -0.5,  0.5,
454             0.5, -0.5, -0.5,
455            -0.5, -0.5, -0.5,
456        ];
457
458        let indices: Vec<u32> = vec![
459            // Front face
460            0, 1, 2, 0, 2, 3,
461            
462            // Back face
463            4, 5, 6, 4, 6, 7,
464            
465            // Left face
466            8, 9, 10, 8, 10, 11,
467            
468            // Right face
469            12, 13, 14, 12, 14, 15,
470            
471            // Top face
472            16, 17, 18, 16, 18, 19,
473            
474            // Bottom face
475            20, 21, 22, 20, 22, 23,
476        ];
477
478        ibo.push_vec(indices);
479        ibo.flush();
480
481        let mut vertices: Vec<Vertex3D> = vec![];
482
483        for i in 0..24 {
484            let vindex = i*3;
485            let x = cube_positions[vindex];
486            let y = cube_positions[vindex+1];
487            let z = cube_positions[vindex+2];
488
489            vertices.push(Vertex3D::from_position(x, y, z));
490        }
491        vbo.push_vec(vertices);
492        vbo.flush();
493
494        vao.bind();
495        vbo.handle.bind();
496        ibo.handle.bind();
497        vao.setup_for::<Vertex3D>();
498        vao.unbind();
499        vbo.handle.unbind();
500        ibo.handle.unbind();
501        Mesh {
502            vao,
503            vbo,
504            ibo,
505        }
506    }
507}
508
509impl Default for Vertex3D {
510    fn default() -> Self {
511        Vertex3D (
512            Vec3::new(0.0, 0.0, 0.0),
513            Vec2::new(0.0, 0.0),
514            Vec3::new(0.0, 0.0, 0.0),
515            Vec4::new(1.0, 1.0, 1.0, 1.0),
516        )
517    }
518}
519
520impl Vertex3D {
521    pub fn from_position(x: f32, y: f32, z: f32) -> Self {
522        Vertex3D(
523            Vec3::new(x, y, z),
524            Vec2::new(0.0, 0.0),
525            Vec3::new(0.0, 0.0, 0.0),
526            Vec4::new(1.0, 1.0, 1.0, 1.0),
527        )
528    }
529}