圱ã«ã¯å
ããããŸããã å
æºããã®å
ç·ãä»ã®ãªããžã§ã¯ãã«åžåãããããããªããžã§ã¯ãã«åœãããªãå Žåãæåã®ãªããžã§ã¯ãã¯åœ±ã®äžã«ãããŸãã 圱ã¯ç»åã«ãªã¢ãªãºã ãè¿œå ãããªããžã§ã¯ãã®çžå¯Ÿçãªäœçœ®ã確èªã§ããããã«ããŸãã 圌ãã®ãããã§ãã·ãŒã³ã¯ãæ·±ããã垯ã³ãŠããŸãã 次ã®ã·ãŒã³ç»åã圱ãããšåœ±ãªãã§æ¯èŒããŸãã
ã芧ã®ããã«ã圱ã«ããããªããžã§ã¯ããäºãã«ã©ã®ããã«é
眮ãããŠããããããæ確ã«ãªããŸãã 圱ã®ãããã§ãç«æ¹äœã®1ã€ã空äžã«èŠããŸãã
ç¹ã«å®å
šãªåœ±ã®ãªã¢ã«ã¿ã€ã ã¢ã«ãŽãªãºã ããŸã çºæãããŠããªãããã圱ã®å®è£
ã¯å°é£ã§ãã 圱ã®èšç®ãè¿äŒŒããããã®ããã€ãã®è¯ãæ¹æ³ããããŸããããããã¯ãã¹ãŠèæ
®ã«å
¥ããªããã°ãªããªãç¬èªã®ç¹æ§ãæã£ãŠããŸãã
æ¹æ³ã®1ã€ã§ããã·ã£ããŠãããã¯æ¯èŒçç°¡åã«å®è£
ã§ããã»ãšãã©ã®ãããªã²ãŒã ã§äœ¿çšãããŠãããé©åãªçµæãåŸãããŸãã ã·ã£ããŠãããã¯ããã»ã©é£ãããªããããã©ãŒãã³ã¹ã®ç¹ã§éåžžã«å®äŸ¡ã§ãããããé«åºŠãªã¢ã«ãŽãªãºã ïŒ ç¹å
æºããã®ã·ã£ããŠãã«ã¹ã±ãŒãã·ã£ããŠããããªã©ïŒã«ç°¡åã«æ¹åã§ããŸãã
ïŒç¿»èš³è
ã®æ³šæ-å°æ¥ããã·ã¢èªçã®ããã€ãã®çšèªã¯ãå®è©ã®ããè±èªçãšéè€ããŸãããšã©ãŒããªããããããªã-å
ã®çšèªãšäžç·ã«èŠããŠãããŠãã ããã
ã·ã£ããŠã«ãŒã
ã·ã£ããŠãããã®åºç€ãšãªãã¢ã€ãã¢ã¯éåžžã«åçŽã§ããå
æºã®èŠç¹ããã·ãŒã³ãæç»ããŸãã ç§ãã¡ãèŠããã®ã¯ãã¹ãŠç
§ããããæ®ãã¯æ¥é°ã«ãªã£ãŠããŸãã åºãšå
æºã®éã«å€§ããªç«æ¹äœãããåºãæ³åããŠãã ããã å
æºã¯åºã®äžéšã§ã¯ãªãç«æ¹äœããèŠãããããåºã®ãã®éšåã¯èŠããªããªããŸãã
äžã®å³ã§ãéãç·ã¯å
æºãèŠããè¡šé¢ã瀺ããŠããŸãã éããè¡šé¢ã¯é»ãå¡ãããŸã-é°åœ±ãä»ããããŸãã å
æºããäžçªå³ã®ç«æ¹äœã®äžéšã«ç·ïŒå
ç·ïŒãåŒããšãæåã«ç©ºäžã«ã¶ãäžãã£ãŠããç«æ¹äœã暪åããŸãã ãã®ãããå³ã®ç«æ¹äœãšã¯ç°ãªããã¶ãäžãã£ãŠããç«æ¹äœã®å·Šé¢ãç
§ããããŸãã
å
ç·ãšè¡šé¢ã®æåã®äº€å·®ç¹ãèŠã€ããŠãä»ã®äº€å·®ç¹ãšæ¯èŒããããšæããŸãã å
ç·ãšãµãŒãã§ã¹ã®äº€ç¹ãæãè¿ã亀ç¹ãšäžèŽããªãå Žåã圱ã®äžã«ãããŸãã ãœãŒã¹ããã®äœåãã®ç°ãªãå
ç·ã«å¯ŸããŠãã®æäœãç¹°ãè¿ãããšã¯éåžžã«éå¹ççã§ãããã²ãŒã ã®ãã¹ãŠã®ãã¬ãŒã ã§æç»ããã®ã«ã¯é©ããŠããŸããã
ããããæ·±ããã¹ãã«ã€ããŠã¯ãã§ã«èªãã§ããŸãïŒ ããã®ç¿»èš³ ã å
ã® ã 深床ãããã¡ã®å€ã¯ãã«ã¡ã©ã®èŠç¹ããã®ãã©ã°ã¡ã³ãã®æ·±åºŠã§ããã0ã1ã®å€ã«ãã£ãŠå¶éãããŸããå
æºã®èŠç¹ããã·ãŒã³ãã¬ã³ããªã³ã°ãããã¯ã¹ãã£ã«æ·±åºŠå€ãæ ŒçŽãããšã©ããªããŸããïŒ ãããã£ãŠãå
æºã®èŠç¹ããèŠãããšãã§ããæå°ã®æ·±ããååŸããŸãã ããã«ã深床å€ã¯ãå
æºã«æãè¿ããµãŒãã§ã¹ã瀺ããŸãã ãã®ãã¯ã¹ãã£ã¯ã 深床ããããŸãã¯ã·ã£ããŠããããšåŒã°ããŸã ã
å·Šã®åçã¯ãç«æ¹äœã®äžã®è¡šé¢ã«åœ±ãèœãšãæåæ§å
æºïŒãã¹ãŠã®å
ç·ãå¹³è¡ïŒã瀺ããŠããŸãã ãã¯ã¹ãã£ã«ä¿åãããŠãã深床å€ã䜿çšããŠããœãŒã¹ã«æãè¿ããµãŒãã§ã¹ãèŠã€ãããã®å©ããåããŠã圱ã®äžã«ãããã®ãå€æããŸãã å
æºã«å¯Ÿå¿ããè¡åã䜿çšãããã¥ãŒããã³æ圱è¡åãšããŠãã·ãŒã³ã¬ã³ããªã³ã°ã䜿çšããŠæ·±åºŠããããäœæããŸãã
å¹³è¡å
ç·ã䜿çšããæåæ§ã©ã€ãã«ã¯äœçœ®ããªãããç¡éã«é ãããããŸãã ãã ããã·ã£ããŠããããäœæããã«ã¯ãå
ã®ç·äžã®äœçœ®ããã·ãŒã³ãæç»ããå¿
èŠããããŸãã
ã泚æ ãã©ã³ã¹ã¬ãŒã¿-openGLã¯ãé ãããïŒz> 1ïŒãŸãã¯è¿ãããïŒz <0ãŸãã¯z <-1ã®èšå®ã«å¿ããŠïŒãµãŒãã§ã¹ãåãåããŸãã ã«ã¡ã©ãããªãã¯ã¹ã¯ãã·ãŒã³äžã®ãªããžã§ã¯ãã®z座æšããã®ééã«ãªãããã«éžæãããŸããããã§ãªãå Žåããããã¯è¡šç€ºãããŸããã æ°åŠçãªèŠ³ç¹ããã¯ãäœçœ®ã¯ãããŸããããå®éã«ã¯ãã«ã¡ã©ã®ãã€ã³ãã¯ãæç»æã«ç»é¢ã®äžå€®ã®ãã¹ãã³ã°çã«è¿ããã€ã³ãã«è¡šç€ºããããã€ã³ããšèŠãªãããšãã§ããŸã
å³åŽã®åçã§ã¯ãåãå
ãç«æ¹äœã芳å¯è
ãèŠããŸãã ãã€ã³ãP
ã§ãµãŒãã§ã¹ã®ãã©ã°ã¡ã³ããæç»ããããã圱ã«ãããã©ãããå€æããå¿
èŠããããŸãã ãããè¡ãã«ã¯ã P
ãå
æºT(P)
ã®åº§æšç©ºéã«å€æããŸãã ç¹P
å
ã®èŠç¹ããã¯èŠããªãããããã®äŸã®åº§æšz
ã¯0.9
ãŸãã ãã€ã³ãx,
ã®åº§æšã«åºã¥ããŠã深床ãããã調ã¹ããšãå
æºã«æãè¿ããã€ã³ãã深床0.4ã®
ã§ããããšãããããŸãããã®å€ã¯ãã€ã³ãP
å€ãããå°ããããããã€ã³ãP
ã¯ã·ã£ããŠå
ã«ãããŸãã
ã·ã£ããŠæç»ã¯2ã€ã®ãã¹ã§æ§æãããŸããæåã«æ·±åºŠããããæç»ãã2çªç®ã®ãã¹ã§éåžžã©ããã¯ãŒã«ããæç»ããŸãã深床ãããã䜿çšããŠãè¡šé¢ã®ã©ã®æçãã·ã£ããŠã«ããããå€æããŸãã è€éã«æãããããããŸãããããã¹ãŠã段éçã«é²ãããšããã¹ãŠãæ確ã«ãªããŸãã
深床ããã
æåã®ãã¹ã§ã¯ã深床ããããçæããŸãã 深床ãããã¯ãå
æºã®èŠ³ç¹ããã¬ã³ããªã³ã°ããã深床å€ãæã€ãã¯ã¹ãã£ã§ãã 次ã«ãããã䜿çšããŠåœ±ãèšç®ããŸãã ã¬ã³ããªã³ã°ãããçµæããã¯ã¹ãã£ã«ä¿åããã«ã¯ãããã® framebuffer ïŒ translationãå¿
èŠã§ãã
æåã«ã深床ããããæç»ããããã®ãã¬ãŒã ãããã¡ãŒãäœæããŸãã
unsigned int depthMapFBO; glGenFramebuffers(1, &depthMapFBO);
ãã¬ãŒã ãããã¡ã®æ·±åºŠãããã¡ãšããŠäœ¿çšãã2Dãã¯ã¹ãã£ãäœæããåŸã
const unsigned int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024; unsigned int depthMap; glGenTextures(1, &depthMap); glBindTexture(GL_TEXTURE_2D, depthMap); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
深床ãããã®äœæã¯è€éã«èŠããŸããã æ·±ãã®å€ã«ã®ã¿é¢å¿ãããããïŒ r,g,b,a
è²ã«ã¯é¢å¿ããªãïŒããã¯ã¹ãã£åœ¢åŒGL_DEPTH_COMPONENT
ãæå®ããŸãã ãã¯ã¹ãã£ã®é«ããšå¹
ã1024 * 1024ã«èšå®ããŸã-ããã¯æ·±åºŠãããã®ãµã€ãºã«ãªããŸãã
次ã«ã深床ãããã¡ãšããŠæ·±åºŠãã¯ã¹ãã£ããã¬ãŒã ãããã¡ã«ã¢ã¿ããããŸãã
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0);
å
æºã®èŠç¹ããã·ãŒã³ãæç»ããå Žåãæ·±ãã«ã®ã¿é¢å¿ããããã«ã©ãŒãããã¡ã¯å¿
èŠãããŸããã ãã¬ãŒã ãããã¡ãŒã¯ã«ã©ãŒãããã¡ãŒããªããšäžå®å
šã«ãªããããè²ãã¬ã³ããªã³ã°ããªãããšãæ瀺çã«ç€ºãå¿
èŠããããŸãã ãããè¡ãããã«ã glDrawBuffer
ãšglReadBuffer
ã«glDrawBuffer
ãèšå®ããŸãã
ããã§ããã¯ã¹ãã£ã«æ·±åºŠå€ãæžã蟌ããã¬ãŒã ãããã¡ãé©åã«æ§æããã深床ããããã¬ã³ããªã³ã°ã§ããŸãã äž¡æ¹ã®ã¬ã³ããªã³ã°ãã¹ã®å®å
šãªå®è£
ã¯æ¬¡ã®ããã«ãªããŸãã
// 1. glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glClear(GL_DEPTH_BUFFER_BIT); ConfigureShaderAndMatrices(); RenderScene(); // 2. ( ) glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ConfigureShaderAndMatrices(); glBindTexture(GL_TEXTURE_2D, depthMap); RenderScene();
ãã®ã³ãŒãã«ã¯è©³çŽ°ã¯å«ãŸããŠããŸããããã·ã£ããŠãããã®äžè¬çãªæŠå¿µã瀺ããŠããŸãã glViewport
åŒã³åºãã«æ³šæããŠglViewport
ãéåžžã深床ãããã®ãµã€ãºã¯ãç»é¢ïŒãŸãã¯æçµç»åãã¬ã³ããªã³ã°ããããã¯ã¹ãã£ïŒã®ãµã€ãºãšã¯ç°ãªããŸãã å€æŽãå¿ãããšãç»é¢ãµã€ãºã®æ£æ¹åœ¢ã®ããŒã¹ã®ã¿ã深床ãã¯ã¹ãã£ã«æŽæ°ãããããïŒãã¯ã¹ãã£ãå°ããå ŽåïŒæ
å ±ã®äžéšã衚瀺ãããŸããïŒãšããžã®å€åŽã«æ®ããŸãïŒã
å
æºã¹ããŒã¹
äžèšã®ã³ãŒãã§äžæãªã®ã¯ã ConfigureShaderAndMatrices()
é¢æ°ãäœããããã ãã§ãã
2çªç®ã®ãã¹ã§ã¯ãéåžžã©ããã«åäœããŸããã«ã¡ã©ã«é©åãªãã¥ãŒãšæ圱è¡åãèšå®ãããªããžã§ã¯ãã«ã¢ãã«è¡åãèšå®ããŸãã ãã ããæåã®ãã¹ã§ã¯ãæ圱ãšãã¥ãŒã«ä»ã®ãããªãã¯ã¹ã䜿çšããŸããå
æºã®èŠç¹ããã·ãŒã³ãæç»ããããã§ãã
æåæ§å
æºãã·ãã¥ã¬ãŒãããããããã¹ãŠã®å
ç·ã¯å¹³è¡ã§ãã ãã®ãããå
æºã«æ£æ圱å³æ³ã䜿çšããŸãïŒé床ã®æªã¿ã¯ãããŸããïŒã
float near_plane = 1.0f, far_plane = 7.5f; glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
ããã¯ããã®èšäºã®ãã¢ã§äœ¿çšãããæ£æ圱å³ã®äŸã§ãã å°åœ±è¡åã¯ãªããžã§ã¯ããèŠãè·é¢ã決å®ããã®ã§ïŒã€ãŸãããããªã«ãŒãã¯ãªããžã§ã¯ããããŸãã«ãè¿ããŸãã¯é ãããããšã¯ãããŸããïŒãã¯ãªããã³ã°é åã®ãµã€ãºã«ã¯ã深床ãããã«è¡šç€ºãããã¹ãŠã®ãªããžã§ã¯ããå«ãŸããŠããããšã確èªããå¿
èŠããããŸãã
ãã¹ãŠã®ãªããžã§ã¯ããå
æºã®èŠç¹ããèŠãããã¥ãŒè¡åãäœæããã«ã¯ã人æ°ã®ãªãé¢æ°glm::lookAt
ã䜿çšããŸããå
æºã¯ã·ãŒã³ã®äžå¿ããèŠããããã«ãªããŸããã
glm::mat4 lightView = glm::lookAt(glm::vec3(-2.0f, 4.0f, -1.0f), glm::vec3( 0.0f, 0.0f, 0.0f), glm::vec3( 0.0f, 1.0f, 0.0f));
ïŒæ³šè»ç·-æåã®ãã¯ãã«ã¯ã«ã¡ã©ã®äœçœ®ã2çªç®ã¯èŠãŠããå Žæã3çªç®ã¯èŠäžããæ¹åã§ãïŒ
ããã2ã€ã®è¡åã®çµã¿åããã«ãããäžçã®åº§æšããå
æºãäžçããèŠãã座æšãžã®å€æè¡åãåŸãããŸãã ããã¯ãããã¹ããããã¬ã³ããªã³ã°ããããã«å¿
èŠãªãã®ã§ãã
glm::mat4 lightSpaceMatrix = lightProjection * lightView;
lightSpaceMatrix
ãããªãã¯ã¹ã¯ãäžèšã§T
ãšããŠæå®ãããã®ãšãŸã£ããåãã§ãT
ãã®ãããªãã¯ã¹ã䜿çšãããšãåŸæ¥ã®ã«ã¡ã©ã®ãã¥ãŒããã³æ圱ãããªãã¯ã¹ã®ä»£ããã«äœ¿çšããŠãéåžžã©ããã·ãŒã³ãå¹³ååã§ããŸãã ãã ããæ·±ãã®å€ã«ã®ã¿é¢å¿ããããæªäœ¿çšã®è²ã«ã€ããŠäžå¿
èŠãªèšç®ãè¡ããã«ããã©ãŒãã³ã¹ãç¶æããããšèããŠããŸãã ãããã£ãŠã深床ãããã®ã¿ãæç»ããæãåçŽãªã·ã§ãŒããŒãäœæããŸãã
ããã¹ãããã¬ã³ããªã³ã°
å
æºã®ã·ãŒã³ãã¬ã³ããªã³ã°ãããšããé ç¹ã®åº§æšã®ã¿ãå¿
èŠã§ããã以äžã¯å¿
èŠãããŸããã ãã®ãããªåçŽãªã·ã§ãŒããŒïŒ simpleDepthShader
ãšåŒã³ãŸãããïŒã®å Žåãé ç¹ã·ã§ãŒããŒãèšè¿°ããŸãã
#version 330 core layout (location = 0) in vec3 aPos; uniform mat4 lightSpaceMatrix; uniform mat4 model; void main() { gl_Position = lightSpaceMatrix * model * vec4(aPos, 1.0); }
ãã®ã·ã§ãŒããŒã¯ãã¢ãã«ããšã«ã lightSpaceMatrix
ã䜿çšããŠã¢ãã«ã®é ç¹ãå
æºã®ç©ºéã«lightSpaceMatrix
ãŸãã
ã·ã£ããŠã®ãã¬ãŒã ãããã¡ãŒã«ã¯ã«ã©ãŒãããã¡ãŒããªãããããã©ã°ã¡ã³ãã·ã§ãŒããŒã¯èšç®ãå¿
èŠãšããã空ã®ãŸãŸã«ã§ããŸãã
#version 330 core void main() { // gl_FragDepth = gl_FragCoord.z; }
空ã®ãã©ã°ã¡ã³ãã·ã§ãŒããŒã¯äœãå®è¡ãããã·ã§ãŒããŒã®æåŸã«æŽæ°ããã深床ãããã¡ãŒãååŸããŸãã ãã®ã³ãŒãè¡ã®ã³ã¡ã³ããå€ãããšãã§ããŸãããå®éã«ã¯æ·±ãã¯ãšã«ããèšç®ãããŸãã
深床ãããã¡ã«æç»ãããšã次ã®ã³ãŒãã«ãªããŸãã
simpleDepthShader.use(); glUniformMatrix4fv(lightSpaceMatrixLocation, 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glClear(GL_DEPTH_BUFFER_BIT); RenderScene(simpleDepthShader); glBindFramebuffer(GL_FRAMEBUFFER, 0);
RenderScene
é¢æ°ã¯ã·ã§ãŒããŒãåãåããæç»ã«å¿
èŠãªé¢æ°ãåŒã³åºããå¿
èŠã«å¿ããŠã¢ãã«è¡åãã€ã³ã¹ããŒã«ããŸãã
ãã®çµæãå
ã®ç¹ã§æãè¿ããã©ã°ã¡ã³ãã®æ·±ããå«ãåãã¯ã»ã«ã«å¯ŸããŠãæ·±ããããã¡ããã£ã±ãã«ãªããŸãã ãã®ãã¯ã¹ãã£ãç»é¢ãµã€ãºã®é·æ¹åœ¢ã«æ圱ããŠè¡šç€ºã§ããŸãã ïŒãã¬ãŒã ãããã¡ã䜿çšããäŸã®åŸåŠçã®å Žåãšåæ§ã§ãã å
ã® ããã§ã®å€æ ãïŒ
é·æ¹åœ¢ã«æ·±åºŠããããæç»ããã«ã¯ã次ã®ã·ã§ãŒããŒã䜿çšããŸãã
#version 330 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D depthMap; void main() { float depthValue = texture(depthMap, TexCoords).r; FragColor = vec4(vec3(depthValue), 1.0); }
ã·ã£ããŠãã¬ã³ããªã³ã°ãããšãã«ãæ圱ãããªãã¯ã¹ãçŽäº€ã§ã¯ãªãé è¿æ³ã«ãªãå Žåã深床ã¯éç·åœ¢ã«å€åããŸãã èšäºã®æåŸã§ããã®éãã«ã€ããŠèª¬æããŸãã
ã·ãŒã³ã深床ãããã«ã¬ã³ããªã³ã°ããããã®ãœãŒã¹ã³ãŒãã¯ã ããã«ãããŸã ã
圱絵
é©åã«äœæããã深床ãããã䜿çšããŠã圱ãæç»ã§ããŸãã ãã©ã°ã¡ã³ãã·ã§ãŒããŒã䜿çšããŠãã©ã°ã¡ã³ããã·ã£ããŠã«ãããã©ããã確èªããŸãããé ç¹ã·ã§ãŒããŒã§å
æºã®ã¹ããŒã¹ã«å€æããŸãã
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; layout (location = 2) in vec2 aTexCoords; out VS_OUT { vec3 FragPos; vec3 Normal; vec2 TexCoords; vec4 FragPosLightSpace; } vs_out; uniform mat4 projection; uniform mat4 view; uniform mat4 model; uniform mat4 lightSpaceMatrix; void main() { vs_out.FragPos = vec3(model * vec4(aPos, 1.0)); vs_out.Normal = transpose(inverse(mat3(model))) * aNormal; vs_out.TexCoords = aTexCoords; vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0); gl_Position = projection * view * model * vec4(aPos, 1.0); }
ããããæ°ãããã®ã¯ãé ç¹ã·ã§ãŒããŒã®åºåã«ããè¿œå ã®ãã¯ãã«FragPosLightSpace
ã§ãã æ·±ããæç»ããããã«æåã®ãã¹ã§äœ¿çšãããã®ãšåãlightSpaceMatrix
ãåãå
¥ãããã®å©ããåããŠããã¯ãã«ãå
æºã®ç©ºéã«å€æããŸãã é ç¹ã·ã§ãŒããŒã¯ãã¯ãŒã«ãã®ã¹ããŒã¹ïŒ vs_out.FragPos
ïŒãšå
æºã®ã¹ããŒã¹ïŒ vs_out.FragPos
ïŒã®äž¡æ¹ã®é ç¹ã®åº§æšãåæã«ãã©ã°ã¡ã³ãã«è»¢éããŸãã
Blinn-Fongã©ã€ãã¢ãã«ã«åºã¥ãããã©ã°ã¡ã³ãã·ã§ãŒããŒã䜿çšããŸãã ãã©ã°ã¡ã³ãã·ã§ãŒããŒã§ã¯ã shadow
å€ãèŠã€ããŸãããã©ã°ã¡ã³ããã·ã£ããŠå
ã«ããå Žåã¯1.0ã«ãªããã©ã€ããããã£ãŠããå Žåã¯0.0ã«ãªããŸãã çµæãšããŠçããdiffuse
ããã³specular
è²ïŒæ¡æ£ããã³é¡é¢åå°ç
§æïŒã¯(1.0 - shadow)
ã§ä¹ç®ãããŸãã éæ¥ç
§æã®ããã«åœ±ãå®å
šã«é»ã«ãªãããšã¯ãã£ãã«ãªãããã圱ã«é¢ä¿ãªãèæ¯ã®ç
§æãååšããŸãã
#version 330 core out vec4 FragColor; in VS_OUT { vec3 FragPos; vec3 Normal; vec2 TexCoords; vec4 FragPosLightSpace; } fs_in; uniform sampler2D diffuseTexture; uniform sampler2D shadowMap; uniform vec3 lightPos; uniform vec3 viewPos; float ShadowCalculation(vec4 fragPosLightSpace) { [...] } void main() { vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb; vec3 normal = normalize(fs_in.Normal); vec3 lightColor = vec3(1.0); // ambient vec3 ambient = 0.15 * color; // diffuse vec3 lightDir = normalize(lightPos - fs_in.FragPos); float diff = max(dot(lightDir, normal), 0.0); vec3 diffuse = diff * lightColor; // specular vec3 viewDir = normalize(viewPos - fs_in.FragPos); float spec = 0.0; vec3 halfwayDir = normalize(lightDir + viewDir); spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0); vec3 specular = spec * lightColor; // calculate shadow float shadow = ShadowCalculation(fs_in.FragPosLightSpace); vec3 lighting = (ambient + (1.0 - shadow) * (diffuse + specular)) * color; FragColor = vec4(lighting, 1.0); }
ããã¯ãã»ãšãã©ã®å Žåãã©ã€ãã£ã³ã°ã®äŸã§äœ¿çšããã·ã§ãŒããŒã®ã³ããŒã§ãïŒ ããäžã®å€æ ã é«åºŠãªã©ã€ãã£ã³ã° ã
ããã§ã¯ã·ã£ããŠèšç®ã®ã¿ãè¿œå ãããŠããŸãã äœæ¥ã®å€§éšåã¯ã ShadowCalculation
é¢æ°ã«ãã£ãŠè¡ãããŸãã ãã©ã°ã¡ã³ãã·ã§ãŒããŒã®æåŸã§ãå
ã®æ¡æ£åå°ãšé¡é¢åå°ããã®å¯äžã«ïŒ1.0-ã·ã£ããŠïŒãæããŸã-ã€ãŸãããã©ã°ã¡ã³ããã·ã§ãŒãã£ã³ã°ãããŠããªãéã«äŸåããŸãã ããã«ããã®å
¥åã·ã§ãŒããŒã¯ãå
æºã®ã¹ããŒã¹å
ã®ãã©ã°ã¡ã³ãã®äœçœ®ãšãæ·±ãã®å€ãæã€ãã¯ã¹ãã£ãŒïŒæåã®ãã¹ã§ã¬ã³ããªã³ã°ãããïŒãããã«åãå
¥ããŸãã
ãã©ã°ã¡ã³ããã·ã£ããŠå
ã«ãããã©ããã確èªããããã«ãå
æºã®ç©ºéã®äœçœ®ãæ£èŠåããã座æšã«ç§»åããŸãã é ç¹ã·ã§ãŒããŒã§é ç¹ã®äœçœ®ãgl_Position
ã«æ»ããšãopenGLã¯x,y,z
ãw
èªåçã«åå²ããããŒã¹ãã¯ãã£ããæ£ããæ©èœããããã«ããŸãã FragPosLightSpace
ãšããŠæž¡ãããªãããããã®åå²ãèªåã§è¡ãå¿
èŠããããŸãã
float ShadowCalculation(vec4 fragPosLightSpace) { // perform perspective divide vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; [...] }
å
æºã®ç©ºéå
ã®ãã©ã°ã¡ã³ãã®äœçœ®ãååŸããŸãã
æ£æ圱ã䜿çšããå Žåã座æšw=1.0
ã¯å€åãããwã«ããé€ç®ã¯äžèŠã«ãªããŸãã ãã ããéèŠæ圱ã䜿çšããå Žåã¯åå²ãå¿
èŠã§ãããã³ãŒãã¯äž¡æ¹ã®å Žåã«æ£ããæ©èœããŸãã
ïŒã¬ãŒã³ã«æ³šæããŠãã ãã-wã«ããåå²ã¯ããã©ã°ã¡ã³ãã·ã§ãŒããŒã§è¡ãå¿
èŠããããŸãã ãã®èšäºã®æåã®å³ã¯ããã¯ã¹ãã£åº§æšã®ç·åœ¢è£éãšéèŠè£éã®éãã瀺ããŠããŸããïŒ
ãã¯ã¹ãã£åº§æšã¯[0,1]ã®ç¯å²ã«ãããã¬ã³ããªã³ã°æã®å¯èŠãã©ã°ã¡ã³ãã®åº§æšã¯[-1,1]ã®å€ãåããŸãã ããããéé[0,1]ã«ç§»åããŸãã
projCoords = projCoords * 0.5 + 0.5;
ãããã®åº§æšã«åºã¥ããŠããã¯ã¹ãã£ã®æ·±åºŠå€ã確èªã§ããŸããããã¯ãå
æºã«æãè¿ããªããžã§ã¯ãã®æ·±åºŠã«ãªããŸãã
float closestDepth = texture(shadowMap, projCoords.xy).r;
çŸåšã®ãã©ã°ã¡ã³ãã®æ·±ããååŸããã«ã¯ãå
æºã®ç©ºéã§ãã®z座æšãååŸããŸãã
float currentDepth = projCoords.z;
ãã®åŸã currentDepth
ãšclosestDepth
åçŽãªæ¯èŒã«ããããã©ã°ã¡ã³ããæãè¿ããã圱ã«ããããå€æã§ããŸãã
float shadow = currentDepth > closestDepth ? 1.0 : 0.0;
ShadowCalculationé¢æ°ã®ãã¹ãŠã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
float ShadowCalculation(vec4 fragPosLightSpace) { // perform perspective divide vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w; // transform to [0,1] range projCoords = projCoords * 0.5 + 0.5; // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords) float closestDepth = texture(shadowMap, projCoords.xy).r; // get depth of current fragment from light's perspective float currentDepth = projCoords.z; // check whether current frag pos is in shadow float shadow = currentDepth > closestDepth ? 1.0 : 0.0; return shadow; }
2çªç®ã®ã¬ã³ããŒãã¹ã§ãã®ã·ã§ãŒããŒããã¯ã¹ãã£ãšéåžžã®ãã¥ãŒããã³æ圱ãããªãã¯ã¹ãšå
±ã«äœ¿çšãããšãçµæã¯å³ã®ããã«ãªããŸãã
ãã¹ãŠãæ£ããè¡ã£ãå Žåãåºãšç«æ¹äœã«åœ±ãèŠããŸãïŒãã ããããã€ãã®ã¢ãŒãã£ãã¡ã¯ãããããŸãïŒã ãœãŒã¹ã³ãŒãã㢠ã
ã·ã£ããŠãããã®æ¹å
ã·ã£ããŠãããã®äœæ¥ãå®äºã§ããŸããããç»åã«ããã€ãã®ã¢ãŒãã£ãã¡ã¯ããèŠãããšãã§ããŸãã åŸç¶ã®ããã¹ãã¯ããããã®ä¿®æ£ã«å°å¿µããŸãã
ã¢ã¢ã¬ãã¿ãŒã³
æããã«ãäžã®ç»åã§äœããééã£ãŠããŸãã æ¡å€§ãããç»åã¯ã ã¢ã¢ã¬ãã¿ãŒã³ã«äŒŒãŠããŸã ã
åºå
šäœã¯ãã¯ã£ãããšèŠãã亀äºã®é»ãã¹ãã©ã€ãã§èŠãããŠããŸãã ãã®å¹æã¯ãåäžã®ç»åã§èª¬æã§ããŸãã
ïŒã¬ãŒã³ã«æ³šæããŠãã ãã-äœè
ã¯ã ã·ã£ããŠããã ããšããçšèªã䜿çšããŠå¹æã説æããŸãã確ç«ããã翻蚳ã¯èŠã€ãããŸããã§ããã
ã·ã£ããŠãããã®è§£å床ã¯éãããŠããããïŒäžââèšã®äŸã§ã¯ããã¯ã¹ãã£1024*1024
ã䜿çšããŸããïŒãæçµç»åã®ããã€ãã®ãã¯ã»ã«ã¯æ·±åºŠãããããåãå€ãååŸã§ããŸãã äžã®å³ã¯ãååŸæéšåïŒå·Šäžããå³ãžïŒãããã¹ãããã®1ã€ã®ãã¯ã»ã«ãè¡šãåºã瀺ããŠããŸãã ïŒãã¯ã»ã«-ãã¯ã¹ãã£ãã¯ã»ã«ïŒ
éåžžãããã¯æ£åžžã§ãããäžã®äŸã®ããã«ãå
ãè¡šé¢ã«å¯ŸããŠæãã«èœã¡ããšåé¡ã«ãªãå¯èœæ§ããããŸãã ãã¯ã¹ãã£ãã深床ãåãåãäžéšã®ãã©ã°ã¡ã³ãã¯ããã®ãã©ã°ã¡ã³ãã®ããã¢ã®å®éã®æ·±åºŠã«å¯Ÿå¿ããªãå€ãååŸããŸãã ãã®ããããã©ã°ã¡ã³ãã®äžéšã¯åœ±ä»ããšèŠãªãããã¹ãã©ã€ãã衚瀺ãããŸãã
ãã®åé¡ã¯å°ããªããã¯ã§è§£æ±ºã§ããŸããã€ãŸãããã¹ãŠã®ãã©ã°ã¡ã³ããè¡šé¢ããäžã«ãªãããã«ãæ·±ãã®å€ãå°ãã ãã·ããïŒã·ã£ããŠãã€ã¢ã¹ïŒããŸãã
ïŒã¬ãŒã³ã«æ³šæããŠãã ããã-ç§ã¯çµµãæ£ããæãããŠããªããšåŒ·ãæããŠããŸãããã©ã°ã¡ã³ãã®é°åœ±ãé²ãããã«ã深床ãããããã®å€ãèšè¿°ãããžã°ã¶ã°ç·ã¯è¡šé¢ã®äžã«ããã¹ãã§ãïŒ
float bias = 0.005; float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
ã·ãŒã³å
šäœã®0.005ã®ã·ããã§åé¡ã¯è§£æ±ºããŸãããéåžžã«å°ããªè§åºŠã§å
ãåœããäžéšã®ãµãŒãã§ã¹ã«ã¯ãŸã 圱ã®çžããããŸãã ããæ·±å»ãªã¢ãããŒãã¯ãå
ãè¡šé¢ã«åœããè§åºŠã«å¿ããŠã·ãããå€æŽããããšã§ãã ã¹ã«ã©ãŒç©ã䜿çšããŸãã
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
ãããã£ãŠãå
ç·ã«ã»ãŒåçŽãªåºã¿ã€ãã®è¡šé¢ã®ã·ããã¯éåžžã«å°ãããªããŸãã æ³ç·ãšå
ã®æ¹åã®éã®è§åºŠã倧ããã»ã©ãã·ããã倧ãããªããŸãã 次ã®å³ã¯ãåãã·ãŒã³ã瀺ããŠããŸãããã·ããã䜿çšããŠããŸããæããã«è¯ãèŠããŸãã
ã·ããããšã«æ£ããå€ãéžæããã«ã¯ãã·ãŒã³ããšã«ç°ãªãå¯èœæ§ããããããéžæããå¿
èŠããããŸãããããã¯éåžžãã¢ãŒãã£ãã¡ã¯ããæ¶ãããŸã§ã·ãããå¢ããã ãã§è¡ãããŸãã
ããŒã¿ãŒãã³ã®å¹æ
ïŒããããã³ïŒ
深床ã®ã·ããã䜿çšããããšã®æ¬ ç¹ã¯ããªããžã§ã¯ãã®å®éã®æ·±åºŠã«ã·ãããé©çšããããšã§ãã ãã®çµæããã®ã·ããã¯ååã«å€§ãããªãå¯èœæ§ããããããäžã®å³ã®ããã«ããªããžã§ã¯ããšåœ±ã®éã«é¡èãªè·é¢ã衚瀺ãããŸãïŒèªåŒµããŠå€§ããªã·ããã䌎ãïŒã
圱ã被åäœããå°ãéãããããããã¯ããŒã¿ãŒãã³å¹æãšåŒã°ããŸãã ã»ãšãã©ã®åé¡ã解決ããããã«å°ãã®ããªãã¯ã䜿çšã§ããŸãã深床ããããæç»ãããšãã«ãæ£é¢åãã®ããªãŽã³ã®ã¯ãªããã³ã°ã䜿çšããŸãã ãªãªãžãã« ã®Habréã§é¡ãæ°ããããšã«ã€ããŠèªãã§ãã ããã
ããã©ã«ãã§ã¯ãopenGLã¯éåãã®ããªãŽã³ãã«ããããŸãã openGLãåãæ¿ããŠå察ã®ããšãè¡ãããšãã§ããŸãã
ã¬ã³ããªã³ã°ã®æåã®ãã¹ã§ã¯ãæ·±ãã®å€ã®ã¿ãå¿
èŠã§ãããåé¢ãããŸãã¯èé¢ããã©ã®æ·±ããåããã¯é¢ä¿ãããŸããã ãªããžã§ã¯ãå
ã«åœ±ããããã©ããã¯é¢ä¿ãªãã®ã§ãäžæ£ç¢ºãªçµæã«æ°ä»ãããšã¯ãããŸãã-ãããã¯ãŸã èŠããŸããã
Peter Panã®å¹æãé€å»ããããã«ãæåã®ãã¹ã§ããã³ããšããžãåãåããŸããã GL_CULL_FACE
æå¹ã«ããå¿
èŠãããããšã«æ³šæããŠãã ããã
glCullFace(GL_FRONT); RenderSceneToDepthMap(); glCullFace(GL_BACK); //
ããã«ãããPeter Penãšãã§ã¯ãã®åé¡ã解決ãããŸãããããã¯ãã¹ãŠã®é¢ã«ãµãŒãã§ã¹ããããªããžã§ã¯ãã«å¯ŸããŠã®ã¿ã§ãã ãã®äŸã§ã¯ãããã¯ãã¥ãŒãã«å¯ŸããŠã¯ããŸãæ©èœããŸãããåé¢ã®ããªãŽã³ãã¯ãªãããããšåºãå®å
šã«åé€ããããããåºã«å¯ŸããŠã¯æ©èœããŸããã ãã®æ¹æ³ã䜿çšããå Žåã¯ãçã«ããªã£ãŠããå Žåã«ã®ã¿ãæ£é¢åãã®ããªãŽã³ã®ã¯ãªããã³ã°ã䜿çšããŠãã ããã
ïŒè»ç·ã«æ³šæããŠãã ãã-ç¹ã«ãã®äŸã§ã¯ãäžã«ãªããžã§ã¯ãããªããããåºãå®å
šã«åæããŠãåé¡ã¯ãããŸãããäžã«åœ±ããããã©ããã¯é¢ä¿ãããŸãããïŒ
ãªããžã§ã¯ããã·ã§ãŒãã£ã³ã°ãããè¡šé¢ã«è¿ããããšãçµæãæ£ãã衚瀺ãããªãå ŽåããããŸãã ãããçã«ããªã£ãŠãããªããžã§ã¯ãã«å¯ŸããŠã®ã¿ãåé¢ã®ã¯ãªããã³ã°ã䜿çšããŸãã ãã ããé©åãªå€ãã·ããã«äœ¿çšããããšã«ãããããŒã¿ãŒãã³å¹æãå®å
šã«åé¿ã§ããŸãã
ããªãã奜ããããããªãã奜ãŸãªããããããªãããäžã€ã®ç®ã«èŠããæ¬ ç¹ã¯ãå
æºã®ç¯å²ã®å€åŽã®ããã€ãã®è¡šé¢ããçè«çã«å
ãåœãã£ããšããŠãé°åœ±ã§æãããããšã§ãã ããã¯ãå
æºã®åç
§ãã¬ãŒã å
ã®ãªã¢ãŒããã€ã³ãã®å Žåã座æšã1.0ãã倧ãããªãããã¯ã¹ãã£åº§æšã0.0ãã1.0ã«ã®ã¿å€åããããã§ãã è¡šé¢ãå
æºããé ãããå Žåã深床ãããã«ã¯å€ããããŸããã
äžã®ç»åã§ã¯ãå
ã®é åãæ³åããããšãã§ããŸã-ãã以å€ã¯ãã¹ãŠæ¥é°ã§ãã ç
§ããããé åã¯ã深床ããããã©ã®ããã«åºã«æ圱ããããã瀺ããŸãã ãã®åäœã®çç±ã¯ã以åã«GL_REPEAT
ã¢ãŒãã深床ãã¯ã¹ãã£ã«èšå®ããGL_REPEAT
ã§ãã
ãã®ãããªãã©ã°ã¡ã³ãã®æ·±ã1.0ãè¿ããããšæããŸã-ããã¯ãïŒå¯èŠãªããžã§ã¯ãã¯1ãè¶
ããæ·±ããæã€ããšãã§ããªãããïŒã·ã£ããŠã«æ±ºããŠå«ãŸããªãããšãæå³ããŸãã "GL_CLAMP_TO_BORDER"
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
, [0,1], 1.0, shadow
0.0. :
, . , . , .
z
, 1.0, GL_CLAMP_TO_BORDER
. ( 1.0) ( 1.0) â .
â , z .
float ShadowCalculation(vec4 fragPosLightSpace) { [...] if(projCoords.z > 1.0) shadow = 0.0; return shadow; }
1.0 .
, , , . , , .
PCF
Percentage-closer filtering
, , . , .
, . .
, .
() â PCF (Percentage-closer filtering), , . , â . , . .
PCF â :
float shadow = 0.0; vec2 texelSize = 1.0 / textureSize(shadowMap, 0); for(int x = -1; x <= 1; ++x) { for(int y = -1; y <= 1; ++y) { float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r; shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0; } } shadow /= 9.0;
textureSize
â , . , , . , . 9 (x,y)
, , .
/ texelSize
, . PCF :
. , , (, 9 ). , PCF .
, PCF, . , .
vs
. , , . . .
( ). , â .
â . , , . , , . : , .
#version 330 core out vec4 FragColor; in vec2 TexCoords; uniform sampler2D depthMap; uniform float near_plane; uniform float far_plane; float LinearizeDepth(float depth) { float z = depth * 2.0 - 1.0; // Back to NDC return (2.0 * near_plane * far_plane) / (far_plane + near_plane - z * (far_plane - near_plane)); } void main() { float depthValue = texture(depthMap, TexCoords).r; FragColor = vec4(vec3(LinearizeDepth(depthValue) / far_plane), 1.0); // perspective // FragColor = vec4(vec3(depthValue), 1.0); // orthographic }
ãã®ã³ãŒãã¯ãæ£æ圱ã§èŠããã®ãšåæ§ã®æ·±åºŠå€ã瀺ããŠããŸããããã¯ãããã°å°çšã§ããããšã«æ³šæããŠãã ãããéç·åœ¢å€æã¯å調ã§ããã2ã€ã®æ·±åºŠå€ãæ¯èŒãããšãç·åœ¢ãéç·åœ¢ãã«é¢ä¿ãªãåãçµæãåŸãããŸãã
è¿œå ã®ãªãœãŒã¹ïŒ
ãªãªãžãã«èšäº