Skip to content

Commit ffd415b

Browse files
committed
Demonstrate lighting in solids demo
1 parent a3328bd commit ffd415b

File tree

1 file changed

+74
-24
lines changed

1 file changed

+74
-24
lines changed

demos/src/bin/solids.rs

Lines changed: 74 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ use minifb::{Key, KeyRepeat};
44

55
use re::prelude::*;
66

7+
use re::core::render::light::normalize_approx;
78
use re::core::{
89
geom::Polyline,
910
math::{ProjMat3, ProjVec3, color::gray},
10-
render::cam::Fov,
11-
render::{Model, ModelToWorld, shader},
11+
render::{
12+
Model, View, World, cam::Fov, debug::dir_to_rgb, light::Kind, shader,
13+
},
1214
};
1315
use re::front::{Frame, minifb::Window};
1416
use re::geom::{io::read_obj, solids::*};
@@ -47,6 +49,17 @@ impl Carousel {
4749
}
4850
}
4951

52+
#[inline]
53+
fn phong<B>(
54+
normal: Vec3<B>,
55+
view_dir: Vec3<B>,
56+
light_dir: Vec3<B>,
57+
r: i32,
58+
) -> f32 {
59+
let refl_dir = light_dir.reflect(normal);
60+
view_dir.dot(&refl_dir).max(0.0).powi(r)
61+
}
62+
5063
fn main() {
5164
eprintln!("Press Space to cycle between objects...");
5265

@@ -59,36 +72,70 @@ fn main() {
5972

6073
let (w, h) = win.dims;
6174
let cam = Camera::new(win.dims)
62-
.transform(scale3(1.0, -1.0, -1.0).to())
75+
.transform(Mat4::identity())
6376
.perspective(Fov::Equiv35mm(28.0), 0.1..1000.0)
6477
.viewport(pt2(10, h - 10)..pt2(w - 10, 10));
6578

79+
type Varyings = (Point3<View>, Normal3);
6680
type VertexIn = Vertex3<Normal3>;
67-
type VertexOut = Vertex<ProjVec3, Color3f>;
68-
type Uniform<'a> = (&'a ProjMat3<Model>, &'a Mat4);
81+
type VertexOut = Vertex<ProjVec3, Varyings>;
82+
struct Uniform {
83+
pub mv: Mat4<Model, View>,
84+
pub proj: ProjMat3<View>,
85+
pub norm: Mat4,
86+
pub light: Light<View>,
87+
}
6988

70-
fn vtx_shader(v: VertexIn, (mvp, spin): Uniform) -> VertexOut {
89+
#[inline]
90+
fn vtx_shader(v: VertexIn, u: &Uniform) -> VertexOut {
7191
// Transform vertex normal
72-
let norm = spin.apply(&v.attrib);
92+
let view_normal = u.norm.apply(&v.attrib);
93+
7394
// Calculate diffuse shading
74-
let diffuse = (norm.z() + 0.2).max(0.2) * 0.8;
75-
// Visualize normal by mapping to RGB values
76-
let [r, g, b] = (0.45 * (v.attrib + splat(1.1))).0;
77-
let col = diffuse * rgb(r, g, b);
78-
vertex(mvp.apply(&v.pos), col)
95+
// let diffuse = (norm.z() + 0.2).max(0.2) * 0.8;
96+
// // Visualize normal by mapping to RGB values
97+
// let [r, g, b] = (0.45 * (v.attrib + splat(1.1))).0;
98+
// let col = diffuse * rgb(r, g, b);
99+
100+
let view_pos = u.mv.apply(&v.pos);
101+
let clip_pos = u.proj.apply(&view_pos);
102+
vertex(clip_pos, (view_pos, view_normal))
79103
}
80104

81-
fn frag_shader(f: Frag<Color3f>, _: Uniform) -> Color4 {
82-
f.var.to_color4()
105+
#[inline]
106+
fn frag_shader(f: Frag<Varyings>, u: &Uniform) -> Color4 {
107+
let (view_pos, view_normal) = f.var;
108+
109+
let (light_col, light_dir) = u.light.eval(view_pos);
110+
let camera_dir = -normalize_approx(view_pos.to_vec());
111+
//let view_normal = normalize_approx(view_normal);
112+
113+
let ambient = rgb(0.15, 0.18, 0.25);
114+
115+
let diffuse = 0.4 * light_dir.dot(&view_normal.to());
116+
117+
let specular = 0.4 * phong(view_normal.to(), camera_dir, light_dir, 30);
118+
119+
let color = gray(1.0);
120+
121+
(light_col * color * diffuse + light_col * specular + ambient)
122+
.to_color4()
123+
//color.to_color4()
83124
}
84125

85126
let shader = shader::new(vtx_shader, frag_shader);
86127

87-
let objects = objects_n(8);
128+
let objects = objects_n(16);
88129

89-
let translate = translate(-3.0 * Vec3::Z);
130+
let translate = translate(3.0 * Vec3::Z);
90131
let mut carousel = Carousel::default();
91132

133+
let _light: Light<World> =
134+
Light::new(rgb(1.0, 1.0, 1.0), Kind::Directional(vec3(0.0, 0.0, -1.0)));
135+
136+
let light: Light<World> =
137+
Light::new(rgb(1.0, 0.9, 0.6), Kind::Point(pt3(-2.0, 3.0, 1.0)));
138+
92139
win.run(|frame| {
93140
let Frame { t, dt, win, .. } = frame;
94141

@@ -102,19 +149,22 @@ fn main() {
102149
let carouse = carousel.update(dt.as_secs_f32());
103150

104151
// Compose transform stack
105-
let model_view_project: ProjMat3<Model> = spin
106-
.then(&translate)
107-
.then(&carouse)
108-
.to::<ModelToWorld>()
109-
.then(&cam.world_to_project());
152+
let modelview: Mat4<Model, View> =
153+
spin.then(&translate).then(&carouse).to();
110154

111155
let object = &objects[carousel.idx % objects.len()];
112156

157+
let uniform = &Uniform {
158+
mv: modelview,
159+
proj: cam.project,
160+
norm: spin,
161+
light: light.transform(&cam.world_to_view()),
162+
};
113163
Batch {
114164
prims: object.faces.clone(),
115165
verts: object.verts.clone(),
116-
uniform: (&model_view_project, &spin),
117-
shader: shader,
166+
uniform,
167+
shader,
118168
viewport: cam.viewport,
119169
target: frame.buf,
120170
ctx: &*frame.ctx,
@@ -148,7 +198,7 @@ fn objects_n(res: u32) -> [Mesh<Normal3>; 14] {
148198
lathe(sectors),
149199
Sphere { radius: 1.0, sectors, segments, }.build(),
150200
Cylinder { radius: 0.8, sectors, segments, capped: true }.build(),
151-
Cone { base_radius: 1.1, apex_radius: 0.3, sectors, segments, capped: true }.build(),
201+
Cone { base_radius: 1.0, apex_radius: 0.3, sectors, segments, capped: true }.build(),
152202
Capsule { radius: 0.5, sectors, body_segments, cap_segments }.build(),
153203
Torus { major_radius: 0.9, minor_radius: 0.3, major_sectors, minor_sectors }.build(),
154204

0 commit comments

Comments
 (0)