ãã®ãã¥ãŒããªã¢ã«ã§ã¯ããã¢ã¢ãã«ã®äŸã䜿çšããŠãèšç®ã·ã§ãŒããŒã䜿çšããŠãããªã«ãŒãã«èšç®ãå®è£
ããæ¹æ³ã瀺ããŸãã
Unity3Dã®ãããžã§ã¯ãã次ã«ç€ºããŸãããã®ã¬ã€ãã®äœæã«é¢ãã説æããããŸãã Unityã§ããŠã³ããŒãããŠéãå¿
èŠããããŸãã
Unityãããžã§ã¯ããªã³ã¯èª°ããã®ã¬ã€ããç解ããŸããïŒ Unity3Dã䜿çšããããå°ãªããšãCïŒãŸãã¯C ++ãç¥ã£ãŠãã人ã ã·ã§ãŒããŒã¯HLSLã§èšè¿°ãããŠããŸããHLSLã¯ãC ++ã®å¯æ¥ãªæ§æé¢é£ã§ãã
ãã®ã¬ã€ãã®æ©æµãåããã®ã¯èª°ã§ããïŒ GPUãã³ã³ãã¥ãŒãã£ã³ã°ã«äœ¿çšããæ¹æ³ãåŠã³ããçµéšè±å¯ãªããã°ã©ããŒã ããããçµéšã®æµ
ãå€åãªããã°ã©ããŒã§ãããã¹ãŠãç°¡åã«ç解ã§ããŸãã
ã³ã³ãã¥ãŒãã£ã³ã°ã«ã°ã©ãã£ãã¯ã«ãŒãã䜿çšããçç± äžŠåã¿ã¹ã¯ã®å Žåããã®ããã©ãŒãã³ã¹ã¯ããã»ããµã®ããã©ãŒãã³ã¹ã®10ã100åã§ãã ã€ãŸããã³ã³ãã¥ãŒã¿ãŒã®å
šå¡ã䟿å©ãªAPIãåããå°ããªã¹ãŒããŒã³ã³ãã¥ãŒã¿ãŒãæã£ãŠããã®ã§ãé©åãªå Žåã«äœ¿çšããã®ãçã«ããªã£ãŠããŸãã
ãã®å·šå€§ãªããã©ãŒãã³ã¹ã¯æ¬åœã«å¿
èŠã§ããïŒ ã¯ããããã»ããµã®é床ã¯å€ãã®å Žåå¶éèŠå ã§ãã ããšãã°ã倧ããªããŒã¿ã»ããã§åãæäœãå®è¡ããå¿
èŠãããå Žåã ããããæ£ç¢ºã«ãã®ãããªã¿ã¹ã¯ã¯ç°¡åã«äžŠååãããŸãã ããã«ãå€ãã®å Žåãéçºè
ã¯èšç®èœåã®ããã«æ±ºå®ãæåŠããã¢ã«ãŽãªãºã 空éã®å
šé åã¯æªèžã®ãŸãŸã§ãã ããšãã°ãGPUãé©åã«ããŒããããšãã²ãŒã ã§æãã¯ãŒã«ãªç©çåŠãè¡ãããšãã§ããŸãã
ãããŠããããªã«ãŒãã䜿çšãããšããã«ãŒããã©ãŒã¹ã§åé¡ãç°¡åã«è§£æ±ºã§ããŸãã æé©åã®èŠæ±ã¯ãéã®æ§èœã«äŸåããŸããã å¹çã®æªãã³ãŒãããã£ãããšããŒãã§ããªããããªã¹ãŒããŒã³ã³ãã¥ãŒã¿ãŒã¯ãããŸããã
ã·ã§ãŒããŒãæ£ç¢ºã«èšç®ããçç± ãªãopenclãŸãã¯cudaã§ãªãã®ã§ããïŒ Cudaã¯nvidiaããŒããŠã§ã¢ã§ã®ã¿åäœããopenclãç¥ããŸããã Unityã¯ãopenglã³ã¢ãå«ãä»»æã®APIã§ãã«ãã§ããŸãã MacãAndroidã³ã³ãã¥ãŒã¿ãŒã§ã¯ãã·ã§ãŒããŒãåäœããŸãããLinuxã§ãåäœããããã§ãïŒè©Šããããšã¯ãããŸãããïŒã ãã ããåAPIã«ã¯èæ
®ãã¹ãå¶éããããŸãã ããšãã°ãMetalã§ã¯ã1ã€ã®è»žã«æ²¿ã£ãŠ256ãè¶
ããã¹ã¬ãããäœæã§ããŸããïŒDX10-1024ïŒã ãŸããAndroid APIã¯ãã«ãŒãã«ããšã«4ã€ãè¶
ãããããã¡ãŒã䜿çšã§ããŸããïŒDX10-8ãDX11-ããã«ãã以äžïŒã
ãªãç©çã·ãã¥ã¬ãŒã·ã§ã³ãªã®ãïŒ ããã¯èšç®éçŽçãªã¿ã¹ã¯ã§ããã䞊åèšç®ã«é©ããŠããŸãã ããã«ãã¿ã¹ã¯ã¯éèŠããããŸãã ã²ãŒã éçºè
ã¯ã²ãŒã ã«èå³æ·±ãç©çåŠãå®è£
ã§ããåŠçã¯åŠææ«ã¬ããŒãçšã®å®éšã¢ãã«ãäœæã§ãããšã³ãžãã¢ãšç§åŠè
ã¯ã¢ãã«ã®èšç®ãè¡ãããšãã§ããŸãã
ãããŠããªãæ£ç¢ºã«é«ªã®ã¢ãã«ã§ããïŒ ç§ã¯åçŽãªããºã«ãåãããã£ãããåæã«äž»èŠãªåé¡ãã«ããŒããã
ãã®ããã¥ã¢ã«ã®äœ¿çšæ¹æ³ ãœãŒã¹ã³ãŒããããŠã³ããŒãããéããŠãããã¥ã¢ã«ãé²ããªããèªãã§ãã ããã ãã¹ãŠã®äž»èŠãªè¡ã詳现ã«èª¬æããŸããããã¹ãŠã®è¡ãå®å
šã«èª¬æããããã§ã¯ãããŸããããã»ãšãã©ã®è¡ã®æå³ã¯æããã§ãã ããã¹ãã«ã¯è€éãªã¢ã«ãŽãªãºã ã¯ãããŸãããGPUã³ã³ãã¥ãŒãã£ã³ã°ãæäŸããã¯ã©ã¹ã®ã€ã³ã¿ãŒãã§ãŒã¹ã®ã¿ã䜿çšããŠããŸãã ã·ã§ãŒããŒã³ãŒãã®åŽã§ã¯ãããŒã¿ãèªã¿åãããããã«å¯ŸããŠç°¡åãªæ°åŠæŒç®ãå®è¡ããçµæãèšé²ãã以å€ã«äœããããŸããã ããããäœãã¯ã£ããããªãããšãããã°ãå¿
ãå°ããŠãã ããã
ãããŠä»ãèšç®ã·ã§ãŒããŒã®äœ¿çšã«ã€ããŠå
šãç¥ããªã人ã®ããã«ãç§ã¯äžæ©èžã¿åºããã³ã³ãã¥ãŒã¿ãŒã·ã§ãŒããŒã®äœ¿çšã®åºæ¬ã«å°å¿µãã
éåžžã«ç°¡åãªã¬ã€ãã«é²ãããšããå§ãããŸãã æ¬è³ªãããããç解ããGPUã³ã³ãã¥ãŒãã£ã³ã°ã®å®è·µã«éåžžã«ç°¡åãªäŸã§æ
£ããããã«ããŸãå§ããããšããå§ãããŸãã ãããŠãããã«æ»ã£ãŠç¶è¡ããŸãã ãããŠãå°ãªããšãã³ã³ãã¥ãŒã¿ãŒã·ã§ãŒããŒã«ããçšåºŠç²ŸéããŠãã人ã¯ã倧èã«èªã¿é²ããŠãã ããã
GPUã§æåããèšç®ãããç©çã¢ãã«ãäœæããå Žåããã®ã¿ã¹ã¯ã¯4ã€ã®éšåã«åããããšãã§ããŸãã
-çŸè±¡ã®æ°åŠã¢ãã«
-ã¢ãã«ã®äžŠåèšç®ã®ã¢ã«ãŽãªãºã
-ã·ã§ãŒããŒã³ãŒã
-ãŠãããå
ã®ã·ã§ãŒããŒã®æºåãšèµ·å
æ°åŠã¢ãã«
ãããªã«ãŒãã®é·æã¯ã1ã€ã®æäœãå€ãã®ãªããžã§ã¯ãã«åæã«é©çšã§ããããšã§ãã ãããã£ãŠã髪ã®ã¢ãã«ã¯ãããããã2ã€ã®é£æ¥ããããããšçžäºäœçšããäžé£ã®ããããšããŠäœæã§ããŸãã ç¹éã®çžäºäœçšã¯ãã°ãã®åçã«åºã¥ããŠããŸãïŒk *ïŒS0-SïŒ^ nãããã§S0ã¯å¹³è¡¡è·é¢ãSã¯çŸåšã®è·é¢ã§ãã çŸå®ã«ã¯ã髪ã®æ¯ã¯ã°ãã®ããã«èŠããã䌞ã³ãªãããã«æããããŸãã ããã¯ãã¢ãã«ã®ã¹ããªã³ã°ãååã«ç¡¬ãããå¿
èŠãããããšãæå³ããŸãã 次æ°ã¯å¹³è¡¡ã®è¿ãã§æ²ç·ã®æ²çã倧ããããããã¯ã©ãã·ã¥ãæžããã髪ã®ããŽã ãã®å¹æãæžããã®ã§ãnãå¢ããããšã§ã¹ããªã³ã°ã®åæ§ãå¢ããããšããå§ãããŸãã n = 2ãåããŸããã以äžã§ä¿æ°kã®å€ã«ã€ããŠèª¬æããŸãã
ãã€ã³ãéã®åŒŸæ§åã«å ããŠãçžå¯Ÿé床ãŸãã¯äžæ¬¡å
ç²æ§ã®æ¡æ£ãå®çŸãããŸãã æ¥ç·é床æåã®äº€æã¯ãåçåŒåŒµåŒ·åºŠãããã³éåžžã®é床ç¹æ§-åçæ²ãæµæã®äº€æãã¢ãã«åããŸãã äžç·ã«ãããã¯é«ªã«æ²¿ã£ãå€ä¹±ã®äŒéãå éãããã€ããã¯ã¹ãæ¹åãã髪ãèŠèŠçã«ããã€ãªãã匟åæ§ãæžãããŸãã
ããã«ããŸã£ããã«ãªãéçãªåŸåããããŸãã åãã€ã³ãã¯ã髪ã®æãç®ãè£æ£ããããšããŸãã ãã€ã³ãã«ãã³ããããå Žåããã³ãå€ã«æ¯äŸãããã³ãå€ãæžå°ãããæ¹åã«åããããåããã€ã³ãã«äœçšããŸãã ãã³ããã€ã³ãã«é£æ¥ãã2ã€ã®ãã€ã³ãã«ã¯ãå察æ¹åã®ååã®åãããããŸãã
ãããã®çžäºäœçšã¯ã髪ã®ç©çåŠãã·ãã¥ã¬ãŒãããã®ã«ååã§ãããããã«éå®ãããŸããã ãã¢ãšãœãªãããªããžã§ã¯ãã®çžäºäœçšãè¿œå ããå¿
èŠããããŸãã ããã¯å®çšçã§ãã ãã€ã³ãã¯ãç©çã¢ãã«ãååãšããŠã液äœãšåºäœãªã©ã®ç°ãªã䞊åã·ãã¥ã¬ãŒã·ã§ã³ãšã³ãã£ãã£éã®çžäºäœçšãå«ãããšã ãã§ã¯ãããŸããã ããããå®éã®ã¿ã¹ã¯ãããšãã°ã²ãŒã ã§ã¯ãGPUã·ãã¥ã¬ãŒã·ã§ã³ã¯CPUåŽã§èšç®ããããªããžã§ã¯ããšãªã¢ã«ã¿ã€ã ã§çžäºäœçšããå¿
èŠããããšããäºå®ã«ããããŸãã ã§ããããç§ã¯ãã®ãããªçžäºäœçšã«æ³šæãæããããããŸããã§ããã ç§ãã¡ã®é«ªã¯åºäœãšçžäºäœçšãããã®æ
å ±ã¯åã¡ãžã£ãŒã§ãããªã¡ã¢ãªã«éä¿¡ãããŸãã
ç°¡åã«ããããã«ãäžžããªããžã§ã¯ãã§ã®ã¿äœæ¥ããŸãã CPUåŽã«ã¯ãæšæºã®2DãŠãããç©çåŠããã®ããã€ãã®ãµãŒã¯ã«ã³ã©ã€ããŒããããŸãã çžäºäœçšã®ã«ãŒã«ã¯æ¬¡ã®ããã«ãªããŸãã髪ã®ãã€ã³ãããœãªããã®å
åŽã«ããå Žåãããã¯å€åŽã«è»¢éãããäœã«åããéšåã¯ãã®ãããªãã€ã³ãã®é床ããå·®ãåŒãããåãéšåãäœã«è»¢éãããŸãã ç°¡åã«ããããã«ãäœã®çµ¶å¯Ÿé床ã¯èæ
®ããŸããã
ã¢ã«ãŽãªãºã ãã³ãŒããã·ã§ãŒããŒã®æºå
ãããã®3ã€ã®ãã€ã³ãã¯ãããããå¥ã
ã«è°è«ããã«ã¯ããŸãã«ãé¢é£ããããŠããŸãã
å€ãã®ãã¢ãäœããããã€ã³ãã説æããããã«ã次ã®æ§é ã䜿çšããŸãã
struct hairNode{ float x; // float y; // float vx; // float vy; // int dvx; // - int dvy; // int dummy1; // 128 int dummy2; // }
ãã®æ§é ã¯ãCPUåŽãšGPUåŽã§2å宣èšãããŸãã 䟿å®äžã CPUåŽã§ã¯ãåæããŒã¿ãæžã蟌ã¿ãGPUãããã¡ãŒã«ã³ããŒããŠãããããã§åŠçãããŸãã ãã ããåæããŒã¿ãéä¿¡ããå¿
èŠããªãå Žåã¯ãGPUåŽã§ã®ã¿ãã®æ§é ã説æã§ããŸããã
ãã©ã¡ãŒã¿ãŒã«ã€ããŠã¯ãdummy1ããã³dummy2 nvidiaã®ãšã³ãžãã¢ãæžããèšäºã§ããããªã¡ã¢ãªãããã¡ã®ããŒã¿ã128ãããã®åæ°ã§ä¿æããæ¹ãè¯ãããšãèªã¿ãŸããã ããã«ããããªãã»ããã®èšç®ã«å¿
èŠãªæäœã®æ°ãæžããŸãã
æ®ãã®ãã©ã¡ãŒã¿ãŒã®å€ã¯æ確ã ãšæããŸãã ãããã泚ææ·±ãèªè
ã¯å°ãããããããŸããïŒãªãé床ã¯ãããŒãã®äžçš®ã§ãããé床ã®å€åã¯intã§ããïŒ ç°¡åãªçãïŒé床ã®å€æŽã¯äžŠåã¹ã¬ããã«ãã£ãŠåæã«å€æŽããããããèšç®ã®ãšã©ãŒãåé¿ããã«ã¯ãå®å
šãªã¬ã³ãŒãã䜿çšããå¿
èŠããããŸãã ãŸããä¿è·ãããæžã蟌ã¿é¢æ°ã¯æŽæ°å€æ°ã§ã®ã¿æ©èœããŸãã ããã«ã€ããŠã¯ã以äžã§è©³ãã説æããŸãã
髪ã®ã¢ãã«åã«ã¯å€ãã®ãã€ã³ãããããŸãã ãã¹ãŠã®ãã€ã³ãã®ããŒã¿ã¯ãããªã¡ã¢ãªã«ä¿åããããããã¡ã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠã¢ã¯ã»ã¹ã§ããŸãã
RWStructuredBuffer<hairNode> hairNodesBuffer;
ã·ã§ãŒããŒã³ãŒãã§ã¯ããã®ååãšããŒã¿åã®ã¿ã決å®ãããã®ãµã€ãºã¯ãããã»ããµã§å®è¡ãããã³ãŒãã®åŽããå€éšã§èšå®ãããŸãã
ã³ã³ãã¥ãŒã¿ãŒã·ã§ãŒããŒã³ãŒãã¯ã©ã®ããã«æ§é åãããŠããŸããïŒ ã³ãŒãã¯ã«ãŒãã«ã§æ§æãããŠããŸãã ããã¯ã¡ãœãããšåãã§ãããåã«ãŒãã«ã¯è€æ°ã®ã³ã¢ã§äžŠè¡ããŠå®è¡ãããŸãã ãããã£ãŠãããããã«ã€ããŠããããŒã®æ°ã¯3次å
æ§é ã®åœ¢ã§ç€ºãããŸãã
ããã¯ã空ã®ã«ãŒãã«ã®ããã«èŠãããã®ã§ãã³ãŒãã¯ãªããå¿
èŠãªå€éšæ
å ±ã®ã¿ããããŸãã
#pragma kernel kernelName [numthreads(8,4,1)] void kernelName (uint3 id : SV_DispatchThreadID){ // }
ã«ãŒãã«ã«ã¯ãã¹ããªãŒã ã®3次å
ã€ã³ããã¯ã¹ãæ ŒçŽããå
¥åãã©ã¡ãŒã¿ãŒidããããŸãã ããã¯éåžžã«äŸ¿å©ã§ããåã¹ã¬ããã¯ç¬èªã®ã€ã³ããã¯ã¹ãç¥ã£ãŠãããããç¬èªã®åå¥ã®ããŒã¿ãŠãããã§äœæ¥ã§ããŸãã
ããã»ããµåŽã§ã¯ãã«ãŒãã«ã¯æ¬¡ã®ããã«åŒã³åºãããŸãã
shaderInstance.Dispatch(kernelIndex, 2, 2, 1);
ãããã®3æ¡ã®ã2ã2ã1ãã¯ã察å¿ããã«ãŒãã«ã®åã®è¡ã«æ¥ç¶ãããŠããŸãã
[numthreads(8,4,1)]
ãããã®2æ¡ã®æ°åã¯ãã¹ã¬ããã®æ°ãã€ãŸã䞊åã«ãŒãã«ã€ã³ã¹ã¿ã³ã¹ã®æ°ã決å®ããŸãã ããªãã¯ããããæããå¿
èŠããããŸãïŒ8 * 4 * 1 * 2 * 2 * 1 = 128ã¹ã¬ããã
ã¢ãã¬ã¹æå®ãããŒã¯å軞ã«ãããŸãã ãã®å Žåãx軞ã¯8 * 2 = 16åäœã«ãªããŸãã y軞ã§ã¯ã4 * 2 = 8åäœã§ãã ã€ãŸããã«ãŒãã«ã次ã®ããã«åŒã³åºãããå ŽåïŒ
ComputeShader.Dispatch(kernelIndex, X, Y, Z);
ã·ã§ãŒããŒåŽã§ã¯ãã¹ã¬ããã®æ°ã¯æ¬¡ã®ããã«èšå®ãããŸãã
[numthreads(x,y,z)]
次ã«ãïŒX * xïŒ*ïŒY * yïŒ*ïŒZ * zïŒã¹ã¬ãããäœæããŸã
ããšãã°ã256 x 256ãã¯ã¹ãã£ã®åãã¯ã»ã«ãåŠçããå¿
èŠããããåãã¯ã»ã«ãåå¥ã®ã¹ããªãŒã ã§åŠçããå¿
èŠããããšããŸãã ãããã£ãŠãã¹ã¬ããã®æ°ã¯æ¬¡ã®ããã«æ±ºå®ã§ããŸãã
Dispatch(kernelIndex, 16, 16, 1);
ãããŠã·ã§ãŒããŒåŽã§ïŒ
[numthreads(16,16,1)]
ã«ãŒãã«å
ã§ã¯ããã©ã¡ãŒã¿ãŒid.xã¯åããã©ã¡ãŒã¿ãŒid.yã®ç¯å²[0ã255]ã®å€ãåããŸãã
ãããã£ãŠã次ã®ãããªè¡ããããŸãã
texture[id.xy]=float4(1, 1, 1, 1);
ãã¯ã¹ãã£ã®65536ãã¯ã»ã«ã®ãããããçœè²ã«ããŸã
id.xyã¯uint2ãšåãã§ãïŒid.xãid.yïŒ
ã¹ã¬ããã®æ°ã«é¢é£ãããã®éšåã誰ã«ãäžæãªå Žåã¯ãåè¿°ã®ç°¡åãªããã¥ã¢ã«ãåç
§ããå®éã«ããããã¹ãŠã䜿çšããŠæãåçŽãªã·ã§ãŒããŒã䜿çšããŠãã³ãã«ãããã©ã¯ã¿ã«ãæç»ããæ¹æ³ã確èªããããšããå§ãããŸãã
æ€èšããŠããã¢ãã«ã®ã·ã§ãŒããŒããã¹ãã«ã¯ãããã€ãã®ã«ãŒãã«ãå«ãŸããŠããããããã®ã«ãŒãã«ã¯UpdateïŒïŒã¡ãœããã§CPUåŽã§èµ·åãããŸãã 次ã«ãåã«ãŒãã«ã®ããã¹ãã確èªããæåã«åã«ãŒãã«ã®æ©èœã«ã€ããŠç°¡åã«èª¬æããŸãã
calc-ç²åéã®çžäºäœçšã®æ¥ç·æ¹åãšæ³ç·æ¹åã®åãèšç®ãããŸãããã°ãã匵åã¯ç²åããããã®éã®ç·ã«æ²¿ã£ãŠæŒãããæ²ãåæ§ãã¯ç²åãé£æ¥ããç²åéã®ç·ã«åçŽã«æŒããŸãã èšç®ãããåã¯åç²åã«å¯ŸããŠä¿åãããŸã
velShare-ç²åã¯çžå¯Ÿé床ã亀æããŸãã æ¥ç·ããã³å®å
šã«å
æ¬ç-åå¥ã ãã«ã¹ããŒãã®äº€æããŸã ããã®ã«ããªãæ¥ç·ã匷調ããã®ã§ããïŒ æ¥ç·é床ã®äº€æã¯ãéåžžãããã¯ããã«åŒ·ããããé«ãä¿æ°ãæã€å¿
èŠããããããåºå¥ããå¿
èŠããããŸããã 次ã«ããªã2çªç®ã®ã±ãŒã¹ã§ãçŽç²ãªéåžžã®ã³ã³ããŒãã³ãã䜿çšããããã«ã¹ããŒãã䜿çšããã®ã§ããïŒ èšç®ãä¿åããŸãã é床ã®å€åã¯ãåã®ã«ãŒãã«ãšåæ§ã«ãåã®åœ¢ã§èšé²ãããŸãã
interactWithColliders-åãã€ã³ãã¯ã³ã©ã€ããŒãšçžäºäœçšããåãµã€ã¯ã«ã§æŽæ°ããããããã¡ãŒã«å«ãŸããæ
å ±
calcApply-以åã®ã«ãŒãã«ã§èšç®ãããåãé床ã«è¿œå ãããé床ãç¹ã®åº§æšãå€æŽããŸã
visInternodeLines-ãã€ã³ãéã§ãã©ã€ã³ã¯1024 x 1024ã®é·ãã®ç¹å¥ãªãããã¡ã«æç»ãããŸãïŒãŸã ãã¯ã¹ãã£äžã«ãããŸããïŒ
pixelsToTexture-ããã§ãåè¿°ã®å€ã¯ããµã€ãº[1024ã1024]ã®ãã¯ã¹ãã£äžã®ãã¯ã»ã«ã®è²ã«æ¢ã«å€æãããŠããŸã
clearPixels-äžéãããã¡ãŒïŒã©ã€ã³ãæç»ããïŒã®ãã¹ãŠã®å€ããªã»ãããããŸã
clearTexture-ãã¯ã¹ãã£ãã¯ãªã¢ãããŸã
oneThreadAction-ãã®ã«ãŒãã«ã¯åäžã®ã¹ã¬ããã§å®è¡ãããŸããããŠã¹ã§ãã©ãã°ããå Žæã«ãã¢ã·ã¹ãã å
šäœãã¹ã ãŒãºã«ç§»åããå¿
èŠããããŸãã ã·ã¹ãã ãçªç¶ã®åãããæ¥æ¿ã«ç§»åããªãããã«ããããã«ãæ»ããããå¿
èŠã§ãïŒèŠããŠããããã«ããã®ã¢ãã«ã§ã¯ãç²åéã®åã¯ç²åéã®è·é¢ã®2ä¹ã«æ¯äŸããŸãïŒã
CPUåŽ
次ã«ããããã®ã«ãŒãã«ãCPUã³ãŒãã®åŽé¢ããã©ã®ããã«èµ·åããããã瀺ããŸãã ããããæåã«ãèµ·åã®ããã«ã·ã§ãŒããŒãæºåããæ¹æ³ã
å€æ°ã宣èšããïŒ
ComputeShader _shader;
ã·ã§ãŒããŒããã¹ããå«ããã¡ã€ã«ãæå®ããŠåæåããŸãã
_shader = Resources.Load<ComputeShader>("shader");
GPUåŽã§äŸ¿å©ãªå®æ°ãèšå®ããŸã
// nodesPerHair nHairs _shader.SetInt("nNodsPerHair", nodesPerHair); _shader.SetInt("nHairs", nHairs);
ã¢ãã«åããããã€ã³ãã®ããŒã¿ãæ ŒçŽããé
åãšããããªã¡ã¢ãªãžã®ããŒã¿ã®èªã¿æžããå¯èœãªã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠãããã¡ã®å€æ°ã宣èšããŸã
hairNode[] hairNodesArray; ComputeBuffer hairNodesBuffer;
ãããã¡ãåæåããé
åããŒã¿ããããªã¡ã¢ãªã«æžã蟌ã¿ãŸã
// hairNodesArray hairNodesBuffer = new ComputeBuffer(hairNodesArray.Length, 4 * 8); hairNodesBuffer.SetData(hairNodesArray);
ã«ãŒãã«ããšã«ã䜿çšãããŠãããããã¡ãèšå®ããŠãã«ãŒãã«ããã®ãããã¡ã«å¯ŸããŠããŒã¿ãèªã¿æžãã§ããããã«ããŸã
kiCalc = _shader.FindKernel("calc"); _shader.SetBuffer(kiCalc, "hairNodesBuffer", hairNodesBuffer);
ãã¹ãŠã®ã·ã§ãŒããŒã«ãŒãã«ã«å¿
èŠãªãããã¡ãŒããã¹ãŠäœæããã³ã€ã³ã¹ããŒã«ãããããã«ãŒãã«ãå®è¡ã§ããŸãã
ãã¹ãŠã®ã«ãŒãã«ã¯ãUpdateïŒïŒããèµ·åãããŸãã ã°ã©ãã£ãã¯ãã€ãã©ã€ã³ã¯UpdateïŒïŒãšåæããŠãããããFixedUpdateïŒïŒããã¯éå§ããªãã§ãã ããïŒåŒ·ãé
ããŸãïŒã
ã«ãŒãã«ã¯æ¬¡ã®é åºã§èµ·åãããŸãïŒUpdateïŒïŒã§åŒã³åºããããdoShaderStuffãã¡ãœããã®ã³ãŒãå
šäœãåŒçšããŸãïŒã
void doShaderStuff(){ int i, nHairThreadGroups, nNodesThreadGroups; nHairThreadGroups = (nHairs - 1) / 16 + 1; nNodesThreadGroups = (nodesPerHair - 1) / 8 + 1; _shader.SetFloats("pivotDestination", pivotPosition); circleCollidersBuffer.SetData(circleCollidersArray); i = 0; while (i < 40) { _shader.Dispatch(kiVelShare, nHairThreadGroups, nNodesThreadGroups, 1); _shader.Dispatch(kiCalc, nHairThreadGroups, nNodesThreadGroups, 1); _shader.Dispatch(kiInteractionWithColliders, nHairThreadGroups, nNodesThreadGroups, 1); _shader.Dispatch(kiCalcApply, nHairThreadGroups, nNodesThreadGroups, 1); _shader.Dispatch(kiOneThreadAction, 1, 1, 1); i++; } circleCollidersBuffer.GetData(circleCollidersArray); _shader.Dispatch(kiVisInternodeLines, nHairThreadGroups, nNodesThreadGroups, 1); _shader.Dispatch(kiClearTexture, 32, 32, 1); _shader.Dispatch(kiPixelsToTexture, 32, 32, 1); _shader.Dispatch(kiClearPixels, 32, 32, 1); }
è€æ°ã®ã«ãŒãã«ãæŽæ°ããšã«40åå®è¡ãããããšãããã«ããããŸãã ãªãã§ïŒ ãã®ãããå°ããªæéã¹ãããã§ãã·ãã¥ã¬ãŒã·ã§ã³ã¯ãªã¢ã«ã¿ã€ã ã§è¿
éã«æ©èœããŸãã ãããŠããªãæéã¹ããããå°ããããå¿
èŠãããã®ã§ããããïŒ ãµã³ããªã³ã°ãšã©ãŒãæžãããããã€ãŸãã·ã¹ãã ã®å®å®æ§ã®ããã ãããŠãã©ã®ããã«ããããŠãªãäžå®å®ãçããã®ã§ããïŒ ã¹ãããã倧ããããã€ã³ãã«å€§ããªåãäœçšãããšãããã¹ãããã§ã¯ãã€ã³ããé£ã³å»ããæ»ãåã¯ããã«å€§ãããªãã次ã®ã¹ãããã§ã¯ãã€ã³ãã¯ããã«ä»ã®æ¹åã«é£ã³ãŸãã çµæïŒã·ã¹ãã ã¯è¡åãè¡ãããã¹ãŠã®ãã€ã³ããæ¯å¹
ãå¢ãããªããååŸã«é£è¡ããŸãã ãŸããå°ããªã¹ãããã§ã¯ããã¹ãŠã®åãšé床æ²ç·ãéåžžã«æ»ããã«ãªããŸããããã¯ãæéã¹ããããæžå°ããã«ã€ããŠèª€å·®ã倧å¹
ã«æžå°ããããã§ãã
ãã®ãããã·ã¹ãã ã¯1ã€ã®å€§ããªã¹ãããã§ã¯ãªããåãµã€ã¯ã«ã§40åã®å°ããªã¹ããããå®è¡ããŸããããã«ãããèšç®ã®ç²ŸåºŠãé«ããªããŸãã ãã®é«ã粟床ã«ãããå®å®æ§ãæãªãããšãªã倧ããªçžäºäœçšåã§äœæ¥ããããšãå¯èœã§ãã ãããŠã倧ããªåŒ·ãã¯ãã¢ãã«ã«ãããã ã匟åã®ãããã¹ã¿ãã¶ãã¶ãããŠããªãããšãçªç¶ã®åãããççºããããšããŠããããšããããŠèä¹
æ§ã®ãã髪ãå
æ°ã«å転ããããšãæå³ããŸãã
ãã¢ãã¢ãã«åãããã€ã³ãã®ããŒã¿ã¯ã1次å
é
åã®åœ¢åŒã§ãããªã¡ã¢ãªã«æ ŒçŽããããããã¡ã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠã¢ã¯ã»ã¹ããŸãã
1次å
ã®ãããã¡ãŒã䜿çšããããããããŒã¯æ¬¡ã®ããã«ã€ã³ããã¯ã¹ä»ããããŸããïŒx軞ïŒé«ªã®æ°*軞yïŒé«ªã®ãã€ã³ãã®æ°ïŒã ã€ãŸããã¹ããªãŒã ã®2次å
é
åãããããããããã¹ããªãŒã ã€ã³ããã¯ã¹ã«ãã£ãŠãã®ãã€ã³ããèªèããŸãã
èŠããŠããããã«ãã«ãŒãã«ãå®è¡ãããã¹ã¬ããã®æ°ã¯ãDispatchïŒïŒã¡ãœããã®ãã©ã¡ãŒã¿ãŒãšã·ã§ãŒããŒã³ãŒãã®[numthreadsïŒïŒ]ãã£ã¬ã¯ãã£ãã®ãã©ã¡ãŒã¿ãŒã®ç©ã«ãã£ãŠæ±ºãŸããŸãã
ãã®äŸã§ã¯ããã¢ãããã§åäœãããã¹ãŠã®ã«ãŒãã«ã®åã«[numthreadsïŒ16.8.1ïŒ]ãã£ã¬ã¯ãã£ãããããŸãã ãããã£ãŠãDispatchïŒïŒã¡ãœããã®ãã©ã¡ãŒã¿ãŒã¯ããã€ã³ãã®é
åå
šäœãåŠçããã®ã«å¿
èŠãªæ°ä»¥äžã®ã¹ã¬ããæ°ã補åãæäŸããããã«ããå¿
èŠããããŸãã ã³ãŒãã§ã¯ãDispatchïŒïŒã¡ãœããã®xããã³yãã©ã¡ãŒã¿ãŒãèšç®ããŸãã
nHairThreadGroups = (nHairs - 1) / 16 + 1; nNodesThreadGroups = (nodesPerHair - 1) / 8 + 1;
ãã©ã¡ãŒã¿ãŒ[numthreadsïŒïŒ]ãšDispatchïŒïŒã®é¢ä¿ã¯ãã°ã©ãã£ãã¯ã³ã³ãã¥ãŒã¿ãŒã®ã¢ãŒããã¯ãã£ã«ç±æ¥ããŸãã æåã¯ãã°ã«ãŒãå
ã®ã¹ã¬ããã®æ°ã§ãã 2çªç®ã¯ãã¹ã¬ããã°ã«ãŒãã®æ°ã§ãã ãããã®æ¯çã¯äœæ¥é床ã«åœ±é¿ããŸãã x軞ã«æ²¿ã£ãŠ1024ã¹ããªãŒã ãå¿
èŠãªå Žåã1024ã¹ããªãŒã ã®1ã°ã«ãŒãããã32ã¹ããªãŒã ã®32ã°ã«ãŒããäœæããããšããå§ãããŸãã ãªãã§ïŒ ãã®è³ªåã«çããã«ã¯ãGPUã®ã¢ãŒããã¯ãã£ã«ã€ããŠå€ãã®ããšã話ãå¿
èŠããããŸãããã®æ·±ããããããã¯ã«ã€ããŠã¯è§ŠããŸããã
GPUã®è©³çŽ°
ãã®ããã40åã®æŽæ°ã§ããã€ã³ãã®é床ã®å€åãèšç®ããé床ãšåº§æšãå€æŽããã«ãŒãã«ãé çªã«èµ·åããŸãã åã«ãŒãã«ã®ã³ãŒããèŠãŠã¿ãŸãããã ããã§ã¯ãã¹ãŠãéåžžã«ã·ã³ãã«ã§ãç¹å®ã®æ©èœãããã€ãåŠç¿ããã ãã§ãã
ã«ãŒãã«èšç®ã¯ããã€ã³ãã®é床ã®å€åãèšç®ããŸãã hairNodesBufferãããã¡ãŒå
ã®ãã€ã³ãã¯é çªã«é
眮ãããæåã¯æåã®é«ªã®æåã®ãã€ã³ãã次ã«2çªç®ã®é«ªãæåŸã«ç¶ããŸãã ãã®åŸãããã«2çªç®ã®é«ªã®æåã®ãã€ã³ããªã©ããã¹ãŠã®é«ªãéãããããã¡ãŒã®æåŸãŸã§ç¶ããŸãã ã«ãŒãã«ã«ã¯idãã©ã¡ãŒã¿ãŒããããid.xã¯ãã¢ã®çªå·ã瀺ããid.yã¯ãã€ã³ãçªå·ã瀺ããŠããããšãèŠããŠããŸãã 次ã«ãããŒã¿ãã€ã³ãã«ã¢ã¯ã»ã¹ããæ¹æ³ã瀺ããŸãã
int nodeIndex, nodeIndex2; hairNode node, node2; nodeIndex = id.x * nNodesPerHair + id.y; nodeIndex2 = nodeIndex + 1; node = hairNodesBuffer[nodeIndex]; node2 = hairNodesBuffer[nodeIndex2];
ããã§ãå€nNodesPerHairã¯ãã·ã§ãŒããŒãåæåãããšãã«CPUåŽã§èšå®ããå®æ°ã§ãã ãããã¡å
ã®ããŒã¿ãžã®ã¢ã¯ã»ã¹ã¯ãããŒã«ã«å€æ°ãžã®ã¢ã¯ã»ã¹ãããå€ãã®ã«ãŒãã«ãµã€ã¯ã«ãå¿
èŠãšããå¯èœæ§ãããããããããã¡ããã®ããŒã¿ã¯ããŒã«ã«å€æ°nodeããã³node2ã«ã³ããŒãããŸãã ã¢ã«ãŽãªãºã èªäœã¯æ¬¡ã®ãšããã§ããåãã€ã³ãã«ã€ããŠã髪ã®æåŸã§ã¯ãªãå Žåã次ã®ãã€ã³ããšã®éã«äœçšããåãèšç®ããŸãã ãã®åã«åºã¥ããŠãåãã€ã³ãã§é床ã®å€åãèšé²ããŸãã
䞊åèšç®ã®éèŠãªæ©èœã¯æ¬¡ã®ãšããã§ããåã¹ããªãŒã ã¯çŸåšãšæ¬¡ã®2ã€ã®ãã€ã³ããå€æŽããŸããã€ãŸãã2ã€ã®äžŠåã¹ããªãŒã ãåãã€ã³ããå€æŽããŸãã 䞊åã¹ã¬ããã«å
±éã®å€æ°ãžã®ä¿è·ãããŠããªãæžã蟌ã¿ã«ã¯ãããŒã¿æ倱ã䌎ããŸãã éåžžã®å¢åã䜿çšããå ŽåïŒ
variable += value;
ãã®å Žåãæåã®ã¹ããªãŒã ãå
ã®å€ãã³ããŒããŠ1ãè¿œå ããŸãããå€ãã¡ã¢ãªã»ã«ã«æžãæ»ãåã«ã2çªç®ã®ã¹ããªãŒã ãå
ã®å€ãååŸããŸãã 次ã«ãæåã®ã¹ã¬ããã¯1ãã€å¢å ããå€ãæžã蟌ã¿ãŸãã ãã®åŸã2çªç®ã®ã¹ã¬ããããã®ãŠããããè¿œå ããå¢å ããå€ãæžãæ»ããŸãã çµæïŒ2ã€ã®ã¹ã¬ããã1ã€ãã€è¿œå ãããŸããããå€æ°ã¯1ãŠãããã ãå¢å ããŸããã ãã®ç¶æ³ãåé¿ããã«ã¯ãå®å
šãªèšé²ã䜿çšããŠãã ããã HLSLã«ã¯ãæ±çšå€æ°ãå®å
šã«å€æŽããããã®ããã€ãã®æ©èœããããŸãã ããŒã¿ã倱ãããªãããšãããã³åã¹ããªãŒã ã®å¯äžãèæ
®ãããããšãä¿èšŒããŸãã
å°ããªåé¡ã¯ããããã®é¢æ°ãæŽæ°å€æ°ã§ã®ã¿æ©èœããããšã§ãã ãããŠãããããã€ã³ãã®ç¶æ
ãèšè¿°ããæ§é ã§ãintåã®dvxããã³dvyãã©ã¡ãŒã¿ã䜿çšããçç±ã§ãã ä¿è·ãããæ©èœã䜿çšããŠãããã«æžã蟌ãããšãã§ããããŒã¿ã倱ããªãããšã ãã ããäžžãã®ç²ŸåºŠã倱ãããªãããã«ããããã«ãäºåã«èŠå ã決å®ããŸããã 1ã€ã¯ãããŒããintã«å€æãããã1ã€ã¯éã«å€æããŸãã ãã®ãããint-valuesã®å
šç¯å²ã䜿çšãã粟床ã倱ããŸããïŒãã¡ãã倱ããŸãããç¡èŠã§ããŸãïŒã
ä¿è·ãããã¬ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
InterlockedAdd(hairNodesBuffer[nodeIndex].dvx, (int)(F_TO_I * (dv.x + 2 * dvFlex.x))); InterlockedAdd(hairNodesBuffer[nodeIndex].dvy, (int)(F_TO_I * (dv.y + 2 * dvFlex.y))); InterlockedAdd(hairNodesBuffer[nodeIndex2].dvx, (int)(F_TO_I * (-dv.x - dvFlex.x))); InterlockedAdd(hairNodesBuffer[nodeIndex2].dvy, (int)(F_TO_I * (-dv.y - dvFlex.y)));
ããã§ãF_TO_Iã¯intã§ã®floatã®æ圱ã«é¢ããåè¿°ã®ä¿æ°ã§ããdvã¯ãã¹ããªã³ã°æ¥ç¶ãä»ããæåã®ããŒãã£ã¯ã«ãžã®2çªç®ã®ããŒãã£ã¯ã«ã®åœ±é¿ã®åãã¯ãã«ã§ãã ãŸããdvFlexã¯æŽæµåã§ãã InterlockedAddïŒïŒã¯intããã³uintåã«å¯ŸããŠãªãŒããŒããŒããããããã©ã«ãã§floatã¯uintãšããŠè§£éãããããããïŒintïŒããè¿œå ããå¿
èŠããããŸãã
velShare Kernelã¯ä»¥åã®ãã®ãšäŒŒãŠããŸããã2ã€ã®é£æ¥ãããã€ã³ãã®dvxããã³dvyãã©ã¡ãŒã¿ãŒãå€æŽããŸãããåãèšç®ãã代ããã«ãçžå¯Ÿé床ã®æ¡æ£ãèšç®ãããŸãã
InteractionWithCollidersã«ãŒãã«ã§ã¯ããã€ã³ãã¯çžäºã«äœçšããŸãããããã§ã¯ãåãã€ã³ãã¯ãœãªãããããã¡ãŒã®ãã¹ãŠã®ã³ã©ã€ããŒãééããŸãïŒåæŽæ°ã§æŽæ°ãããŸãïŒã ã€ãŸããåã¹ã¬ããã¯1ã€ã®ããŒãã£ã¯ã«ã®ã¿ã«æžã蟌ããããåæèšé²ã®å±éºã¯ãªããããInterlockedAddïŒïŒã®ä»£ããã«ãããŒãã£ã¯ã«ã®é床ãçŽæ¥å€æŽã§ããŸãã ãããåæã«ãæã
ã®ã¢ãã«ã¯ããã€ã³ããã³ã©ã€ããŒã«éåéãäŒéããããšãæ瀺ããŠããŸãã ããã¯ã䞊åã¹ããªãŒã ãåãã³ã©ã€ããŒã®å¢ããåæã«å€æŽã§ããããšãæå³ããŸããã€ãŸããä¿è·ãããèšé²ãªãã·ã§ã³ã䜿çšããŸãã
ããã§ã®ã¿ç解ããå¿
èŠããããŸããintã«floatãæ圱ãããšãæŽæ°éšåãšå°æ°éšåã競åããŸãã 粟床ã¯ããŸããŸãªèŠæš¡ãšç«¶åããŸãã ç¹ã®çžäºäœçšã®å Žåãå€ã®ååãªåºãããèªããä¿æ°ãéžæããæ®ãã¯ç²ŸåºŠã®ããã«èš±å¯ãããŸããã ãã ãããã®ä¿æ°ã¯ãéåéãã³ã©ã€ããŒã«è»¢éããã®ã«ã¯é©ããŠããŸãããåæã«ãæ°çŸã®ãã€ã³ããäžæ¹åã«éåéãè¿œå ã§ãããããå€æ°ãå容ããããã«ç²ŸåºŠãç ç²ã«ããå¿
èŠããããŸãã ãããã£ãŠãä¿è·ãããã¬ã³ãŒãã§ã¯ãä¿æ°F_TO_Iã䜿çšãããããå°ããä¿æ°ã䜿çšããŸãã
ãã€ã³ãã®ãã¹ãŠã®çžäºäœçšãèšç®ãããåŸãcalcApplyã«ãŒãã«ã§é床ã«éåéãè¿œå ãã座æšã«é床ãè¿œå ããŸãã ããã«ããã®ã«ãŒãã«ã§ã¯ããã¢ã®åã«ãŒãïŒæåã®è¡ïŒã®ãã€ã³ãã¯ããã¢ã·ã¹ãã å
šäœã®çŸåšã®äœçœ®ãåºæºã«ããŠç¹å®ã®å Žæã«åºå®ãããŠããŸãã ãã®ã«ãŒãã«ã§ããéåã®å¯äžãåçŽé床æåã«è¿œå ãããŸãã ããã«ã空æ°ã«ã€ããŠããã¬ãŒãã³ã°ããå®çŸãããŸããã€ãŸããåãã€ã³ãã®é床ã®çµ¶å¯Ÿå€ã«1ãããããã«å°ããä¿æ°ãä¹ç®ãããŸãã
calcApplyã«ãŒãã«ã§ã¯ãé床ãdPosRateä¿æ°ãä»ããŠåº§æšã«åœ±é¿ããããšã«æ³šæããŠãã ããã ã·ãã¥ã¬ãŒã·ã§ã³ã¹ãããã®ãµã€ãºã決å®ããŸãã ãã®ä¿æ°ã¯CPUåŽã§èšå®ããããsimulationSpeedããšåŒã°ããå€æ°ã«æ ŒçŽãããŸãã ãã®ãã©ã¡ãŒã¿ã倧ããã»ã©ãã·ã¹ãã ã¯æéã®çµéãšãšãã«éãé²åããŸãã ãã ããèšç®ã®ç²ŸåºŠã¯äœããªããŸãã ç¹°ãè¿ããŸãããèšç®ã®ç²ŸåºŠã¯åã®å€§ãããå¶éããŸãã倧ããªåãšäœã粟床ã®å Žåã誀差ã®å€§ãããéåžžã«å€§ãããããã¢ãã«ã®åäœã決å®ãããããã§ãã ã·ãã¥ã¬ãŒã·ã§ã³é床ãããªãé
ãããŸãããããã«ãã粟床ãåäžããããããã倧ããªåããããããšãã§ããããçŸå®çãªã¢ãã«ã®åäœãæå³ããŸãã
åã®å€§ããã«ã¯ãé床ã«å¯Ÿãããã«ã¹ã®åœ±é¿ã«é¢é£ããä¿æ°ãdVelRateãããããŸãã ãã®ä¿æ°ã¯å€§ãããCPUåŽã§èšå®ããããstrengthOfForcesããšåŒã°ããŸãã
åè¿°ã®ãã¹ãŠã®ã«ãŒãã«ã§ãã¹ã¬ããã®æ°ã¯ãã€ã³ãã®æ°ã«çããã1ã€ã®ã¹ã¬ããã1ã€ã®ãã€ã³ããåŠçããããšãç¹°ãè¿ããŸãã ãããŠãããã¯è¯ãç¿æ
£ã§ãã ã¹ã¬ããã®æ°ã«ã¯äœãæ¯æããŸãããã¹ã¬ããã®æ°ã¯ããã€ã§ãããŸããŸããïŒã·ã§ãŒããŒã¢ãã«5.0ã§ã¯ãx軞ãšy軞ã«æ²¿ã£ãŠ1024以äžãz軞ã«æ²¿ã£ãŠ64以äžïŒã 䞊åã³ã³ãã¥ãŒãã£ã³ã°ã®äŒçµ±ã§ã¯ãã«ãŒãã䜿çšããŠè€æ°ã®ããŒã¿ãŠãããã«é¢é£ãã1ã€ã®ã¹ã¬ããã§åäžã®æäœãå®è¡ããããšãé¿ããæ¹ãããã§ãããã
CPUã³ãŒãåŽã®doShaderStuffïŒïŒã¡ãœããã«æ»ããŸãã ãã¢ã¢ãã«ãèšç®ãã40ã¹ãããã®ãµã€ã¯ã«ãå®äºããåŸãã³ã©ã€ããŒã®ããŒã¿ãèªã¿åããŸãã
circleCollidersBuffer.GetData(circleCollidersArray);
GPUåŽã§ã¯ããã¢åŽããã®ãã«ã¹ãã³ã©ã€ããŒã®ããŒã¿ãšãšãã«ãããã¡ãŒã«èšé²ãããCPUåŽã§ãããã䜿çšããŠåäœã«åãå ããããšãæãåºããŠãã ããã åäœã«ãããåã¯ãç©çãšåæããŠãããããFixedUpdateïŒïŒã¡ãœããã§é©çšãããããšã«æ³šæããŠãã ããã ãã®å ŽåãæŽæ°ïŒïŒã§ãã«ã¹ããŒã¿ãæŽæ°ãããŸãã ãããã£ãŠãããŸããŸãªèŠå ã®åœ±é¿äžã§ã1ã€ã®UpdateïŒïŒã§è€æ°ã®FixedUpdateïŒïŒããã³ãã®éãçºçããå¯èœæ§ããããŸãã ã€ãŸããã³ã©ã€ããŒã§ã®é«ªã®å¹æã«çµ¶å¯Ÿçãªç²ŸåºŠã¯ãªããããŒã¿ã®äžéšã¯åœ±é¿ãåããåã«äžæžãã§ããä»ã®ããŒã¿ã¯2å圱é¿ãåããå¯èœæ§ããããŸãã ãããé²ãããã®æ段ãè¬ããããšã¯ã§ããŸããããããã®æ段ã¯æ€èšäžã®ããã°ã©ã ã§ã¯è¡ãããŸããã
ãŸããGetDataïŒïŒã¡ãœãããã°ã©ãã£ãã¯ã¹ãã€ãã©ã€ã³ãäžæåæ¢ãããããé¡èãªé床äœäžãçºçããããšã«ã泚æããŠãã ããã æ®å¿µãªããããŠãããå
ã®ãã®ã¡ãœããã®éåæããŒãžã§ã³ã¯ãŸã å®è£
ãããŠããŸããããåã«ãããšã2018幎ã«ç»å Žããäºå®ã§ãã ãããŸã§ã®éãGPUããCPUã«ããŒã¿ãã³ããŒããå¿
èŠãããã¿ã¹ã¯ã®å Žåãããã°ã©ã ã®åäœã20ã30ïŒ
é
ããªãããšãç解ããå¿
èŠããããŸãã åæã«ãSetDataïŒïŒã¡ãœããã«ã¯ãã®ãããªå¹æã¯ãªããããã«åäœããŸãã
å¯èŠå
doShaderStuffïŒïŒã¡ãœããã§èµ·åãããæ®ãã®ã«ãŒãã«ã¯ããã¢ã·ã¹ãã ã®èŠèŠåã®ã¿ã«é¢é£ä»ããããŠããŸããèŠèŠåã«é¢é£ãããã¹ãŠãèæ
®ããŠãã ãããCPUåŽã§ã¯ãRenderTextureå€æ°ã宣èšããenableRandomWrite = trueãèšå®ããããšãå¿ããã«ãImage UIã³ã³ããŒãã³ãã®ãããªã¢ã«ã§mainTextureãšããŠäœ¿çšããŸãããããŠããã®ãã¯ã¹ãã£ã«æžã蟌ãå¿
èŠã®ããã«ãŒãã«ããšã«ãSetTextureïŒïŒã¡ãœãããåŒã³åºããŠãRenderTextureãªããžã§ã¯ããã·ã§ãŒããŒåŽã®å€æ°ã«ãã€ã³ãããŸãã RenderTexture renderTexture; renderTexture = new RenderTexture(1024, 1024, 32); renderTexture.enableRandomWrite = true; renderTexture.Create(); GameObject.Find("canvas/image").GetComponent<UnityEngine.UI.Image>().material.mainTexture = renderTexture; _shader.SetTexture(kiPixelsToTexture, "renderTexture", renderTexture);
ã·ã§ãŒããŒåŽã§ã¯ãRWTexture2Dåã®å€æ°ã宣èšããŸãããããã䜿çšããŠããã¯ã¹ãã£ãã¯ã»ã«ã®è²ãèšå®ããŸãã RWTexture2D<float4> renderTexture;
次ã«ãã«ã©ãŒãã¯ã»ã«ãæžã蟌ãåã«åŒã³åºããããã¯ã¹ãã£ã¯ãªãŒãã³ã°ã«ãŒãã«ãæ€èšããŸãã #pragma kernel clearTexture [numthreads(32,32,1)] void clearTexture (uint3 id : SV_DispatchThreadID){ renderTexture[id.xy] = float4(0, 0, 0, 0); }
ãã®ã«ãŒãã«ã¯æ¬¡ã®ããã«å®è¡ãããŸãã _shader.Dispatch(kiClearTexture, 32, 32, 1);
ã¹ããªãŒã ããšã®ãã¯ã»ã«ããšã«ã1024 x 1024ã®ã¹ããªãŒã ãããããšãããããŸããã©ã¡ãã䟿å©ãïŒid.xyãã©ã¡ãŒã¿ãŒã䜿çšããŠãã¯ã»ã«ãã¢ãã¬ã¹æå®ããã ãã§ãã髪ã¯ã©ã®ãããæ£ç¢ºã«æãããŠããŸããïŒé«ªãåéæã«ãªãããã«æ±ºããŸããã亀差ãããšãã«è²ããã飜åããŸããããã¯ãæ¢ã«èæ
®ãããŠããã«ãŒãã«ã®ããã«ããã¹ãŠã®ãã€ã³ããåæã«å®è¡ããããããåããã¯ã»ã«ã«2æ¬ã®ç·ãåæã«æç»ã§ãããããå®å
šãªèšé²ã䜿çšããå¿
èŠãããããšãæå³ããŸããã€ã³ãã®æ°ã«çããã¹ã¬ããã®æ°ã§ãæç»èªäœã¯ç°¡åã§ããåãã€ã³ããã次ã®ãã€ã³ããŸã§ç·ãåŒããŸããç·ã§ã¹ã€ãŒããããæ£æ¹åœ¢ãã¯ã»ã«ã®ã»ãããéžæããããã®ç¹å¥ãªã¢ã«ãŽãªãºã ããããŸãããç§ã¯åçŽãªæ¹æ³ãæ¡çšããããšã«ããŸãããç·ã¯ã2ç¹éã®ç·ã«æ²¿ã£ãŠå°ããªã¹ãããã§ç§»åããŠæç»ãããŸããå¢åã䜿çšãããããããã¯ã¹ãã£ã§ã¯ãªããããã¡ã«ã«ã©ãŒããŒã¿ãæžã蟌ã¿ãŸããäœããã®çç±ã§ãã¯ã¹ãã£ã¯èªã¿ã«ããã§ãããããã¯åœç¶ã®ããã§ããvisInternodeLinesã«ãŒãã«ããã¹ãŠã®ç·ãæç»ããåŸããã¯ã»ã«ããããã¡ãŒãããã¯ã¹ãã£ã«ã³ããŒããŸããè²ã¯äœ¿çšãããã°ã¬ãŒã®ã°ã©ããŒã·ã§ã³ã®ã¿ãæç»ããŸãã RWStructuredBufferãããã¡ãŒã®ä»£ããã«è²ãå¿
èŠãªå Žåã¯ãRWStructuredBufferã䜿çšãããã4ã€ã®è²ãã©ã¡ãŒã¿ãŒã1ã€ã®uintã«æžã蟌ãããšãã§ããŸãããšããã§ãRenderTextureã䜿çšãããã®ã¡ãœããã¯ãããŒã§ã¯æ©èœããããã©ãŒã©ã ã§ããªãããšãã質åã«å¯ŸããçããåŸãããšãã§ããŸããã§ãããèšç®ã·ã§ãŒããŒããã®ããŒã¿ãèŠèŠåããä»ã®æ¹æ³ããããŸãããç§ã¯ãŸã ããããç 究ããŠããªãããšãåçœããªããã°ãªããŸããããpixelsToTextureãã«ãŒãã«ããã¯ã¹ãã£ãå€æŽããåŸãé£ãã§ãã髪ã®ç»åãç»é¢ã«è¡šç€ºãããŸããGPUã³ã³ãã¥ãŒãã£ã³ã°ã«é¢ãããã¹ãŠã®ã³ãŒãã«ã€ããŠè©±ããŸãããããã¥ã¢ã«ã«ã¯å€ãã®æ
å ±ããããäžåºŠã«ææ¡ããã®ã¯é£ããå ŽåããããŸãããã®åéã§å®éšããäºå®ãããå Žåã¯ãå®è·µãéããŠç¥èãçµ±åããããã«ããŒãããç°¡åãªããã°ã©ã ãäœæããããšããå§ãããŸãã宿é¡ãšèããŠãã ãããå®è¡ã¯ç°¡åã§äŸ¿å©ã§ãã1ã€ã®ã«ãŒãã«ã倧ããªé
åã®ãã¹ãŠã®æ°å€ãäºä¹ããã·ã§ãŒããŒãäœæããŸããCPUåŽã§ãé
åãæºåãããããã·ã§ãŒããŒãããã¡ãŒã«æžã蟌ã¿ãã«ãŒãã«ãèµ·åããŠããããããªã¡ã¢ãªããæ
å ±ãååŸããæ°å€ã2ä¹ããŠãããã©ããã確èªããŸãã