@@ -4,11 +4,13 @@ use minifb::{Key, KeyRepeat};
44
55use re:: prelude:: * ;
66
7+ use re:: core:: render:: light:: normalize_approx;
78use 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} ;
1315use re:: front:: { Frame , minifb:: Window } ;
1416use 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+
5063fn 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