CAUTION: Currently, this is POC, and in development, so not production ready. If you interest this project, you can see examples dir
threerender is a simple 3D rendering engine. It will target providing feature of fundamental for 3D development.
It is similar to Three.js, but this will be more extensible and work on multiple platforms.
You can use this library as follow.
use std::rc::Rc;
use threerender::color::rgb::RGBA;
use threerender::math::{Quat, Transform, Vec3};
use threerender::mesh::{Sphere, Square};
use threerender::renderer::Renderer;
use threerender::traits::entity::EntityDescriptor;
use threerender::{CameraStyle, LightBaseStyle, LightStyle, RendererBuilder, HemisphereLightStyle};
fn main() {
let (width, height) = (2000, 1500);
let mut renderer_builder = RendererBuilder::new();
renderer_builder.set_width(width);
renderer_builder.set_height(height);
renderer_builder.set_background(RGBA::new(0, 0, 0, 1));
renderer_builder.set_camera(CameraStyle {
width: width as f32,
height: height as f32,
..Default::default()
});
renderer_builder.add_light(LightStyle::with_directional(
"directional".to_owned(),
LightBaseStyle::default(),
None,
));
renderer_builder.add_light(LightStyle::with_hemisphere(
"hemisphere".to_owned(),
HemisphereLightStyle::default(),
Vec3::new(0., 50., 0.),
));
let sphere = Rc::new(Sphere::new(50, 50, None));
renderer_builder.push(EntityDescriptor {
id: "sphere".to_owned(),
mesh: Some(sphere),
fill_color: RGBA::new(255, 255, 255, 255),
transform: Transform::from_translation_rotation_scale(
Vec3::ZERO,
Quat::default(),
Vec3::ONE,
),
state: Default::default(),
reflection: Default::default(),
children: vec![],
..Default::default()
});
let square = Rc::new(Square::new(None));
renderer_builder.push(EntityDescriptor {
id: "square1".to_owned(),
mesh: Some(square.clone()),
fill_color: RGBA::new(0, 255, 0, 255),
transform: Transform::from_translation_rotation_scale(
Vec3::new(0., 0., -3.),
Quat::default(),
Vec3::ONE,
),
state: Default::default(),
reflection: Default::default(),
children: vec![],
..Default::default()
});
renderer_builder.push(EntityDescriptor {
id: "square2".to_owned(),
mesh: Some(square),
fill_color: RGBA::new(255, 0, 0, 255),
transform: Transform::from_translation_rotation_scale(
Vec3::new(-3., 0., -1.),
Quat::default(),
Vec3::ONE,
),
state: Default::default(),
reflection: Default::default(),
children: vec![],
..Default::default()
});
let event_loop = winit::event_loop::EventLoop::new();
let window = winit::window::Window::new(&event_loop).unwrap();
window.set_inner_size(winit::dpi::PhysicalSize::new(
renderer_builder.width(),
renderer_builder.height(),
));
let mut renderer = Renderer::new(&window, renderer_builder);
event_loop.run(move |event, _target, control_flow| {
match event {
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::Resized(size),
..
} => {
renderer.resize(size.width, size.height);
// For macos
window.request_redraw();
}
winit::event::Event::WindowEvent {
event: winit::event::WindowEvent::CloseRequested,
..
} => *control_flow = winit::event_loop::ControlFlow::Exit,
winit::event::Event::RedrawRequested(_) => {
renderer.render();
}
_ => {},
}
});
}
You can try this project by examples.
You can run these examples by below command.
cargo run -p examples_{PROJECT_NAME}
- 3D entities
- Square
- 2D texture rendering
- Sphere
- 2D texture rendering
- Square
- 2D entities
- Lines
- Plane
- 2D texture rendering
- Triangle
- Camera
- Light
- Directional light
- Spot light
- Point light
- Hemisphere light
- Shadow
- Directional shadow
- Opacity
- Soft shadow(PCSS)
- Point light shadow
- Spot light shadow
- Multi light/shadow
- Reflection rate for entity
- 2D texture
- Override shader
- glTF support
- Basic glTF support
- Animation
- PBR
- Normal mapping
- Model transparency
- Extensible window system
- Extendable shader by user
- Custom render process by implementing trait
- Shadow rendering
- Ray tracing
- Performance improvement
- Multiple render target
- https://threejs.org/docs/#api/en/renderers/WebGLMultipleRenderTargets
- User can customize own renderer like the deferred rendering
- dirty check
- Optimize multi object like cloning object and transfer vertex more efficiently
- Mip map for texture
- Provide some functionality to be able to define mip map.
- multi threading
- Optimize image loading. Eg. We should not draw image if image is not visible.
- Level of details for polygon(LOD)
- Multiple render target
- Font
- Integration with 2D library like egui
- Web support / Deno support(native binding)
- Convenient Math API for 3D development