é
ããæ©ãã3次å
ã°ã©ãã£ãã¯ã¹ã«åºäŒã£ã人ã¯å
šå¡ãã¬ã³ãã©ãŒã®ããã€ãã®ãã¹ãå«ãã¬ã³ããªã³ã°ã¡ãœããã®ããã¥ã¡ã³ããéããŸããã ãã®ãããªæ¹æ³ã«ãããæããã¹ãããã®èŒãïŒã°ããŒïŒãã¢ã³ããšã³ããªã¯ã«ãŒãžã§ã³ã被åçæ·±åºŠã®å¹æãªã©ãçŸãã广ã§ç»åãè£å®ã§ããŸãã
ã倧人ã®ãOpenGLãšç§ã®ãæ°ã«å
¥ãã®WebGLã¯ã©ã¡ãããäžéãã¯ã¹ãã£ã§çµæãã¬ã³ããªã³ã°ããããã®è±å¯ãªæ©èœãæäŸããŸãã ãã ãããã®æ©èœã®ç®¡çã¯ããªãè€éãªããã»ã¹ã§ãããå¿
èŠãªè§£å床ã®ãã¯ã¹ãã£ã®äœæãããŠããã©ãŒã ã®åœåã察å¿ããã·ã§ãŒããŒãžã®è»¢éãŸã§ãããããæ®µéã§ãšã©ãŒãçºçãããããªããŸãã
WebGLãé©åã«æºåããæ¹æ³ãçè§£ããããã«ã Align Technologyã®ã¹ãã·ã£ãªã¹ãã«é ŒããŸãã ã 圌ãã¯ãããŸããŸãªãã¯ã¹ãã£ãããã®ãã¹ãŠã®åç©åã管çããç¹å¥ãªãããŒãžã£ãŒãäœæããããšã決å®ããŸãããããã¯äœ¿ããããã§ãããã ããããæ¥ããã®ã¯ã«ããã®äžã«ãããŸãã ãã«ããã¹ã¬ã³ããªã³ã°ãæŽçããå¿
èŠæ§ã«ãããŸã§ééããããšã®ãªããæºåã®ã§ããŠããªãèªè
ã«ãšã£ãŠããã®èšäºã¯çè§£ã§ããªãããã«æããããããããŸããã ã¿ã¹ã¯ã¯éåžžã«å
·äœçã§ãããéåžžã«è峿·±ããã®ã§ãã

ç¶æ³ã®æ·±å»ããçè§£ããŠãããããã«ãäŒç€Ÿã«ã€ããŠç°¡åã«èª¬æããŸãã Alignã¯ãåŸæ¥ã®ãã¬ãŒã¹ãªãã§äººã
ãç¬é¡ãä¿®æ£ã§ãã補åãçºå£²ããŸãã ã€ãŸãã圌ãã®çŽæ¥ã®æ¶è²»è
ã¯å»åž«ã§ãã ããã¯ããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®ä¿¡é Œæ§ãããã©ãŒãã³ã¹ãããã³å質ã«çŽ æŽãããèŠæ±ã課ãç¹å®ã®èŠæ±ãããããªãéããããŠãŒã¶ãŒå±€ã§ãã ãã€ãŠãC ++ãã¡ã€ã³ããŒã«ãšããŠéžæãããŸããããé倧ãªå¶éããããŸããããã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ã®ã¿ã§ãWindowså°çšã§ãã çŽ2幎åãWebããŒãžã§ã³ãžã®ç§»è¡ãå§ãŸããŸããã ææ°ã®ãã©ãŠã¶ãŒãšãã¯ãããžãŒã¹ã¿ãã¯ã®æ©èœã«ãããã»ãŒ15幎åã«äœæããããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãè¿
éãã€äŸ¿å©ã«åäœæããã³ãŒãããŒã¹ãé©åãããããšãã§ããŸããã ãã¡ãããããã«ãããããŒã¿ããªã¥ãŒã ãšããŠã³ããŒãé床ãæé©åããå¿
èŠæ§ãªã©ãããã³ããšã³ããšããã¯ãšã³ãã§ã®äžé£ã®ã¿ã¹ã¯ã解決ããå¿
èŠãçããŸããã ãã®èšäºããã³ä»¥äžã®èšäºã¯ããããã®ã¿ã¹ã¯ã«å°å¿µããŸãã
ãããŠãäºåºŠèµ·ããªãããã«ãç§ã¯ãœãŒã¹ã§æçš¿ãæ··ä¹±ãããªãããã«ããŸãã ã€ãŸããå®è£
ã®è©³çްã«å«ãŸããã³ãŒãã®èªè
ã«ã€ã³ã¹ãã¬ãŒã·ã§ã³ãäžãããã®ã¯ãã¹ãŠãå¯èœã§ããã°èœæžãããããããããã§æç¢ºãªã¢ã€ãã¢ã«éå
ããããããŸãã ãã¬ãŒã·ã§ã³ã¯ãWebGLããã³ãã®å
éšãããã³ã®ç§å¯ã®ããŒã«ãéãããšã«åæããAlign Technologyã¹ãã·ã£ãªã¹ãã®1人ã§ããVasily Stavenkoãç§ãã¡ã«èªã£ãããã«ãäžäººç§°ã§è¡ãããŸãã
åé¡ã®èª¬æ
ãããããäœãå®è£
ãããã®ããããã«äœãå¿
èŠãªã®ããäŒãã䟡å€ããããŸãã ç§ãã¡ã®ä»æ§ã¯ã倿°ã®èŠèŠå¹æãæå³ããŸããã Screen Space Ambient OcclusionïŒãŸãã¯SSAOïŒãšã·ã³ãã«ãªã·ã£ããŠãå®è£
ããããšã«ããŸããã
SSAOã¯ã倧ãŸãã«èšã£ãŠãä»ã®ãã€ã³ãã«å²ãŸãããã€ã³ãã§ã®åèšã·ã£ããŠã€ã³ã°ã®èšç®ã§ãã ãã®ã¢ã€ãã¢ã®èŠç¹ã¯æ¬¡ã®ãšããã§ãã
float light = 0; float deltaLight; for(int astep =0; astep < ANGULAR_STEPS; ++astep){ vec2 offset = getOffset(astep, ANGULAR_STEPS); for (int rstep = 0; rstep < RADIAL_STEPS; ++rstep ){ float radius = getRadius(rstep, RADIAL_STEPS); vec4 otherPointPosition = textureLookup(offset, radius); float screenSpaceDistance = length(point.xy - otherPointPosition.xy); screenSpaceDistance = max(screenSpaceDistance, 0.00001); float deltaHeight = otherPointPosition.z - point.z; float lightness = (deltaHeight / screenSpaceDistance); // ! deltaLight = companyRelatedMagic(lightness); } light += companyRelatedMagic2(deltaLight); }
textureLookup
颿°ã¯ãæ¥ç¶ããããã¯ã¹ãã£ãããã¯ã»ã«ãéžæããŸãããã¯ã»ã«ã¯è²ã§ã¯ãªãããã€ã³ãã®äœçœ®ã§ãã æ¬¡ã«ãã€ã«ãããŒã·ã§ã³ããæ·±ãã®çŸåšã®æç»ããããã©ã°ã¡ã³ãããã®è·é¢ã«å¯Ÿããæ¯ãšããŠèšç®ããŸããããã¯ã座æšgl_FragCoords
ãŸãã æ¬¡ã«ãããžãã¯ãã³ããŒã䜿çšããŠäººã®ããžãã¯ãè¡ããç®çã®ç¯å²ã®å€ãååŸããŸãã
çµæã®ãã¯ã¹ãã£ã¯æ¬¡ã®ããã«ãªããŸãã
ããã¯æçµçãªçµæã®ããã§ãïŒ

SSAOãã¯ã¹ãã£ã®è§£å床ããã«ã€ã¡ãŒãžãããäœãããšãããããŸãã ããã¯æå³çã«è¡ãããŸãã ãã©ã°ã¡ã³ãã«äœçœ®ãã¬ã³ããªã³ã°ããçŽåŸã«ããã¯ã¹ãã£ãå§çž®ãããã®åŸã®ã¿SSAOãèšç®ããŸãã è§£å床ãäœããšãã¬ã³ããªã³ã°ãšåŠçãé«éã«ãªããŸãã ã€ãŸããæçµç»åãäœæããåã«ãäžéç»åã®è§£å床ãäžããå¿
èŠããããŸãã
èŠçŽãããšã次ã®ãã¯ã¹ãã£ãæç»ããå¿
èŠããããŸãã
GL_FLOAT
圢åŒã®å
ã®è§£å床äœçœ®ã®ãã¯ã¹ãã£- äœè§£å床ã®äœçœ®ã®ãã¯ã¹ãã£ã
- äœè§£å床ã®SSAOãã¯ã¹ãã£ã
- äœè§£å床SSAOã®ãã¯ã¹ãã£ããŒãããŠããŸãã
- é«è§£å床ã®SSAOãã¯ã¹ãã£ããŒãããŠããŸãã
- ã·ã£ããŠãã¹ã¯ãã¯ã¹ãã£ã
- æ£ãããããªã¢ã«ã§ã¬ã³ããªã³ã°ãããã·ãŒã³ç»åã
äŸåé¢ä¿ãšåå©çš
ã»ãšãã©ã®ãã¯ã¹ãã£ã¯ãæ¢ã«ã¬ã³ããªã³ã°ããããã¯ã¹ãã£ãããå Žåã«ã®ã¿ã¬ã³ããªã³ã°ã§ããŸãã ããã«ããããã®ããã€ãã¯è€æ°å䜿çšã§ããŸãã ã€ãŸããäŸåé¢ä¿ã§æ©èœããã¡ã«ããºã ãå¿
èŠã§ãã
ãããã°
ã¬ã³ããªã³ã°ããã»ã¹ããããã°ããã«ã¯ãä»»æã®ãã¯ã¹ãã£ãæ¢åã®ã³ã³ããã¹ãã«æã£ãŠãããšäŸ¿å©ã§ãã
ãã¯ã¹ãã£ãšãã¬ãŒã ãããã¡ã®ç®¡ç
ç§ãã¡ã¯ãã§ã«THREE.jsãã¬ãŒã ã¯ãŒã¯ãäœæ¥ã«äœ¿çšããŠãããããæ¬¡ã®èŠä»¶ãæ¢ã«ãããšã®çžäºäœçšããçããŠããŸãã çŽç²ãªWebGLã«ã¹ãªããããªãããšã決å®ããæ®å¿µãªãããã¬ãŒã ãããã¡ãŒã®ãªãŒããŒããããæäŸããTHREE.WebGLRenderTarget
ã䜿çšãTHREE.WebGLRenderTarget
ã ãããããã®ãªãŒããŒãããããã£ãŠããã¬ã³ããªã³ã°ã¯èš±å®¹å¯èœãªé床ã§åäœãããã®ãããªãªããžã§ã¯ãã®ç®¡çã¯ã2ã€ã®é¢é£ãããåæã«ç¬ç«ãããªããžã§ã¯ãã管çãããããã¯ããã«ç°¡åã§ãã
ãã¯ã¹ãã£è§£å床管ç
ç»ååºåã³ãŒããå®å
šã«å€æŽããå¿
èŠããªããè§£å床ããããªãã¯ã¹ãªã©ã倿Žããå¿
èŠããªããšããäºå®ã«ç
©ããããããšãªããæ°å€ãšå
ã®å¶éã®éæ³ã§ããŠã³ãµã³ããªã³ã°ãã©ã¡ãŒã¿ãŒããåçãã§ããããã«ããããšèããŠããŸãã ãããã£ãŠããããŒãžã£ãŒã®ãµã³ããªã³ã°ã¡ã«ããºã ããçž«ãåããããããšã決å®ãããŸããã
ã·ãŒã³ãã¬ã³ããªã³ã°ããåã«ãããªã¢ã«ã眮ãæãã
THREE.Scene
å
ã®ãã¹ãŠã®ãªããžã§ã¯ãã®ãããªã¢ã«ã¯ããªããžã§ã¯ãã®å¯èŠæ§ãèæ
®ããŠäœçœ®ãæç»ããããã«äº€æãããã®åŸæå€±ãªã埩å
ããå¿
èŠããããŸãã ããã§ã Scene.overrideMaterial
ãã©ã¡ãŒã¿ãŒã䜿çšã§ããããšã«Scene.overrideMaterial
ãã ããã ãããããã®å Žåãããžãã¯ã¯ããè€éã«ãªããŸããã
å®è£
ãäž»ãªã¢ã€ãã¢ã§ã
ãã®çµæãç§ãã¡ã¯äœãããŸãããïŒ
æåã«ã圌ãã¯ãããŒãžã£ãŒãäœããŸããããã®èª¬æã¯ä»¥äžã«ãããŸãã ãŸããã·ã§ãŒããŒãèªåçã«èªã¿åããã¬ã³ããªã³ã°ããã®ã«å¿
èŠãªãã¯ã¹ãã£ãŒã確èªããã¯ã©ã¹ãäœæããŸããã ãããŒãžã£ã¯ããã¯ã¹ãã£ãã¬ã³ããªã³ã°ããããã®äŸåé¢ä¿ãããããšãçè§£ã§ããå¿
èŠãªäŸåé¢ä¿ãæç»ããå¿
èŠããããŸãã
ãã®ãããŒãžã£ãŒã¯ãPassã¯ã©ã¹ã€ã³ã¹ã¿ã³ã¹ã§åæåãããããšã«ãªã£ãŠããŸãã ã€ãŸããããã»ãŒãžã远å ããå¥ã®ãªããžã§ã¯ããå¿
èŠã§ããããã§ã«ã¢ããªã±ãŒã·ã§ã³åºæã§ãã ææ°ã®WebGLã·ã§ãŒããŒã§ã¯çºä¿¡ãã¯ã¹ãã£ã®ååãæå®ã§ããªããããScreenSpacePassãå¿åã«ãã远å ãããšãã«ååãä»ããå¿
èŠããããŸããã ãããŠã圌ãã¯ã·ã§ãŒããŒããã¹ããããããèªãããšãã§ããŸããã
ãã®ãããªæ¹æ³ã¯æ¬¡ã®ãšããã§ãã
addPass(name, pass){ if(!pass instanceof Pass) throw new Error("Adding wrong class to renderer passes"); pass.setSceneAndCamera(this.screenSpaceScene, this.camera); this.passes.set(name, pass); }
ã¯ããåããããŒãžã£ã§screenSpaceSceneç¶æ
管çãåæããŸããã 幞ããªããšã«ãããã¯ç»é¢å
šäœãéããå¯äžã®ãžãªã¡ããªã¡ãã·ã¥ã§ãã
ç¹å®ã®ããã»ãŒãžãç»é¢ã«æç»ããããã«å¿
èŠãªã¡ãœããã¯æ¬¡ã®ãšããã§ãã
if(!this.passes.has(name)) throw new Error(`Multipass manager has no rendertarget named ${name}`) const target = this.passes.get(name); if(target.dependencies) { this._prepareDependencies(target.dependencies);
ããã€ãã®ã³ã¡ã³ãïŒ
- åç®æšã¯ãã¬ã³ããªã³ã°ã®ãã¹ã§ãã
this.passes
ã¯javascript MapïŒïŒã®ã€ã³ã¹ã¿ã³ã¹ã§ãïŒã¿ã€ãïŒ Map<String, Pass>
ïŒãtarget.dependencies
ã¯ãã·ã§ãŒããŒã®ãã¯ã¹ãã£ãŠããã©ãŒã ã®ãªã¹ãã§ãã æ£èŠè¡šçŸã䜿çšããŠã·ã§ãŒããŒãœãŒã¹ããèªã¿åããŸããinstallDependencies
ã¯ãŠããã©ãŒã ã®ã€ã³ã¹ããŒã«ã«ãããŸããã- åäŸåé¢ä¿ã®
this.prerender
ã¯ãæå®ããã颿°ã®åйã§ããthis.prerender
颿°ãå®è¡ããŸãã ã¡ãœããã®éãã¯ãããã§ããããšãã°ãã¬ã³ããªã³ã°ã¯ã¿ãŒã²ããã®ãã¬ãŒã ãã¬ãŒã ãããã¡ã«éãããŸãã
this.renderer.render(target.getScene(), target.getCamera(), target.framebuffer);
ãããã£ãŠããã®ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠãã¹ã®å
±éã¯ã©ã¹ã次ã®ããã«æç»ããŸããã
class Pass{
ä»çµã¿
ãŸãããããŒãžã£ãŒãæ§æããå¿
èŠããããŸãã ãããè¡ãã«ã¯ããããã€ã³ã¹ã¿ã³ã¹åããããã«ããã€ãã®Pass-sã远å ããŸãã æ¬¡ã«ãã³ã³ããã¹ãã«ãã¹ãæç»ããå¿
èŠãããå Žåã¯ãåã«åŒã³åºããŸã
manager.renderOnCanvas("passName");
ãã®ãã¹ã¯ç»é¢ã«æç»ããå¿
èŠãããããããŒãžã£ãŒã¯ãã®åã«ãã¹ãŠã®äŸåé¢ä¿ãæºåããå¿
èŠããããŸãã ãã¯ã¹ãã£ãåå©çšãããã®ã§ããããŒãžã£ãŒã¯æ¢ã«æç»ããããã¯ã¹ãã£ã®ååšã確èªããæåŸã®ãã¬ãŒã ã®ãã¯ã¹ãã£ãæç»ã§ããªããã¯ã¹ãã£ã§ãããšå€æããªãããã«ãæç»ãéå§ããåã«å€ããã¯ã¹ãã£ããªã»ããããŸãã ãã®ããããããŒãžã£ãŒã«ã¯ã察å¿ããååstart
颿°ããããŸãã
function render(){ manager.start(); manager.renderOnCanvas('mainPass'); }
調åã®ãšããã¹ããŒã ã®æ··ä¹±ã¯ãã¡ã€ã³ãã£ã³ãã¹ã«åéæã®ãã¯ã¹ãã£ãæç»ããå¿
èŠæ§ã«ãã£ãŠçããŸããã ãã¬ã³ãããå Žåã以åã®çµæãæ¶å»ããå¿
èŠã¯ãªãããã¬ã³ãèªäœãèšå®ããå¿
èŠããããŸãã ç§ãã¡ã®å Žåãæºåããããã¯ã¹ãã£ã¯ããã¬ã³ãã«ãã£ãŠæçµã¬ã³ããªã³ã°äžã«ç»åã«éããããŸãã æé ã¯æ¬¡ã®ãšããã§ãã
- gl.Clearã䜿çšããŠèæ¯ãæ¶å»ããŸããthree.jsã¯ãæ¶å»ããå¿
èŠããªãããšãéç¥ããªãå Žåããããèªåçã«å®è¡ããŸãã
- ãã¬ã³ãã§åœ±ãä»ããŸãã
- éæåºŠã䜿çšããŠé¡ã®ç»åããªãŒããŒã¬ã€ããŸãã
- SSAOã課ããŸãã
ãã®ããã«ïŒ
function render(){ this.passManager.start(); if(showShadow) this.passManager.renderOnCanvas('displayShadow'); this.passManager.renderOnCanvas('main', { clear:{color:false, stencil:true, depth:true} }); if(showSSAO) this.passManager.renderOnCanvas('displaySSAO',{ clear:{color:false, stencil:true, depth:true} }); }
ããããªéãã¯ãã«ã©ãŒãããã¡ãŒãæ¶å»ããããä»ã®ãã¹ãŠã®ãããã¡ãŒãã¯ãªã¢ãããããšã§ãã
äœããã®çš®é¡ã®äžéãã¯ã¹ãã£ã衚瀺ãããå ŽåïŒãããã°ç®çãªã©ïŒãã¬ã³ããªã³ã°ããããã«å€æŽããããšããã§ããŸããã ããšãã°ãäžã§åŒçšããSSAOã®ãã¯ã¹ãã£ã¯ã次ã®ã³ãŒãã§ã¬ã³ããªã³ã°ãããŸããã
function render(){ this.passManager.start(); this.passManager.renderOnCanvas('ssao'); }
ScenePassã®å®è£
次ã«ããã¯ã¹ãã£ã®ã·ãŒã³ã®éè·¯ãæç»ããæ¹æ³ã«ã€ããŠè©³ãã説æããŸãã æããã«ãã·ãŒã³ãã¬ã³ããªã³ã°ããŠãããªã¢ã«ã眮ãæããããšãã§ãããã®ãšããã¹ãŠãç»é¢åº§æšã§ã¬ã³ããªã³ã°ãããã®ãå¿
èŠã§ãã
export class ScenePass extends Pass{ constructor(scene, camera, options={}){ let prerender=options.prerender ||null, postrender=options.postrender || null; super(options.framebufferOptions); this.scene = scene; this.camera = camera; this._prerender = prerender; this._postrender = postrender; this._clearOptions = options.clearOptions; this.overrideMaterial = options.overrideMaterial || null; } setSceneAndCamera(){
ãããã¯ã©ã¹å
šäœã§ãã ã»ãšãã©ãã¹ãŠã®æ©èœãèŠªã«æ®ã£ãŠãããããéåžžã«ç°¡åã§ããããšãããããŸããã ã芧ã®ããã«ããã¹ãŠã®é©åãªãªããžã§ã¯ãã§ã®ãããªã¢ã«ã®é 次亀æäžã§ã¯ãªããã·ãŒã³å
šäœã®ãããªã¢ã«ã1ã€ã®å²ãåœãŠæäœã§äžåºŠã«çœ®ãæããããšãã§ããå Žåã overrideMaterial
ãæ®ãããšã«ããŸããã å®éã _prerender
ãš_postrender
ãããã¯ãåã
ã®ã¡ãã·ã¥ã®ãããªã¢ã«ã®ããªãè³¢ã代æ¿åã§ãã ç§ãã¡ã®å Žåãæ¬¡ã®ããã«ãªããŸãã
class Pass{
Scene.traverse
ã¯ãã·ãŒã³å
šäœã§ååž°çã«å®è¡ãããTHREE.jsã¡ãœããã§ãã
ScreenSpacePassã®å®è£
ScreenSpacePassã¯ãäžå¿
èŠãªãã€ã©ãŒãã¬ãŒããªãã§äœæ¥ããããã«ãã·ã§ãŒããŒããå¿
èŠãªæå€§æ
å ±ãæœåºããããã«èæ¡ãããŸããã ã¯ã©ã¹ã¯éåžžã«è€éã§ããããšã倿ããŸããã äž»ãªé£ç¹ã¯ããµã³ããªã³ã°ãæäŸããããžãã¯ãã€ãŸãããã¯ã¹ãã£ã«é©åãªæš©éãèšå®ããããšã§ãã ãã¯ã¹ãã£ã§ã¯ãªãç»é¢äžã«æç»ãããå ŽåãçŸåšã®ãã¬ãŒã ãããã¡ã®è§£å床ãèšå®ããããã®è¿œå ã®æ¹æ³ãéå§ããå¿
èŠããããŸããã æè¡çãªè€éããã¯ã©ã¹ã®è²¬ä»»ããšã³ãã£ãã£ã®æ°ãã¿ã¹ã¯ã«å²ãåœãŠãããæéã®éã§åŠ¥åããªããã°ãªããŸããã§ããã
ãŠããã©ãŒã ã®èªåæ€çŽ¢ãšã€ã³ã¹ããŒã«ã¯ããã¯ã¹ãã£ã®ãŠããã©ãŒã åã®ã¿ã€ããã¹ãªã©ã®åé¡ããã°ããèŠã€ããã®ã«åœ¹ç«ã¡ãŸããã ãã®ãããªå ŽåãGLã¯ä»ã®ãã¯ã¹ãã£ãŒã䜿çšã§ããŸãããç»é¢ã«è¡šç€ºããããã®ã¯æ£ç¢ºã«è¡šç€ºãããããã®çç±ãããããŸããã
export class ScreenSpacePass extends Pass { constructor(fragmentShader, options = {}){
ããã§ããœãŒã¹ã³ãŒãã¯éåžžã«å€§ãããã¯ã©ã¹ã¯éåžžã«ã¹ããŒãã§ããããšã倿ããŸããã ãã ããã»ãšãã©ã®ã³ãŒãã¯ãã·ã§ãŒããŒã«ãã¯ã¹ãã£ã®ãŠããã©ãŒã ããããã©ãããæ€åºããããããäŸåé¢ä¿ãšããŠèšå®ããã ãã§ããããšãããããŸãã
æåŸã«ãã©ã®ããã«äœ¿çšãããã瀺ããŸãã EffectComposer
ãšåŒã°ããã¢ããªã±ãŒã·ã§ã³åºæã®ãšã³ãã£ãã£ã 圌ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãèšè¿°ããããããŒãžã£ãŒãäœæãã圌ã®ãã¹ãäœæããŸãã
this.passManager = new PassManager(threeRenderer); this.passManager.addPass('downscalePositionSSAO', new ScreenSpacePass(require('./shaders/passingFragmentShader.glsl'), {scaleFactor}) ); this.passManager.addPass('downscalePositionShadow', new ScreenSpacePass(require('./shaders/positionDownSampler.glsl'), {scaleFactor}) ); this.passManager.addPass('ssao', new ScreenSpacePass(require('./shaders/SSAO.glsl'), {scaleFactor}) );
äŸãšããŠãpassingFragmentShader.glslãã¡ã€ã«ã®å
容ïŒ
precision highp float; uniform sampler2D positions;
ã·ã§ãŒããŒã¯éåžžã«çã-è£éããããã¯ã»ã«ãååŸãããããæž¡ããŸãã ãã¹ãŠã®äœæ¥ã¯ããã¯ã¹ãã£èšå®ïŒ GL_LINEAR
ïŒã®ç·åœ¢è£éã«ãã£ãŠè¡ãããŸãã
次ã«ã positions
ãã©ã®ããã«æç»ãããããèŠãŠã¿ãŸãããã
ããã°ã©ã ã®ä»ã®å Žæã§äœæ¥ã·ãŒã³ãå¿
èŠãªã®ã§ã EffectComposer
ãã®ææè
ã§EffectComposer
ãªããå¿
èŠãªãšãã«å°ããããŸãã
function updateScenes(scenes, camera){ this.passManager.addPass('main', new ScenePass(scene, camera)); this.passManager.addPass('positions', new ScenePass(scene, camera, { prerender: materialReplacer, postrender:materialRestore, framebufferOptions })) }
ã芧ã®ããã«ã誰ããã·ãŒã³ã®å€æŽã«ã€ããŠç§ãã¡ã«éç¥ãããšã EffectComposer
ã¯2ã€ã®Pass-aãäœæããŸãã1ã€ã¯ããã©ã«ãèšå®ã§ããã1ã€ã¯å·§åŠãªãããªã¢ã«ã®çœ®ãæãã§ãã ã·ãŒã³ã®ããã»ãŒãžã«ã¯ããªãããŒãªäŸåé¢ä¿ã¯å«ãŸããŠããŸãããååãšããŠããããã¯åç¬ã§æç»ãããŸããã説æããã¢ãããŒãã§ã¯ãäŸåé¢ä¿ã远å ããããã«ScenePassã«ããã€ãã®ã¡ãœããã远å ãããšãããè¡ãããšãã§ããŸãã ã·ãŒã³ã®ã©ã®çš®é¡ã®ãããªã¢ã«ãã¬ã³ããªã³ã°ãããäŸåé¢ä¿ãæã¡ããã®ãã¯æããã§ã¯ãªãããã§ãã
ãããã«
ãã®ã±ãŒã¹ã§ã¯äœ¿ããããã«ãããããããã·ã§ãŒããŒã«åºã¥ãããã¹ã®å®å
šèªåçæãå®çŸã§ããŸããã§ããã ãã¯ã¹ãã£åºåãã©ã¡ãŒã¿ãŒGL_RGB
ã GL_RGBA
ã GL_FLOAT
ã GL_UNSIGNED_BYTE
ãªã©ã®è¿œå ãã©ã¡ãŒã¿ãŒã§ã·ãŒã³ã¬ã³ããªã³ã°ããã»ãŒãžãè£å®ããããŒã«ãŒãã·ã§ãŒããŒã«è¿œå ããããããŸããGL_UNSIGNED_BYTE
ã ããã«ãããäžæ¹ã§ã¯ã³ãŒããç°¡çŽ åãããŸãããã·ã§ãŒããŒãåå©çšããèªç±åºŠãäœããªããŸãã ã€ãŸãããã®èšå®ã¯ãŸã 説æããå¿
èŠããããŸããã
äŸåé¢ä¿ãããã³ã°ããŸã å®è£
ããªããã°ãªããªãã£ãããšã«èšåãã䟡å€ããããŸãã ããã¯ã1ã€ã®ã·ã§ãŒããŒãè€æ°ã®ãã¹ã§äœ¿çšããç°ãªãå
¥åãã¯ã¹ãã£ã§äœ¿çšããå Žåã«åœ¹ç«ã€ããšã倿ããŸããã ãã®å Žåãåãã¹ã¯é¢æ°ã®ããã«èŠãå§ãããããå°ããããæ©èœçãã«è¡ãæ¹æ³ãèããŸããã
ããããéçºå
šäœãéåžžã«æçšã§ããããšã倿ããŸããã ç¹ã«ã倧å¹
ãªå°é£ãªãã«ãããžã§ã¯ãã«ãšãã§ã¯ãã远å ã§ããŸãã å人çã«ã¯ãã€ã¡ãŒãžãç°¡åã«ãããã°ã§ããæ©èœãæãæ°ã«å
¥ã£ãŠããŸãã