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 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 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
412impl 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 -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 -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 -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 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 -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 -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 0, 1, 2, 0, 2, 3,
461
462 4, 5, 6, 4, 6, 7,
464
465 8, 9, 10, 8, 10, 11,
467
468 12, 13, 14, 12, 14, 15,
470
471 16, 17, 18, 16, 18, 19,
473
474 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}