@@ -171,8 +171,19 @@ Matrix4x4 Camera::projective() const {
171171 }
172172
173173Matrix4x4 Camera::viewShadow (const Vec3& lightDir, size_t layer) const {
174- // Vec3 ldir = Vec3::normalize({1,1,0});
175- Vec3 ldir = lightDir;
174+ Vec3 ldir = lightDir;
175+ float eps = 0 .005f ;
176+
177+ if (std::abs (ldir.y )<eps) {
178+ float k = (1 .f -eps*eps)/std::sqrt (ldir.x *ldir.x + ldir.z *ldir.z );
179+ ldir.y = (ldir.y <0 ) ? -eps : eps;
180+ ldir.x *= k;
181+ ldir.z *= k;
182+ }
183+
184+ // if(layer==1)
185+ // return viewShadow2(ldir,layer);
186+
176187 Vec3 center = cameraPos;
177188 auto vp = viewProj ();
178189 vp.project (center);
@@ -183,21 +194,21 @@ Matrix4x4 Camera::viewShadow(const Vec3& lightDir, size_t layer) const {
183194 vp.project (r);
184195
185196 float smWidth = 0 ;
186- float smWidthInv = 0 ;
187- float zScale = 1 .f /5120 ;
188-
197+ float smDepth = 5120 *5 ;
189198 switch (layer) {
190199 case 0 :
191200 smWidth = (r-l).length ();
192201 smWidth = std::max (smWidth,1024 .f ); // ~4 pixels per santimeter
202+ smDepth = 5120 ;
193203 break ;
194204 case 1 :
195205 smWidth = 5120 ;
196- zScale *= 0 . 2f ;
206+ smDepth = 5120 * 5 ;
197207 break ;
198208 };
199209
200- smWidthInv = 1 .f /smWidth;
210+ float smWidthInv = 1 .f /smWidth;
211+ float zScale = 1 .f /smDepth;
201212
202213 float rotation = (180 +src.spin .y -rotOffset.y );
203214
@@ -209,9 +220,10 @@ Matrix4x4 Camera::viewShadow(const Vec3& lightDir, size_t layer) const {
209220 view.translate (cameraPos);
210221 view.scale (-1 ,-1 ,-1 );
211222
223+ // sun direction
212224 if (ldir.y !=0 .f ) {
213- float lx = ldir.x /ldir.y ;
214- float lz = ldir.z /ldir.y ;
225+ float lx = ldir.x /std::abs ( ldir.y ) ;
226+ float lz = ldir.z /std::abs ( ldir.y ) ;
215227
216228 const float ang = -rotation*float (M_PI)/180 .f ;
217229 const float c = std::cos (ang), s = std::sin (ang);
@@ -223,7 +235,28 @@ Matrix4x4 Camera::viewShadow(const Vec3& lightDir, size_t layer) const {
223235 view.set (1 ,1 , dz*smWidthInv);
224236 }
225237
238+ // strectch shadowmap on light dir
239+ if (ldir.y !=0 .f ) {
240+ // stetch view to camera
241+ float r0 = std::fmod (rotation, 360 .f );
242+ float r = std::fmod (std::atan2 (ldir.z ,ldir.x )*180 .f /float (M_PI), 360 .f );
243+ r -= r0;
244+
245+ float s = std::abs (ldir.y );
246+ Matrix4x4 proj;
247+ proj.identity ();
248+ proj.rotate ( r, 0 , 0 , 1 );
249+ proj.translate (-0 .5f ,0 ,0 );
250+ proj.scale (s, 1 , 1 );
251+ // proj.scale(0.1f, 1, 1);
252+ proj.translate (0 .5f ,0 ,0 );
253+ proj.rotate (-r, 0 , 0 , 1 );
254+ proj.mul (view);
255+ view = proj;
256+ }
257+
226258 if (layer>0 ) {
259+ // projective shadowmap
227260 Tempest::Matrix4x4 proj;
228261 proj.identity ();
229262
@@ -239,24 +272,25 @@ Matrix4x4 Camera::viewShadow(const Vec3& lightDir, size_t layer) const {
239272 inv.project (mid);
240273 view.translate (mid-cameraPos);
241274
242- Matrix4x4 proj;
243- proj. identity () ;
244-
245- switch (layer) {
246- case 0 :
247- proj.translate (0 .f , 0 .8f , 0 .5f );
248- break ;
249- case 1 : {
250- proj.translate (0 .f , 0 .5f , 0 .5f );
251- proj. scale ( 1 ,( 0 . 5f +ldir. y )/ 1 . 5f , 1 ) ;
252- break ;
275+ {
276+ Matrix4x4 proj;
277+ proj. identity ();
278+ switch (layer) {
279+ case 0 :
280+ proj.translate (0 .f , 0 .8f , 0 .5f );
281+ break ;
282+ case 1 : {
283+ proj.translate (0 .f , 0 .5f , 0 .5f );
284+ break ;
285+ }
253286 }
287+
288+ proj.mul (view);
289+ view = proj;
254290 }
255291
256- proj.mul (view);
257- return proj;
292+ return view;
258293 }
259-
260294float Camera::zNear () const {
261295 return 0 .01f ;
262296 }
0 commit comments