ãã¢ã¯ãã¡ãã«ãããŸã ã ãããžã§ã¯ãã¯Demo_PSSMãšåŒã°ããŸãã ãã«ãããã«ã¯ãVisual Studio 2012/2013ãšCMakeãå¿ èŠã§ãã
ã·ã£ããŠãããã³ã°
ãªãªãžãã«ã®ã·ã£ããŠãããã³ã°ã¢ã«ãŽãªãºã ã¯é·ãéçºæãããŸããã ãã®åäœåçã¯æ¬¡ã®ãšããã§ãã
- å
æºã®äœçœ®ãããã¯ã¹ãã£ïŒã·ã£ããŠãããïŒã«ã·ãŒã³ãæç»ããŸãã ããã§éèŠãªã®ã¯ãç°ãªãã¿ã€ãã®å
æºã§ã¯ããã¹ãŠãå°ãç°ãªãæ¹æ³ã§çºçããããšã§ãã
æåæ§å æºïŒç¹å®ã®è¿äŒŒã«ã¯æ¥å ãå«ãŸãããªã©ïŒã¯ç©ºéå ã«äœçœ®ãæã¡ãŸããããã·ã£ããŠãããã圢æããã«ã¯ãã®äœçœ®ãéžæããå¿ èŠããããŸãã éåžžããªãã¶ãŒããŒã®äœçœ®ã«é¢é£ä»ããããŠããããããªãã¶ãŒããŒã®èŠçå ã«çŽæ¥ãããªããžã§ã¯ãã¯ã·ã£ããŠãããã«å ¥ããŸãã ã¬ã³ããªã³ã°æã«ã¯ ã æ£æ圱ã䜿çšãããŸãã
æ圱å æºïŒäžéæãªã©ã³ãã·ã§ãŒããåããã©ã³ããã¹ãããã©ã€ãïŒã¯ã空éå ã®ç¹å®ã®äœçœ®ãæã¡ãç¹å®ã®æ¹åãžã®å ã®äŒæãå¶éããŸãã ãã®å Žåã«ã·ã£ããŠããããã¬ã³ããªã³ã°ãããšãã¯ãéåžžã®éèŠæ圱è¡åã䜿çšãããŸãã
å šæ¹åæ§ã®å æºïŒçœç±ç¯ãªã©ïŒã¯ã空éå ã«ç¹å®ã®äœçœ®ããããŸããããã¹ãŠã®æ¹åã«å ãåºããŸãã ãã®ãããªå æºããã·ã£ããŠãæ£ããæ§ç¯ããã«ã¯ãç«æ¹äœãã¯ã¹ãã£ïŒãã¥ãŒããããïŒã䜿çšããå¿ èŠããããŸããããã¯ãååãšããŠãã·ãŒã³ãã·ã£ããŠãããã«6åæç»ããããšãæå³ããŸãã ãã¹ãŠã®ã²ãŒã ããã®ãããªå æºããã®åçãªåœ±ãè²·ãããšãã§ããããã§ã¯ãªãããã¹ãŠã®ã²ãŒã ããããå¿ èŠãšããããã§ããããŸããã ãã®ã¢ãããŒãã®åäœåçã«èå³ãããå Žåã¯ããã®ãããã¯ã«é¢ããå€ãèšäºããããŸãã
ããã«ãã·ã£ããŠãããã³ã°ã¢ã«ãŽãªãºã ã®ãµãã¯ã©ã¹ïŒ LiSPSM ã TSM ã PSMãªã©ïŒããããéæšæºã®æ圱ãã¥ãŒãããªãã¯ã¹ã䜿çšããŠã·ã£ããŠã®å質ãåäžãããå ã®ã¢ãããŒãã®æ¬ ç¹ãæé€ããŸãã
ã·ã£ããŠãããã®åœ¢ææ¹æ³ã«é¢ä¿ãªããå æºããæãè¿ãïŒå æºã®äœçœ®ããïŒèŠãããã€ã³ããŸã§ã®è·é¢ããŸãã¯ããè€éãªã¢ã«ãŽãªãºã ã®ãã®è·é¢ã®é¢æ°ãåžžã«å«ãŸããŸãã - ã¡ã€ã³ã«ã¡ã©ããã·ãŒã³ãæããŸãã ãªããžã§ã¯ãã®ãã€ã³ããã·ã£ããŠå ã«ãããã©ãããç解ããã«ã¯ããã®ãã€ã³ãã®åº§æšãã·ã£ããŠãããã®ç©ºéã«å€æããŠæ¯èŒããã ãã§ååã§ãã ã·ã£ããŠãããã®ã¹ããŒã¹ã¯ããã®ãããã®åœ¢æã«äœ¿çšãããæ圱ãã¥ãŒã®ãããªãã¯ã¹ã«ãã£ãŠæ±ºãŸããŸãã ãªããžã§ã¯ãã®ãã€ã³ãã®åº§æšããã®ç©ºéã«è»¢éãã座æšã[-1; -1]ãã[0; 1]ã®ç¯å²ã«å€æããŠããã¯ã¹ãã£åº§æšãååŸããŸãã ååŸãã座æšãç¯å²[0; 1]ã®å€ã«ããããšãå€æããå Žåããã®ãã€ã³ãã¯ã·ã£ããŠãããã«è©²åœãããã·ã§ãŒãã£ã³ã°ãããŠããªããšèŠãªãããšãã§ããŸãã ååŸãããã¯ã¹ãã£åº§æšã«åºã¥ããŠã·ã£ããŠãããããéžæãè¡ã£ãåŸãå æºãšããã«æãè¿ããªããžã§ã¯ãã®ãã€ã³ãéã®è·é¢ãååŸããŸãã ãã®è·é¢ãçŸåšã®ãã€ã³ããšå æºã®éã®è·é¢ãšæ¯èŒãããšãã·ã£ããŠãããã®å€ãå°ããå Žåããã€ã³ãã¯ã·ã£ããŠã«è¡šç€ºãããŸãã ããã¯è«ççãªèŠ³ç¹ããã¯éåžžã«åçŽã§ããã·ã£ããŠãããããã®å€ãå°ããå Žåããã®æç¹ã§å æºã«è¿ããªããžã§ã¯ãããããã·ã£ããŠã«ããŸãã
ã·ã£ããŠãããã³ã°ã¯ããã€ãããã¯ã·ã£ããŠãã¬ã³ããªã³ã°ããããã®æãäžè¬çãªã¢ã«ãŽãªãºã ã§ãã ã¢ã«ãŽãªãºã ã®1ã€ãŸãã¯å¥ã®å€æŽã®å®è£ ã¯ãã»ãšãã©ãã¹ãŠã®ã°ã©ãã£ãã¯ãšã³ãžã³ã§èŠã€ããããšãã§ããŸãã ãã®ã¢ã«ãŽãªãºã ã®äž»ãªå©ç¹ã¯ãä»»æã®å¹ŸäœåŠçã«è€éãªãªããžã§ã¯ãããã·ã£ããŠãè¿ éã«åœ¢æã§ããããšã§ãã ãã ããã¢ã«ãŽãªãºã ã®ããŸããŸãªããªãšãŒã·ã§ã³ã®ååšã¯ãäž»ã«ãã®æ¬ ç¹ã«ãããã®ã§ãããéåžžã«äžå¿«ãªã°ã©ãã£ãã¯ã¢ãŒãã£ãã¡ã¯ãã«ã€ãªããå¯èœæ§ããããŸãã PPSMã«åºæã®åé¡ãšããããå æããæ¹æ³ã«ã€ããŠã¯ã以äžã§èª¬æããŸãã
å¹³è¡åå²ã·ã£ããŠãããã³ã°
次ã®ã¿ã¹ã¯ãèæ ®ããŠãã ããã ãã¬ãŒã€ãŒããããªãé¢ããå Žæã«ãããªããžã§ã¯ããããè¿ãã«ãããªããžã§ã¯ãã®åœ±ã«åœ±é¿ãäžããã«åçãªåœ±ãæãå¿ èŠããããŸãã çŽå°æ¥å ã®ã¿ã«å¶éããŸãã
ãã®çš®ã®ã¿ã¹ã¯ã¯ãå±å€ã²ãŒã ã«ç¹ã«é¢é£ããŠããå ŽåããããŸããå±å€ã²ãŒã ã§ã¯ãç¶æ³ã«ãã£ãŠã¯ããã¬ã€ã€ãŒãç®ã®åã®æ°çŸã¡ãŒãã«ã®æ¯è²ãèŠãããšãã§ããŸãã ãã®å Žåãã·ã£ããŠãããã«èŠãããšæãã»ã©ãããå€ãã®ã¹ããŒã¹ãã·ã£ããŠãããã«åãŸããŸãã ã·ã£ããŠãããå ã®ãªããžã§ã¯ãã®é©åãªè§£å床ãç¶æããããã«ããããèªäœã®è§£å床ãäžããããšãäœåãªããããŸããããã¯æåã«ããã©ãŒãã³ã¹ã®äœäžã«ã€ãªããã次ã«ã¬ã³ããªã³ã°ã¿ãŒã²ããã®æ倧ãµã€ãºã®å¶éã«éããŸãã ãã®çµæãããã©ãŒãã³ã¹ãšåœ±ã®å質ã®ãã©ã³ã¹ãåããªãããã¯ã£ãããšèŠãããšã€ãªã¢ã·ã³ã°å¹æãåãã圱ãåŸãããŸããããŒããã«ãã£ãŠããã¹ã¯ãäžååã§ãã ãã®ãããªè§£æ±ºçã§ã¯æºè¶³ã§ããªãããšã¯æããã§ãã
ãã®åé¡ã解決ããããã«ããã¬ãŒã€ãŒã«è¿ããªããžã§ã¯ãããé ãã«ãããªããžã§ã¯ããããã·ã£ããŠãããã§ããå€ãã®é åãåãåããããªæ圱è¡åãèãåºãããšãã§ããŸãã ããã¯ãPerspective Shadow MappingïŒPSMïŒã¢ã«ãŽãªãºã ãšä»ã®å€ãã®ã¢ã«ãŽãªãºã ã®äž»ãªã¢ã€ãã¢ã§ãã ãã®ã¢ãããŒãã®äž»ãªå©ç¹ã¯ãå®éã«ã·ãŒã³ã®ã¬ã³ããªã³ã°ããã»ã¹ãå€æŽããããã¥ãŒæ圱ã®ãããªãã¯ã¹ã®èšç®æ¹æ³ã®ã¿ãå€æŽãããããšã§ãã ãã®ã¢ãããŒãã¯ãæ¢åã®ã²ãŒã ãŸãã¯ãšã³ãžã³ã«å€§ããªå€æŽãå ããããšãªããæ¢åã®ã²ãŒã ãŸãã¯ãšã³ãžã³ã«ç°¡åã«çµ±åã§ããŸãã ãã®ãããªã¢ãããŒãã®äž»ãªæ¬ ç¹ã¯ãå¢çæ¡ä»¶ã§ãã æ¥æ²¡æã«å€ªéœãã圱ãåŒãç¶æ³ãæ³åããŠãã ããã 倪éœãå°å¹³ç·ã«è¿ã¥ããšãã·ã£ããŠãããå ã®ãªããžã§ã¯ãã倧ããéãªãå§ããŸãã ãã®å Žåãéå®åå°åœ±è¡åã¯ç¶æ³ãæªåãããå¯èœæ§ããããŸãã èšãæãããšãPSMã¯ã©ã¹ã®ã¢ã«ãŽãªãºã ã¯ãç¹å®ã®ç¶æ³ãããšãã°ã倩é è¿ãã®ãåãã®ãªã倪éœãããã²ãŒã ã«åœ±ãæãããå Žåã«ããŸãæ©èœããŸãã
PSSMã¢ã«ãŽãªãºã ã§ã¯ãæ ¹æ¬çã«ç°ãªãã¢ãããŒããææ¡ãããŠããŸãã äžéšã§ã¯ããã®ã¢ã«ãŽãªãºã ã¯ã«ã¹ã±ãŒãã·ã£ããŠãããã³ã° ïŒCSMïŒãšããŠç¥ãããŠããŸãã æ£åŒã«ã¯ããããã¯ç°ãªãã¢ã«ãŽãªãºã ã§ãããPSSMã¯CSMã®ç¹æ®ãªã±ãŒã¹ã§ãããšããèšããŸãã ãã®ã¢ã«ãŽãªãºã ã§ã¯ãã¡ã€ã³ã«ã¡ã©ã®å¯èŠæ§ã®ãã©ãããïŒéå°ïŒãã»ã°ã¡ã³ãã«åå²ããããšãææ¡ãããŠããŸãã PSSMã®å Žå-CSMã®å Žåããã¢ããã³ãã¡ãŒã¯ãªããã³ã°ãã¬ãŒã³ã«å¹³è¡ãªå¢çãæã€-åé¢ã®ã¿ã€ãã¯å³å¯ã«èŠå¶ãããŠããŸããã åã»ã°ã¡ã³ãïŒã¢ã«ãŽãªãºã ã®çšèªã§åå²ïŒããšã«ãç¬èªã®ã·ã£ããŠããããæ§ç¯ãããŸãã åé¢ã®äŸã次ã®å³ã«ç€ºããŸãã
å³ã§ã¯ãå¯èŠæ§ãã©ãããã®3ã€ã®ã»ã°ã¡ã³ããžã®ããŒãã£ã·ã§ã³ã確èªã§ããŸãã åã»ã°ã¡ã³ãã¯ãããŠã³ãã£ã³ã°ããã¯ã¹ã«ãã£ãŠåŒ·èª¿è¡šç€ºãããŸãïŒ3次å 空éã«ã¯ãããã¯ã¹ãããŠã³ãã£ã³ã°ããã¯ã¹ããããŸãïŒã ã¹ããŒã¹ã®ãããã®éãããéšåã®ããããã«ã€ããŠãç¬èªã®ã·ã£ããŠããããæ§ç¯ãããŸãã æ°é ãã®ããèªè ã¯ãããã§ã¯è»žäžã«æŽåããå¢çå¹³è¡å é¢äœã䜿çšããããšã«æ°ä»ãã§ãããã ã¢ã³ãã©ã³ã¹ã䜿çšã§ããŸããããã«ããããªããžã§ã¯ãã¯ãªããã³ã°ã¢ã«ãŽãªãºã ãããã«è€éã«ãªããå æºã®äœçœ®ãããã¥ãŒãããªãã¯ã¹ã圢æãããæ¹æ³ããããã«å€ãããŸãã èŠçã®ãã©ããããæ¡å€§ããã«ã€ããŠãã«ã¡ã©ã«è¿ãã»ã°ã¡ã³ãã®é åã¯ãæãé ãé åãããå€§å¹ ã«å°ãããªãå ŽåããããŸãã ã·ã£ããŠãããã®è§£å床ãåãã§ããã°ãè¿æ¥ãããªããžã§ã¯ãããã®ã·ã£ããŠã®è§£å床ãé«ããªããŸãã GPU Gems 3ã®äžèšã®èšäºã§ã¯ãå¯èŠæ§ãã©ãããã®ããŒãã£ã·ã§ã³è·é¢ãèšç®ããããã«æ¬¡ã®ã¹ããŒã ãææ¡ãããŸããã
ããã§ã iã¯ããŒãã£ã·ã§ã³ã€ã³ããã¯ã¹ã mã¯ããŒãã£ã·ã§ã³ã®æ°ã nã¯ãã¢ã¯ãªããã³ã°ãã¬ãŒã³ãŸã§ã®è·é¢ã fã¯ãã¡ãŒã¯ãªããã³ã°ãã¬ãŒã³ãŸã§ã®è·é¢ã λã¯å¯Ÿæ°ãšåäžã®ããŒãã£ã·ã§ã³ã¹ã±ãŒã«éã®è£éã決å®ããä¿æ°ã§ãã
å®è£ å šè¬
Direct3D 11ããã³OpenGLã§ã®å®è£ ã®PSSMã¢ã«ãŽãªãºã ã«ã¯ãå€ãã®å ±éç¹ããããŸãã ã¢ã«ãŽãªãºã ãå®è£ ããã«ã¯ã以äžãæºåããå¿ èŠããããŸãã
- ããã€ãã®ã·ã£ããŠã«ãŒãïŒããŒãã£ã·ã§ã³ã®æ°ã«å¿ããŠïŒã äžèŠãè€æ°ã®ã·ã£ããŠããããååŸããã«ã¯ããªããžã§ã¯ããæ°åæç»ããå¿ èŠãããããã§ãã å®éããããæ瀺çã«è¡ãå¿ èŠã¯ãããŸãããããŒããŠã§ã¢ã®ã€ã³ã¹ã¿ã³ã¹åã®ã¡ã«ããºã ã䜿çšããŸãã ãããè¡ãã«ã¯ãã¬ã³ããªã³ã°çšã®ãããããã¯ã¹ãã£ã®é åãšåçŽãªå¹ŸäœåŠçã·ã§ãŒããŒãå¿ èŠã§ãã
- ãªããžã§ã¯ããã¯ãªããããã¡ã«ããºã ã ã²ãŒã ã¯ãŒã«ãã®ãªããžã§ã¯ãã¯ãããŸããŸãªå¹ŸäœåŠç圢ç¶ã§ããã空éå ã®ããŸããŸãªäœçœ®ã«ãããŸãã æ¡åŒµãªããžã§ã¯ãã¯è€æ°ã®ã·ã£ããŠãããã§èŠãããšãã§ããå°ããªãªããžã§ã¯ãã¯1ã€ã ãã§èŠãããšãã§ããŸãã ãªããžã§ã¯ãã¯ãé£æ¥ããã»ã°ã¡ã³ãã®å¢çã«çŽæ¥è¡šç€ºã§ããå°ãªããšã2ã€ã®ã·ã£ããŠãããã«æç»ããå¿ èŠããããŸãã ãããã£ãŠããªããžã§ã¯ããã©ã®ã·ã£ããŠãããã®ãµãã»ããã«è©²åœããããå€æããã¡ã«ããºã ãå¿ èŠã§ãã
- æé©ãªããŒãã£ã·ã§ã³æ°ã決å®ããã¡ã«ããºã ã ãã¬ãŒã ããšã®åã»ã°ã¡ã³ãã®ã·ã£ããŠãããã®ã¬ã³ããªã³ã°ã¯ãã³ã³ãã¥ãŒãã£ã³ã°ãªãœãŒã¹ã®æµªè²»ã«ãªãå¯èœæ§ããããŸãã å€ãã®å Žåããã¬ãŒã€ãŒã¯ã²ãŒã ã®äžçã®ã»ãã®äžéšãã圌ã®åã«èŠããŸããïŒããšãã°ã圌ã¯è¶³ã®äžãèŠããã圌ã®åã®å£ã«èŠç·ã眮ãããããŸãïŒã ããã¯ã²ãŒã ã®ã¬ãã¥ãŒã®ã¿ã€ãã«å€§ããäŸåããããšã¯æããã§ããããã®ãããªæé©åãè¡ãããšã¯çŽ æŽãããããšã§ãã
ãã®çµæãã·ã£ããŠããããã¬ã³ããªã³ã°ããããã®æ圱åãããªãã¯ã¹ã圢æããããã®æ¬¡ã®ã¢ã«ãŽãªãºã ãååŸããŸãã
- ææªã®å Žåã®èŠçã®ãã©ããããç Žãè·é¢ãèšç®ããŸãã ææªã®å Žåã¯ããã«ãããŸã-ã«ã¡ã©ã®é ãã¯ãªããã³ã°å¹³é¢ã«åœ±ãèŠããŸãã
ã³ãŒãvoid calculateMaxSplitDistances() { float nearPlane = m_camera.getInternalCamera().GetNearPlane(); float farPlane = m_camera.getInternalCamera().GetFarPlane(); for (int i = 1; i < m_splitCount; i++) { float f = (float)i / (float)m_splitCount; float l = nearPlane * pow(farPlane / nearPlane, f); float u = nearPlane + (farPlane - nearPlane) * f; m_maxSplitDistances[i - 1] = l * m_splitLambda + u * (1.0f - m_splitLambda); } m_farPlane = farPlane + m_splitShift; }
- ã«ã¡ã©ãšåœ±ãèœãšããªããžã§ã¯ãã®æãé ãå¯èŠç¹ã®éã®è·é¢ã決å®ããŸãã ããã§ã¯ããªããžã§ã¯ãã¯åœ±ãèœãšãããšãã§ããèœãšããªãããšã«æ³šæããããšãéèŠã§ãã ããšãã°ãå¹³ããªäžéµã®é¢šæ¯ã¯ã圱ãèœãšããªãããã«ããããšãã§ããŸãããã®å Žåãç
§æã¢ã«ãŽãªãºã ãã·ã§ãŒãã£ã³ã°ãæ
åœããŠããå¯èœæ§ããããŸãã ã·ã£ããŠãæ圱ãããªããžã§ã¯ãã®ã¿ãã·ã£ããŠãããã«æç»ãããŸãã
ã³ãŒãfloat calculateFurthestPointInCamera(const matrix44& cameraView) { bbox3 scenebox; scenebox.begin_extend(); for (size_t i = 0; i < m_entitiesData.size(); i++) { if (m_entitiesData[i].isShadowCaster) { bbox3 b = m_entitiesData[i].geometry.lock()->getBoundingBox(); b.transform(m_entitiesData[i].model); scenebox.extend(b); } } scenebox.end_extend(); float maxZ = m_camera.getInternalCamera().GetNearPlane(); for (int i = 0; i < 8; i++) { vector3 corner = scenebox.corner_point(i); float z = -cameraView.transform_coord(corner).z; if (z > maxZ) maxZ = z; } return std::min(maxZ, m_farPlane); }
- ã¹ããã1ãš2ã§åŸãããå€ã«åºã¥ããŠãæ¬åœã«å¿
èŠãªã»ã°ã¡ã³ãã®æ°ãšãããã®åå²è·é¢ã決å®ããŸãã
ã³ãŒãvoid calculateSplitDistances() { // calculate how many shadow maps do we really need m_currentSplitCount = 1; if (!m_maxSplitDistances.empty()) { for (size_t i = 0; i < m_maxSplitDistances.size(); i++) { float d = m_maxSplitDistances[i] - m_splitShift; if (m_furthestPointInCamera >= d) m_currentSplitCount++; } } float nearPlane = m_camera.getInternalCamera().GetNearPlane(); for (int i = 0; i < m_currentSplitCount; i++) { float f = (float)i / (float)m_currentSplitCount; float l = nearPlane * pow(m_furthestPointInCamera / nearPlane, f); float u = nearPlane + (m_furthestPointInCamera - nearPlane) * f; m_splitDistances[i] = l * m_splitLambda + u * (1.0f - m_splitLambda); } m_splitDistances[0] = nearPlane; m_splitDistances[m_currentSplitCount] = m_furthestPointInCamera; }
- åã»ã°ã¡ã³ãïŒã»ã°ã¡ã³ãã®å¢çã¯è¿è·é¢ãšé è·é¢ã«ãã£ãŠæ±ºå®ãããŸãïŒã«ã€ããŠãå¢çããã¯ã¹ãèšç®ããŸãã
ã³ãŒãbbox3 calculateFrustumBox(float nearPlane, float farPlane) { vector3 eye = m_camera.getPosition(); vector3 vZ = m_camera.getOrientation().z_direction(); vector3 vX = m_camera.getOrientation().x_direction(); vector3 vY = m_camera.getOrientation().y_direction(); float fov = n_deg2rad(m_camera.getInternalCamera().GetAngleOfView()); float aspect = m_camera.getInternalCamera().GetAspectRatio(); float nearPlaneHeight = n_tan(fov * 0.5f) * nearPlane; float nearPlaneWidth = nearPlaneHeight * aspect; float farPlaneHeight = n_tan(fov * 0.5f) * farPlane; float farPlaneWidth = farPlaneHeight * aspect; vector3 nearPlaneCenter = eye + vZ * nearPlane; vector3 farPlaneCenter = eye + vZ * farPlane; bbox3 box; box.begin_extend(); box.extend(vector3(nearPlaneCenter - vX * nearPlaneWidth - vY * nearPlaneHeight)); box.extend(vector3(nearPlaneCenter - vX * nearPlaneWidth + vY * nearPlaneHeight)); box.extend(vector3(nearPlaneCenter + vX * nearPlaneWidth + vY * nearPlaneHeight)); box.extend(vector3(nearPlaneCenter + vX * nearPlaneWidth - vY * nearPlaneHeight)); box.extend(vector3(farPlaneCenter - vX * farPlaneWidth - vY * farPlaneHeight)); box.extend(vector3(farPlaneCenter - vX * farPlaneWidth + vY * farPlaneHeight)); box.extend(vector3(farPlaneCenter + vX * farPlaneWidth + vY * farPlaneHeight)); box.extend(vector3(farPlaneCenter + vX * farPlaneWidth - vY * farPlaneHeight)); box.end_extend(); return box; }
- åã»ã°ã¡ã³ãã®æ圱ãã¥ãŒã®ã·ã£ããŠãããªãã¯ã¹ãèšç®ããŸãã
ã³ãŒãmatrix44 calculateShadowViewProjection(const bbox3& frustumBox) { const float LIGHT_SOURCE_HEIGHT = 500.0f; vector3 viewDir = m_camera.getOrientation().z_direction(); vector3 size = frustumBox.size(); vector3 center = frustumBox.center() - viewDir * m_splitShift; center.y = 0; auto lightSource = m_lightManager.getLightSource(0); vector3 lightDir = lightSource.orientation.z_direction(); matrix44 shadowView; shadowView.pos_component() = center - lightDir * LIGHT_SOURCE_HEIGHT; shadowView.lookatRh(shadowView.pos_component() + lightDir, lightSource.orientation.y_direction()); shadowView.invert_simple(); matrix44 shadowProj; float d = std::max(size.x, size.z); shadowProj.orthoRh(d, d, 0.1f, 2000.0f); return shadowView * shadowProj; }
2ã€ã®ããŠã³ãã£ã³ã°ããã¯ã¹ïŒãªããžã§ã¯ããšå¯èŠæ§ã®ãã©ãããã®ã»ã°ã¡ã³ãïŒã®äº€å·®ã®ç°¡åãªãã¹ãã䜿çšããŠãªããžã§ã¯ããåãåããŸãã èæ ®ãã¹ãéèŠãªæ©èœã1ã€ãããŸãã ãªããžã§ã¯ãã¯èŠããŸãããããããã圱ãèŠããŸãã äžèšã®ã¢ãããŒãã䜿çšãããšãã¡ã€ã³ã«ã¡ã©ã«è¡šç€ºãããŠããªããã¹ãŠã®ãªããžã§ã¯ããåãåããããããããã®åœ±ããªããªãããšãæšæž¬ããã®ã¯ç°¡åã§ãã ãããé²ãããã«ãããªãäžè¬çãªææ³ã䜿çšããŸãããå ã®äŒææ¹åã«æ²¿ã£ãŠãªããžã§ã¯ãã®ããŠã³ãã£ã³ã°ããã¯ã¹ãåŒã£åŒµãããªããžã§ã¯ãã®åœ±ãèŠãã空éé åã®å€§ãŸããªè¿äŒŒå€ãäžããŸããã ãã®çµæããã®ãªããžã§ã¯ããæç»ãããåãªããžã§ã¯ãã«å¯ŸããŠãã·ã£ããŠãããã€ã³ããã¯ã¹ã®é åãäœæãããŸããã
ã³ãŒã
void updateShadowVisibilityMask(const bbox3& frustumBox, const std::shared_ptr<framework::Geometry3D>& entity, EntityData& entityData, int splitIndex) { bbox3 b = entity->getBoundingBox(); b.transform(entityData.model); // shadow box computation auto lightSource = m_lightManager.getLightSource(0); vector3 lightDir = lightSource.orientation.z_direction(); float shadowBoxL = fabs(lightDir.z) < 1e-5 ? 1000.0f : (b.size().y / -lightDir.z); bbox3 shadowBox; shadowBox.begin_extend(); for (int i = 0; i < 8; i++) { shadowBox.extend(b.corner_point(i)); shadowBox.extend(b.corner_point(i) + lightDir * shadowBoxL); } shadowBox.end_extend(); if (frustumBox.clipstatus(shadowBox) != bbox3::Outside) { int i = entityData.shadowInstancesCount; entityData.shadowIndices[i] = splitIndex; entityData.shadowInstancesCount++; } }
次ã«ãã¬ã³ããªã³ã°ããã»ã¹ãšãDirect3D 11ããã³OpenGL 4.3ã®ç¹å®ã®éšåãèŠãŠã¿ãŸãããã
Direct3D 11ã®å®è£
Direct3D 11ã«ã¢ã«ãŽãªãºã ãå®è£ ããã«ã¯ã次ã®ãã®ãå¿ èŠã§ãã
- ã·ã£ããŠããããã¬ã³ããªã³ã°ããããã®ãã¯ã¹ãã£ã®é
åã
D3D11_TEXTURE2D_DESC
æ§é äœD3D11_TEXTURE2D_DESC
ãã®çš®ã®ãªããžã§ã¯ããäœæããD3D11_TEXTURE2D_DESC
ã¯ãD3D11_TEXTURE2D_DESC
ãã£ãŒã«ãããããŸãã ãããã£ãŠãC ++ã³ãŒãã§ã¯ãID3D11Texture2D* array[N]
䌌ããã®ã¯ãããŸããã Direct3D APIã®èŠ³ç¹ããèŠããšããã¯ã¹ãã£é åã¯åäžã®ãã¯ã¹ãã£ãšã¯å°ãç°ãªããŸãã ã·ã§ãŒããŒã§ãã®ãããªé åã䜿çšããå Žåã®éèŠãªæ©èœã¯ãé åå ã®ã©ã®ãã¯ã¹ãã£ãŒããããŸãã¯ãã®ãªããžã§ã¯ããæç»ãããã決å®ã§ããããšã§ãïŒHLSLã®SV_RenderTargetArrayIndex
ã»ãã³ãã£ã¯ã¹ïŒã ããã¯ããã®ã¢ãããŒããšMRTïŒè€æ°ã®ã¬ã³ããŒã¿ãŒã²ããïŒã®äž»ãªéãã§ããMRTã§ã¯ã1ã€ã®ãªããžã§ã¯ããæå®ããããã¹ãŠã®ãã¯ã¹ãã£ã«ããã«æç»ãããŸãã äžåºŠã«è€æ°ã®ã·ã£ããŠã«ãŒãã«æç»ããå¿ èŠããããªããžã§ã¯ãã«ã€ããŠã¯ãããŒããŠã§ã¢ã€ã³ã¹ã¿ã³ã¹åã䜿çšããŸããããã«ãããGPUã¬ãã«ã§ãªããžã§ã¯ããè€è£œã§ããŸãã ãã®å Žåããªããžã§ã¯ããé åå ã®1ã€ã®ãã¯ã¹ãã£ã«æç»ãããã®ã¯ããŒã³ãä»ã®ãã¯ã¹ãã£ã«æç»ã§ããŸãã ã·ã£ããŠãããã§ã¯ã深床å€ã®ã¿ãæ ŒçŽããããããã¯ã¹ãã£åœ¢åŒDXGI_FORMAT_R32_FLOAT
ã䜿çšããŸãã - ç¹å¥ãªãã¯ã¹ãã£ãµã³ãã©ãŒã Direct3D APIã§ã¯ããã¯ã¹ãã£ãããµã³ããªã³ã°ããããã®ç¹å¥ãªãã©ã¡ãŒã¿ãŒãèšå®ã§ããŸããããã«ããããã¯ã¹ãã£ã®å€ãæå®ãããæ°å€ãšæ¯èŒã§ããŸãã ãã®å Žåã®çµæã¯0ãŸãã¯1ã«ãªãããããã®å€ã®éã®é·ç§»ã¯ãç·åœ¢ãŸãã¯ç°æ¹æ§ãã£ã«ã¿ãŒã«ãã£ãŠå¹³æ»åã§ããŸãã
D3D11_SAMPLER_DESC
æ§é äœã«ãµã³ãã©ãŒãäœæããã«ã¯ã次ã®ãã©ã¡ãŒã¿ãŒãèšå®ããŸãã
samplerDesc.Filter = D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; samplerDesc.ComparisonFunc = D3D11_COMPARISON_LESS; samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER; samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER; samplerDesc.BorderColor[0] = 1.0f; samplerDesc.BorderColor[1] = 1.0f; samplerDesc.BorderColor[2] = 1.0f; samplerDesc.BorderColor[3] = 1.0f;
ãããã£ãŠãåç·åœ¢ãã£ã«ã¿ãªã³ã°ããlessãé¢æ°ãšã®æ¯èŒãããã³ç¯å²[0; 1]以å€ã®åº§æšã«ãããã¯ã¹ãã£ããã®ãµã³ããªã³ã°ã«ããã1ïŒã€ãŸãã圱ãªãïŒãè¿ãããŸãã
次ã®ã¹ããŒã ã«åŸã£ãŠã¬ã³ããªã³ã°ããŸãã
- ã·ã£ããŠãããã®é
åãã¯ãªã¢ããŸãã ãªããžã§ã¯ããšå
æºéã®æå°è·é¢ã¯ã·ã£ããŠãããã«ä¿åããããããå€
FLT_MAX
ã¯ãªã¢ããŸãã - ã·ãŒã³ãã·ã£ããŠãããã®é
åã«ã¬ã³ããªã³ã°ããŸãã ãããè¡ãã«ã¯ãæ圱ãã¥ãŒã®ã·ã£ããŠãããªãã¯ã¹ã®é
åãšåãªããžã§ã¯ãã®ã·ã£ããŠãããã€ã³ããã¯ã¹ã®é
åãã·ã§ãŒããŒã«è»¢éããŸãã è€æ°ã®ã·ã£ããŠãããã«æç»ããå¿
èŠããããªããžã§ã¯ãã¯ã
DrawIndexedInstanced
ã¡ãœããã䜿çšããŠã€ã³ã¹ã¿ã³ã¹åããŠæç»ãããŸãã ã·ã£ããŠããããçæããããã®HLSLã·ã§ãŒããŒã以äžã«ç€ºããŸãã
é ç¹ã·ã§ãŒããŒ#include <common.h.hlsl> struct VS_OUTPUT { float4 position : SV_POSITION; float depth : TEXCOORD0; uint instanceID : SV_InstanceID; }; VS_OUTPUT main(VS_INPUT input, unsigned int instanceID : SV_InstanceID) { VS_OUTPUT output; float4 pos = mul(float4(input.position, 1), model); output.position = mul(pos, shadowViewProjection[shadowIndices[instanceID]]); output.depth = output.position.z; output.instanceID = instanceID; return output; }
幟äœåŠã·ã§ãŒããŒ#include <common.h.hlsl> struct GS_INPUT { float4 position : SV_POSITION; float depth : TEXCOORD0; uint instanceID : SV_InstanceID; }; struct GS_OUTPUT { float4 position : SV_POSITION; float depth : TEXCOORD0; uint index : SV_RenderTargetArrayIndex; }; [maxvertexcount(3)] void main(triangle GS_INPUT pnt[3], inout TriangleStream<GS_OUTPUT> triStream) { GS_OUTPUT p = (GS_OUTPUT)pnt[0]; p.index = shadowIndices[pnt[0].instanceID]; triStream.Append(p); p = (GS_OUTPUT)pnt[1]; p.index = shadowIndices[pnt[1].instanceID]; triStream.Append(p); p = (GS_OUTPUT)pnt[2]; p.index = shadowIndices[pnt[2].instanceID]; triStream.Append(p); triStream.RestartStrip(); }
ãã¯ã»ã«ã·ã§ãŒããŒstruct PS_INPUT { float4 position : SV_POSITION; float depth : TEXCOORD0; uint index : SV_RenderTargetArrayIndex; }; float main(PS_INPUT input) : SV_TARGET { return input.depth; }
ãã®çµæãã·ã£ããŠãããã®é åã¯æ¬¡ã®ããã«ãªããŸãã
- ã¡ã€ã³ã«ã¡ã©ããã·ãŒã³ãã¬ã³ããªã³ã°ããŸãã 圱ãå°ããŒãããããããã«ã Percentage Closer Filteringã¢ã«ãŽãªãºã ã䜿çšããŸãã ãã€ã³ãã®ã·ã£ããŠã€ã³ã°ãèšç®ãããšãããã¹ãŠã®ã·ã£ããŠããããããµã³ãã«ãäœæããçµæãæ··åããŸãã ãã®çµæããããŒãå€ãååŸããŸãã0.0ã¯å®å
šã«åœ±ä»ãã®ãã€ã³ããæå³ãã1.0ã¯å®å
šã«åœ±ãªãã®ãã€ã³ããæå³ããŸãã ã·ã§ãŒãã£ã³ã°ãèšç®ããããã®HLSLã®é¢æ°ã以äžã«ç€ºããŸãã
float3 getShadowCoords(int splitIndex, float3 worldPos) { float4 coords = mul(float4(worldPos, 1), shadowViewProjection[splitIndex]); coords.xy = (coords.xy / coords.ww) * float2(0.5, -0.5) + float2(0.5, 0.5); return coords.xyz; } float sampleShadowMap(int index, float3 coords, float bias) { if (coords.x < 0 || coords.x > 1 || coords.y < 0 || coords.y > 1) return 1.0f; float3 uv = float3(coords.xy, index); float receiver = coords.z; float sum = 0.0; const int FILTER_SIZE = 3; const float HALF_FILTER_SIZE = 0.5 * float(FILTER_SIZE); for (int i = 0; i < FILTER_SIZE; i++) { for (int j = 0; j < FILTER_SIZE; j++) { float3 offset = float3(shadowBlurStep * (float2(i, j) - HALF_FILTER_SIZE) / HALF_FILTER_SIZE, 0); sum += shadowMap.SampleCmpLevelZero(shadowMapSampler, uv + offset, receiver - bias); } } return sum / (FILTER_SIZE * FILTER_SIZE); } float shadow(float3 worldPos) { float shadowValue = 0; [unroll(MAX_SPLITS)] for (int i = 0; i < splitsCount; i++) { float3 coords = getShadowCoords(i, worldPos); shadowValue += (1.0 - sampleShadowMap(i, coords, SHADOW_BIASES[i])); } return 1.0 - saturate(shadowValue); }
æåŸã«ã圱ã«å ããŠãã©ã€ãã£ã³ã°ã¢ã«ãŽãªãºã ããã®ã·ã§ãŒãã£ã³ã°ããããšããäºå®ãèæ ®ããå¿ èŠããããŸãïŒç§ã¯Blinn-Fongã©ã€ãã£ã³ã°ã¢ãã«ã䜿çšããŸããïŒã äºéã·ã§ãŒãã£ã³ã°ãé²ãããã«ããã¯ã»ã«ã·ã§ãŒããŒã«æ¬¡ã®ã³ãŒããè¿œå ããŸããã
float shadowValue = shadow(input.worldPos); shadowValue = lerp(1, shadowValue, ndol);
ããã§ã¯ãç §æã¢ãã«ã«å©ç¹ããããŸãã Blinn-Fongã¢ãã«ã«ãããšæãå Žåã圱ã¯è¿œå ãããŸããã 解決çã¯çæ³çã§ãããšäž»åŒµããŠããŸããããããçšåºŠã¯åé¡ãæé€ããŸãã
ãã®çµæã次ã®å³ãåŸãããŸãã
OpenGL 4.3ã®å®è£
OpenGL 4.3ã«ã¢ã«ãŽãªãºã ãå®è£ ããã«ã¯ãDirect3D 11ãšåããã®ããã¹ãŠå¿ èŠã§ããã埮åŠãªç¹ããããŸãã OpenGLã§ã¯ã深床å€ãå«ããã¯ã¹ãã£ïŒããšãã°ã圢åŒ
GL_DEPTH_COMPONENT32F
ïŒã®ã¿ã®æ¯èŒãšçµã¿åãããŠéžæãè¡ãããšãã§ããŸãã ãããã£ãŠã深床ãããã¡ã®ã¿ãã¬ã³ããªã³ã°ããã«ã©ãŒãšã³ããªãåé€ããŸãïŒããæ£ç¢ºã«ã¯ã深床ãããã¡ãæ ŒçŽããããã«ãã¬ãŒã ãããã¡ã«ãã¯ã¹ãã£ã®é åã®ã¿ãã¢ã¿ããããŸãïŒã ããã¯ãäžæ¹ã§ããããªã¡ã¢ãªãå°ãç¯çŽããã°ã©ãã£ãã¯ãã€ãã©ã€ã³ã容æã«ããŸããä»æ¹ã§ã¯ãæ£èŠåããã深床å€ã䜿çšããããšã匷å¶ããŸãã
OpenGLã®éžæãªãã·ã§ã³ã¯ããã¯ã¹ãã£ã«çŽæ¥ãããã³ã°ã§ããŸãã ãããã¯ã以åDirect3D 11ã§æ€èšãããŠãããã®ãšåãã§ãã
const float BORDER_COLOR[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glBindTexture(m_shadowMap->getTargetType(), m_shadowMap->getDepthBuffer()); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_COMPARE_FUNC, GL_LESS); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(m_shadowMap->getTargetType(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameterfv(m_shadowMap->getTargetType(), GL_TEXTURE_BORDER_COLOR, BORDER_COLOR); glBindTexture(m_shadowMap->getTargetType(), 0);
èå³æ·±ãããã»ã¹ã¯ãOpenGLã®å éšã§3次å ã®ãã¯ã¹ãã£ã§è¡šããããã¯ã¹ãã£ã®é åã®äœæã§ãã
glTexStorage3D
ã¯ãããäœæããããã®ç¹å¥ãªé¢æ°ãäœæãããäž¡æ¹ãšã
glTexStorage3D
ã䜿çšããŠäœæãããŸãã GLSLã®
SV_RenderTargetArrayIndex
ã®é¡äŒŒç©ã¯ãçµã¿èŸŒã¿å€æ°
gl_Layer
ã§ãã
ã¬ã³ããªã³ã°ã¹ããŒã ãåããŸãŸã§ãã
- ã·ã£ããŠã«ãŒãã®é åãã¯ãªã¢ããŸãã ãã¬ãŒã ãããã¡ã«ã¯ã«ã©ãŒãã£ã³ãã«ããªãããã深床ãããã¡ã®ã¿ãã¯ãªã¢ããŸãã æ£èŠåããã深床ãããã¡ã®å Žåãæ倧å€ã¯1.0ã«ãªããŸãã
- ã·ã£ããŠããããã¬ã³ããªã³ã°ããŸãã 深床ãããã¡ãŒã®ã¿ã圢æãããããããã©ã°ã¡ã³ãã·ã§ãŒããŒã¯å¿
èŠãããŸããã
é ç¹ã·ã§ãŒããŒ#version 430 core const int MAX_SPLITS = 4; layout(location = 0) in vec3 position; layout(location = 1) in vec3 normal; layout(location = 2) in vec2 uv0; layout(location = 3) in vec3 tangent; layout(location = 4) in vec3 binormal; out VS_OUTPUT { float depth; flat int instanceID; } vsoutput; uniform mat4 modelMatrix; uniform mat4 shadowViewProjection[MAX_SPLITS]; uniform int shadowIndices[MAX_SPLITS]; void main() { vec4 wpos = modelMatrix * vec4(position, 1); vec4 pos = shadowViewProjection[shadowIndices[gl_InstanceID]] * vec4(wpos.xyz, 1); gl_Position = pos; vsoutput.depth = pos.z; vsoutput.instanceID = gl_InstanceID; }
幟äœåŠã·ã§ãŒããŒ#version 430 core const int MAX_SPLITS = 4; layout(triangles) in; layout(triangle_strip, max_vertices = 3) out; in VS_OUTPUT { float depth; flat int instanceID; } gsinput[]; uniform int shadowIndices[MAX_SPLITS]; void main() { for (int i = 0; i < gl_in.length(); i++) { gl_Position = gl_in[i].gl_Position; gl_Layer = shadowIndices[gsinput[i].instanceID]; EmitVertex(); } EndPrimitive(); }
- ã¡ã€ã³ã«ã¡ã©ããã·ãŒã³ãã¬ã³ããªã³ã°ããŸãã ã·ã§ãŒãã£ã³ã°ãèšç®ãããšããäž»ãªããšã¯ãçŸåšã®ãã€ã³ããšå
æºïŒã³ãŒãã®
coords.z
ïŒéã®è·é¢ãç¯å²[0; 1]ã«å€æããããšãå¿ããªãããšã§ãã
vec3 getShadowCoords(int splitIndex, vec3 worldPos) { vec4 coords = shadowViewProjection[splitIndex] * vec4(worldPos, 1); coords.xyz = (coords.xyz / coords.w) * vec3(0.5) + vec3(0.5); return coords.xyz; }
ãã®çµæãDirect3D 11ãšã¯ãããã«ç°ãªãç»åãåŸãããŸãïŒèå³æ·±ããããå¥ã®è§åºŠãã衚瀺ããŸãïŒã
åé¡
ã·ã£ããŠãããã³ã°ã¢ã«ãŽãªãºã ãšãã®ä¿®æ£ã«ã¯å€ãã®åé¡ããããŸãã å€ãã®å Žåãã¢ã«ãŽãªãºã ã¯ç¹å®ã®ã²ãŒã ãŸãã¯ç¹å®ã®ã·ãŒã³ã«åãããŠæ éã«èª¿æŽããå¿ èŠããããŸãã æãäžè¬çãªåé¡ãšè§£æ±ºçã®ãªã¹ãã¯ã ããã«ãããŸã ã PSSMãå®è£ ãããšãã«ã次ã®ããšã«æ°ä»ããŸããã
- ãªãã¶ãŒããŒã®èåŸã«ãããªããžã§ã¯ãããã®åœ±ã®æ¶å€±ã ã·ã£ããŠã«ãŒãã¯ããã®ã«ãã¬ããžãã¡ã€ã³ã«ã¡ã©ããã®å¯èŠæ§ã®ãã©ãããã«å¯èœãªéãäžèŽããããã«é 眮ããŸãã ãããã£ãŠããªãã¶ãŒããŒã®èåŸã«ãããªããžã§ã¯ãã¯ãåçŽã«ãããã«èœã¡ãŸããã æ圱ãã¥ãŒã®ã·ã£ããŠãããªãã¯ã¹ãèšç®ããã¢ã«ãŽãªãºã ã§ãããžã§ã³ãã¯ãã«ãšã¯å察ã®æ¹åã«ã·ãããå°å ¥ããããšã«ããããã®ã¢ãŒãã£ãã¡ã¯ããå¹³æ»åããŸããã ãã¡ãããããã¯æ¥æ²¡æã®é·ã圱ãé«ããªããžã§ã¯ãããã®åœ±ã®å Žåã®åé¡ã解決ããŸãããã
- ãªããžã§ã¯ãã®åœ±ãããªãã³ã°ããŸãã ãªããžã§ã¯ããååã«å€§ããå Žåãæåã®ã»ã°ã¡ã³ãã®ã·ã£ããŠããããã¬ã³ããªã³ã°ãããšãã«ããªããžã§ã¯ããéšåçã«åãåãããšãã§ããŸãã ããã解決ããã«ã¯ã圱ãã¬ã³ããªã³ã°ãããã«ã¡ã©ã®äœçœ®ã調æŽããåã®æ®µèœããã·ããããŸãã èšå®ã倱æãããšããã®ãããªã¢ãŒãã£ãã¡ã¯ãã確èªã§ããŸãã
- åœã®èªå·±ã·ã£ããŒã€ã³ã°ã ãããããã·ã£ããŠãããã®äœ¿çšããçããæãæåãªã°ã©ãã£ãã¯ã¢ãŒãã£ãã¡ã¯ãã ãã®åé¡ã¯ãã·ã£ããŠãããã®å€ãšèšç®å€ãæ¯èŒãããšãã«ãšã©ãŒãå°å
¥ããããšã«ãããéåžžã«ããŸã解決ãããŸãã å®éã«ã¯ãåã·ã£ããŠãããã«åå¥ã®ãšã©ãŒå€ã䜿çšããå¿
èŠããããŸããã äžã®å·ŠåŽã®å³ã¯ãå³åŽã®äžå¹žãªãšã©ãŒã®éžæã瀺ããŠããŸã-æåãããšã©ãŒã§ãã
- æ®å¿µãªãããæ·±ããæ¯èŒãããšãã«ãšã©ãŒãå°å
¥ããããšã§èª€ã£ãã»ã«ãã·ã£ããŒã€ã³ã°ãæé€ãããšãPeter PanningãšåŒã°ããå¥ã®ã¢ãŒãã£ãã¡ã¯ãã«ã€ãªãããŸãïŒãPeter Panãšãã§ã¯ãããšããŠå€§ãŸãã«ãã·ã¢èªã«å€æã§ããŸãïŒã æ¬ãèŠããŠããªã人ã®ããã«ãããŒã¿ãŒãã³ã®åœ±ã¯åœŒã®äººçãçãããã°ãã°ææè
ããéããŸããã ãã®ããã«èŠããŸãïŒå®¶ã®é
ã®åœ±ãå°ããããŠããŸãïŒã
ãã®ã¢ãŒãã£ãã¡ã¯ãã¯ãç¹ã«è€éãªåœ¢ç¶ã®ãªããžã§ã¯ãã§ã¯ç¹ã«æ°ã¥ãã«ããå ŽåããããŸãããã»ãšãã©åžžã«ããã«ãããŸãã
æ§èœ
ããã©ãŒãã³ã¹æž¬å®ã¯ãWindows 8.1ãå®è¡ããAMD Phenom II X4 970 3.79GHzã16Gb RAMãAMD Radeon HD 7700ã·ãªãŒãºã®æ§æã®ã³ã³ãã¥ãŒã¿ãŒã§å®è¡ãããŸããã
å¹³åãã¬ãŒã æéã Direct3D 11 / 1920x1080 / MSAA 8x /ãã«ã¹ã¯ãªãŒã³/å°ããªã·ãŒã³ïŒ1ãã¬ãŒã ãããæ倧12kããªãŽã³ãæ倧20åã®ãªããžã§ã¯ãïŒ
åå²æ°/ã·ã£ããŠããããµã€ãºïŒN x Nãã¯ã»ã«ïŒ | 1024 | 2048 | 4096 |
---|---|---|---|
2 | 4.5546ms | 5.07555ms | 7.1661ããªç§ |
3 | 5.50837ms | 6.18023ms | 9.75103ms |
4 | 6.00958ããªç§ | 7.23269ms | 12.1952ms |
å¹³åãã¬ãŒã æéã OpenGL 4.3 / 1920x1080 / MSAA 8x /ãã«ã¹ã¯ãªãŒã³/å°ããªã·ãŒã³ïŒ1ãã¬ãŒã ãããã12kããªãŽã³ãã20ãªããžã§ã¯ãïŒ
åå²æ°/ã·ã£ããŠããããµã€ãºïŒN x Nãã¯ã»ã«ïŒ | 1024 | 2048 | 4096 |
---|---|---|---|
2 | 3.2095ms | 4.05457ms | 6.06558ms |
3 | 3.9968ms | 4.87389ms | 8.65781ms |
4 | 4.68831ms | 5.93709ms | 10.4345ms |
å¹³åãã¬ãŒã æéã 4ããŒãã£ã·ã§ã³/ 1920x1080 / MSAA 8x /ãã«ã¹ã¯ãªãŒã³/倧ã·ãŒã³ïŒ1ãã¬ãŒã ãããã1000kããªãŽã³ãã1000ãªããžã§ã¯ããã500ãªããžã§ã¯ãã€ã³ã¹ã¿ã³ã¹ïŒ
API /ã·ã£ããŠããããµã€ãºïŒN x Nãã¯ã»ã«ïŒ | 1024 | 2048 | 4096 |
---|---|---|---|
Direct3D 11 | 29.2031ms | 33.3434ms | 40.5429ms |
Opengl 4.3 | 21.0032ms | 26.4095ms | 41.8098ms |
çµæã¯ã倧å°ã®ã·ãŒã³ã§ãOpenGL 4.3ã®å®è£ ãäžè¬ã«é«éã«åäœããããšã瀺ããŸããã ã°ã©ãã£ãã¯ãã€ãã©ã€ã³ã®è² è·ã®å¢å ïŒãªããžã§ã¯ããšãã®ã€ã³ã¹ã¿ã³ã¹ã®æ°ã®å¢å ãã·ã£ããŠãããã®ãµã€ãºã®å¢å ïŒã«ãããå®è£ éã®äœæ¥é床ã®å·®ã¯å°ãããªããŸãã OpenGLå®è£ ã®å©ç¹ããDirect3D 11ãšã¯ç°ãªãã·ã£ããŠãããã®åœ¢ææ¹æ³ãšé¢é£ä»ããŠããŸãïŒè²ã«æžã蟌ãããšãªã深床ãããã¡ãŒã®ã¿ã䜿çšããŸããïŒã Direct3D 11ã§åãããšãè¡ãããšã劚ãããã®ã¯äœããããŸãããããã¯ãæ£èŠåããã深床å€ã®äœ¿çšãšèª¿åããŠããŸãã ãã ãããã®ã¢ãããŒãã¯ãã©ã®è¿œå ããŒã¿ãŸãã¯æ·±åºŠå€ã§ã¯ãªã深床å€ã®é¢æ°ãã·ã£ããŠãããã«æ ŒçŽãããŸã§ã¯æ©èœããŸããã ãŸããã¢ã«ãŽãªãºã ã®ããã€ãã®æ¹åïŒ Variance Shadow Mappingãªã© ïŒã¯å®è£ ãå°é£ã§ãã
çµè«
PSSMã¢ã«ãŽãªãºã ã¯ã倧ããªãªãŒãã³ã¹ããŒã¹ã«åœ±ãäœæããæãæåããæ¹æ³ã®1ã€ã§ãã ã·ã³ãã«ã§ç解ããããåå²åçã«åºã¥ããŠãããã·ã£ããŠã®å質ãå¢æžããããšã§ç°¡åã«ã¹ã±ãŒãªã³ã°ã§ããŸãã ãã®ã¢ã«ãŽãªãºã ãä»ã®ã·ã£ããŠãããã³ã°ã¢ã«ãŽãªãºã ãšçµã¿åãããŠãããçŸãããœããã·ã£ããŠãŸãã¯ç©ççã«æ£ç¢ºãªãœããã·ã£ããŠãååŸã§ããŸãã åæã«ãã·ã£ããŠãããã³ã°ã¯ã©ã¹ã®ã¢ã«ãŽãªãºã ã¯ãäžå¿«ãªã°ã©ãã£ãã¯ã¢ãŒãã£ãã¡ã¯ãã®åºçŸã«ã€ãªããããšãå€ããç¹å®ã®ã²ãŒã çšã«ã¢ã«ãŽãªãºã ã埮調æŽããããšã§ããããé€å»ããå¿ èŠããããŸãã