
ãã¬ãŒã·ã§ã³ã¯ãäžã®åçã®ãããªã·ãŒã³ãçæããå°ããªãã¢ã®äŸã§è¡ãããŸãã CPUã§ããŒã¿ãæºåããŠããããã©ã°ã¡ã³ãã·ã§ãŒããŒã®åºåã«è²ã®å€ãæžã蟌ããŸã§ããšããµã€ãã£ã³ã°ãªæ ãããŸãã
ç®æšãšæ段
ãã¢ãäœæãããšãã次ã®ç®æšãèšå®ããŸããã
- ãããªã¡ã¢ãªã«ä¿åãããããŒã¿ã®éãæå°éã«ããŸãã ãã®çµæïŒ
- å©çšå¯èœãªãã¹ãŠã®ãã€ãã©ã€ã³ã¹ããŒãžã䜿çšããŠãå¯èœãªéãGPUãå»æ£ããŸãã
- ããã€ãã®ã·ãŒã³èšå®ãã«ã¹ã¿ãã€ãºå¯èœã«ããŸãã
- ãžãªã¡ããªãšã·ã§ãŒããŒã®äœæã«çŠç¹ãåœãŠãæ®ãã®ã³ã³ããŒãã³ãã«æå°éã®åŽåãè²»ãããŸãã ãããã£ãŠãæãããç¥ãããŠããã€ã³ã¹ãã«ã¡ã³ããŒã·ã§ã³ãC ++ 11ïŒgccïŒãQt5 + qmakeãGLSLã䜿çšãããŸããã
- å¯èœã§ããã°ãã¢ã»ã³ããªãç°¡çŽ åããããŸããŸãªãã©ãããã©ãŒã ã§çµæã®ãã¢ãèµ·åããŸãã
ãã®ãªã¹ãã«åºã¥ããŠãããã€ãã®ãã€ã³ãã®ç 究ãç ç²ã«ããªããã°ãªããŸããã§ããã
- ã¡ã€ã³ã«ãŒãã¯åºæ¬çã«äœæãããŸãã ãããã£ãŠãã¢ãã¡ãŒã·ã§ã³ã®é床ãšã«ã¡ã©ã®åãã¯ãã¬ãŒã ã¬ãŒãã«äŸåããããã空éå ã®ã«ã¡ã©ã®äœçœ®ã«äŸåããŸãã
- ã«ã¡ã©ã®åäžã®ã¯ã©ã¹ã§ã¯ããã®ãã¹ãŠãå€æŽããããã«ã座æšãæ¹åãæ圱ãããã³æ©èœãé¢äžããŸãã ãã®ãã©ãŒã ã§ã¯ãæžã蟌ã¿ã«ããã»ã©æéã¯ãããããã«ã¡ã©ãã©ã¡ãŒã¿ãŒãã·ã§ãŒããŒã«ããªãæé©ã«è»¢éããããšãã§ããŸããã
- ã·ã§ãŒããŒã¯ã©ã¹ã¯ã察å¿ããQt5ã¯ã©ã¹ã®ããªãèãã©ãããŒã®åœ¢ã§äœæãããŸãã ããŸããŸãªæ®µéã§å ±éããã³ãŒãã®æçã¯ãäžç·ã«æ¥çãããã³ã³ãã€ã©ãªããã£ãã€ã¶ãŒã«æž¡ãããŸããã³ã³ãã€ã©ãªããã£ãã€ã¶ãŒã¯ãæªäœ¿çšã®ã³ãŒããšã°ããŒãã«å€æ°ãç Žæ£ããŸãã
- ããã°ã©ã ã¯åäžã®ã·ã§ãŒããŒã䜿çšããããããnewfangledã UBOãªãã§ããŒã¿è»¢éãè¡ãããŸãã ãã®å Žåãã³ãŒããè€éåããŠãããã©ãŒãã³ã¹ã¯åäžããŸããã
- 1ç§ãããã®ãã¬ãŒã ã«ãŠã³ã¿ãŒã¯ã OpenGLã¯ãšãªã«åºã¥ããŠããŸã ã ãããã£ãŠããå®éã®ãFPSã¯è¡šç€ºãããŸããããQtã«ãã£ãŠçºçãããªãŒããŒããããèæ ®ã«å ¥ããªãããããã«é倧è©äŸ¡ãããçæ³çãªã€ã³ãžã±ãŒã¿ãŒã衚瀺ãããŸãã
- ãã®ãã¢ãäœæããç®çã¯ã¯ãŒã«ãªç §æã§ã¯ãªãã£ããããã·ã§ãŒããŒã«1ã€ã®å æºã䜿çšããPhongç §æã®åçŽãªå®è£ ã䜿çšãããŸãã
- ã·ã§ãŒããŒã§ã®ãã€ãºã®å®è£ ã¯ããµãŒãããŒãã£ã®èè ããåãããŸããã
ã¹ããŒãªãŒã®éçšã§ãã¢ã®ã³ãŒãå šäœãã¬ãã¥ãŒããæ©äŒãèªè ã«æäŸããããã«ãããã«ãªããžããªãžã®ãªã³ã¯ãæäŸããŸãã
ãžãªã¡ããªçæã®ç°¡åãªæŠèŠ
ãããã®ã»ãããæç»ããŸã ãåãããã«ã¯åäžã®é ç¹ãå«ãŸããŸãã åé ç¹ã«ã¯ã1ã€ã®4ã³ã³ããŒãã³ãå±æ§ãå«ãŸããŸãã ããŒã¿ã®ãã®æå°éã®éšåãã·ãŒããšããŠäœ¿çšããŠããã®ãããªåãããïŒã€ãŸãã1ãã€ã³ãïŒã®å¯åã¹ãã ã®ããã·ã¥å šäœããæé·ããããŸãã ããã«ããŠãŒã¶ãŒå®çŸ©ã®ãã©ã¡ãŒã¿ãŒã䜿çšããŠããã¹ãŠã®ããã·ã¥ã颚ã«ãããããšãã§ããŸãã ããã·ã¥çæäœæ¥ã®ã»ãšãã©ã¯ã ããã»ã¬ãŒã·ã§ã³è©äŸ¡ã·ã§ãŒããŒããã³ãžãªã¡ããªã·ã§ãŒããŒã§è¡ãããŸãã ãã®ãããããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒã§ã¯ãæªæãšé¢šã«ãããã¹ãŠã®å€åœ¢ã§ããã·ã¥ã¹ã±ã«ãã³ãçæããããžãªã¡ããªã·ã§ãŒããŒã§ã¯ãããªãŽã³ã®ãèãããã®ã¹ã±ã«ãã³äžã«åŒã䌞ã°ãããŸãã ãã©ã°ã¡ã³ãã·ã§ãŒããŒã¯ãéåžžã©ãããç §æãèšç®ãããããã€å³ã«åºã¥ããŠæç¶ãçã«çæããããã¯ã¹ãã£ãé©çšããŸãã
ããã§ã¯å§ããŸãããïŒ
CPU
ã¢ãã¿ãŒã®ãã¯ã»ã«ãè²ä»ãããããŒã¿ã®æ¹æ³ã¯ãCPUã§ã®æºåããå§ãŸããŸãã åè¿°ã®ããã«ãã·ãŒã³ã®åãã¢ãã«ãã¯æåã¯1ã€ã®é ç¹ã§æ§æãããŠããŸãã ãã®é ç¹ã4次å ã«ããŸããæåã®3ã€ã®ã³ã³ããŒãã³ãã¯ç©ºéå ã®é ç¹ã®äœçœ®ã§ããã4çªç®ã®ã³ã³ããŒãã³ãã¯ããã·ã¥å ã®ã¹ãã ã®æ°ã§ãã ãããã£ãŠãããã·ã¥ã¯ãèã®æ°ãäºãã«ç°ãªãããšãã§ããŸãã æéãµã€ãºã®æ£æ¹æ Œåã®ããŒããã座æšã®çæãéå§ããäžããããééããã©ã³ãã ãªå€ã§å座æšãæåããŸãã
const int numNodes = 14; // . const GLfloat gridStep = 3.0f; // . // : const GLfloat xDispAmp = 5.0f; const GLfloat zDispAmp = 5.0f; const GLfloat yDispAmp = 0.3f; // . numClusters = numNodes * numNodes; // . GLfloat *vertices = new GLfloat[numClusters * 4]; // . std::random_device rd; std::mt19937 mt(rd()); std::uniform_real_distribution<GLfloat> xDisp(-xDispAmp, xDispAmp); std::uniform_real_distribution<GLfloat> yDisp(-yDispAmp, yDispAmp); std::uniform_real_distribution<GLfloat> zDisp(-zDispAmp, zDispAmp); std::uniform_int_distribution<GLint> numStems(12, 64); // . for(int i = 0; i < numNodes; ++i) { for(int j = 0; j < numNodes; ++j) { const int idx = (i * numNodes + j) * 4; vertices[idx] = (i - numNodes / 2) * gridStep + xDisp(mt); vertices[idx + 1] = yDisp(mt); vertices[idx + 2] = (j - numNodes / 2) * gridStep + zDisp(mt); vertices[idx + 3] = numStems(mt); } }
çæãããããŒã¿ããããªã¡ã¢ãªã«éä¿¡ããŸãã
GLuint vao; // https://www.opengl.org/wiki/Vertex_Specification#Vertex_Array_Object GLuint posVbo; // https://www.opengl.org/wiki/Vertex_Specification#Vertex_Buffer_Object glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &posVbo); glEnableVertexAttribArray(ATTRIBINDEX_VERTEX); glBindBuffer(GL_ARRAY_BUFFER, posVbo); glVertexAttribPointer(ATTRIBINDEX_VERTEX, 4, GL_FLOAT, GL_FALSE, 0, 0); glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * numClusters * 4, vertices, GL_STATIC_DRAW); glFinish(); delete[] vertices;
ããã§ãçæãããèããèçå šäœãã¬ã³ããªã³ã°ããæ¹æ³ã¯éåžžã«ç°¡æœã«èŠããŸãã
void ProceduralGrass::draw() { glBindVertexArray(vao); glPatchParameteri(GL_PATCH_VERTICES, 1); glDrawArrays(GL_PATCHES, 0, numClusters); glBindVertexArray(0); }
ã·ã§ãŒããŒã§ã¯ããžãªã¡ããªã«å ããŠãåçã«ååžããä¹±æ°ãå¿ èŠã§ãã éé[0;ã§æ°å€ãååŸããã®ãæé©ã§ãã 1]ãããã³ç¹å®ã®åå Žæã®GPUã§ãããããå¿ èŠãªééã«ããŸãã ãããã1次å ãã¯ã¹ãã£ãŒã®åœ¢ã§ãããªã¡ã¢ãªã«é ä¿¡ããŸãããã®ãã¯ã¹ãã£ãŒã«ã¯ãæãè¿ãå€ããã£ã«ã¿ãŒãšããŠèšå®ãããŸãã 2次å ã®å Žåããã®ãããªãã£ã«ã¿ãªã³ã°ã¯åæ§ã®çµæã«ã€ãªããããšãæãåºãããŠãã ããã

åºæ
çæããã³ãã¯ã¹ãã£èšå®ã³ãŒãïŒ
const GLuint randTexSize = 256; GLfloat randTexData[randTexSize]; std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution<float> dis(0.0f, 1.0f); std::generate(randTexData, randTexData + randTexSize, [&](){return dis(gen);}); // Create and tune random texture. glGenTextures(1, &randTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_1D, randTexture); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0); glTexImage1D(GL_TEXTURE_1D, 0, GL_R16F, randTexSize, 0, GL_RED, GL_FLOAT, randTexData); glUniform1i(glGetUniformLocation(grassShader.programId(), "urandom01"), 0);
é ç¹ã·ã§ãŒããŒ
ååãšããŠãããã»ã¬ãŒã·ã§ã³ã䜿çšããå Žåãé ç¹ã·ã§ãŒããŒã¯éåžžã«é 延ããŠããããšãå€æããŸããããã¯ããã€ãã©ã€ã³ãããããéå§ãããŸã ãžãªã¡ããªãååšããªãããã§ãã ãã®å Žåãé ç¹ã·ã§ãŒããŒã¯ç°¡åã§ãã ãã®äžã§ãåã«å ¥å£ããåºå£ã«ããã«ãã€ã³ããéä¿¡ããŸãïŒ
layout(location=0) in vec4 position; void main(void) { gl_Position = position; }
ãã»ã¬ãŒã·ã§ã³
ããŒããŠã§ã¢ããã»ã¬ãŒã·ã§ã³ã¯ãGPUã䜿çšããŠããªãŽã³ã¢ãã«ã®ç²åºŠãé«ããããã®åŒ·åãªææ³ã§ãã äžå€®åŠçè£ çœ®ã§å®è¡ãããããªãŽã³ãäžè§åœ¢ã«åå²ããã¢ã«ãŽãªãºã ãšæ··åããªãã§ãã ããã ããŒããŠã§ã¢ããã»ã¬ãŒã·ã§ã³ã¯ãã°ã©ãã£ãã¯ãã€ãã©ã€ã³ã®3ã€ã®ã¹ããŒãžã§æ§æããããã®ãã¡ã®2ã€ãããã°ã©ã ã§ããŸãïŒé»è²ã§åŒ·èª¿è¡šç€ºïŒã

ã·ã§ãŒããŒãšãã®å ¥å/åºåã®è©³çŽ°ã«ã€ããŠã¯ã以äžã§èª¬æããŸãã ããã§ã¯ãä»»æã®æ°ã®é ç¹ã§æ§æãããããããããã»ã¬ãŒã·ã§ã³å ¥åã«é©çšãããŸããããã¯ãåglDraw *åŒã³åºãã«å¯ŸããŠåºå®ãããå°ãªããšã32ã«å¶éãããŸãããããã®é ç¹ã®å±æ§ã¯ãããªããæãããã«ã ããã¯ãå€ãé ç¹ã·ã§ãŒããŒãšæ¯èŒããŠæ¬åœã«çŽ æŽãããæ©äŒãæäŸããŸãã
ããã°ã©ã å¯èœãªããã»ã¬ãŒã·ã§ã³ã®äœæ¥ã¢ãã«ã¯ãä»ã®ã·ã§ãŒããŒãšã¯å€§ããç°ãªããé ç¹ã·ã§ãŒããŒãšå¹ŸäœåŠçã·ã§ãŒããŒã®äœ¿çšçµéšãããå Žåã§ããæåã«ããã«æ £ãããšæžæãå¯èœæ§ããããŸãã
ããã»ã¬ãŒã·ã§ã³å¶åŸ¡ã·ã§ãŒããŒ
äžè¬çãªå Žåãé ç¹ã·ã§ãŒããŒãåå¥ã«ééããå ¥åãããã®ãã¹ãŠã®é ç¹ã¯ãããã»ã¬ãŒã·ã§ã³ã³ã³ãããŒã«ã·ã§ãŒããŒã§äœ¿çšã§ããŸãã ãã®å ¥åã¯ãgl_PatchVerticesInãââããã®é ç¹ã®æ°ãgl_PrimitiveIDãããã®ã·ãªã¢ã«çªå·ãããã³åºåé ç¹ã®ã·ãªã¢ã«çªå·gl_InvocationIDãåãåããŸããããã«ã€ããŠã¯åŸã§èª¬æããŸãã gl_PrimitiveIDãããã®ã·ãŒã±ã³ã¹çªå·ã¯ãåäžã®glDraw *åŒã³åºãã®äžéšãšããŠã«ãŠã³ããããŸãã é ç¹ããŒã¿èªäœã¯ã次ã®ããã«å®£èšãããgl_inæ§é äœã®é åãä»ããŠã¢ã¯ã»ã¹ã§ããŸãã
in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[gl_MaxPatchVertices];
ãã®é åã«ã¯ã0ããgl_PatchVerticesIn-1ãŸã§ã€ã³ããã¯ã¹ãä»ããããŸãããã®å®£èšã§æãéèŠãªã®ã¯ãé ç¹ã·ã§ãŒããŒã®åºåããã®ããŒã¿ãå«ãgl_Positionãã£ãŒã«ãã§ãã åºåãããã®é ç¹ã®æ°ã¯ãã·ã§ãŒããŒã®ã³ãŒãã§ã°ããŒãã«å®£èšã«ãã£ãŠèšå®ãããŸãã
layout (vertices = 1) out; //
å ¥åãããã®é ç¹ã®æ°ãšäžèŽããå¿ èŠã¯ãããŸããã ã·ã§ãŒããŒåŒã³åºãã®æ°ã¯ãåºåé ç¹ã®æ°ã«çãããªããŸãã ååŒã³åºãã§ãã·ã§ãŒããŒã¯ãããã®ãã¹ãŠã®å ¥åé ç¹ã«ã¢ã¯ã»ã¹ã§ããŸãããgl_outåºåé åã®gl_InvocationIDã€ã³ããã¯ã¹ã«ã®ã¿æžã蟌ãããšãã§ããŸãã
out gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_out[];
次ã«ãããèå³æ·±ãäºå®ã«ç§»ããŸãããã ã·ã§ãŒããŒã¯gl_InvocationIDã€ã³ããã¯ã¹ã§ã®ã¿æžã蟌ãããšãã§ããŸãããã©ã®ã€ã³ããã¯ã¹ã§ãåºåé åãèªã¿åãããšãã§ããŸãïŒ ã·ã§ãŒããŒã®äœæ¥ã¯éåžžã«äžŠååãããŠããããããã®åŒã³åºãã®é åºã¯æ±ºå®è«çã§ã¯ãªãããšãèŠããŠããŸãã ããã«ãããã·ã§ãŒããŒã«ããããŒã¿ã®å ±æã«å¶éã課ãããŸãããSIMD䞊ååŠçãå¯èœã«ãªããã³ã³ãã€ã©ãŒã¯æãå³ããæé©åã䜿çšããããã«ãªããŸãã ãããã®ã«ãŒã«ã®éåãé²ãããã«ãããã»ã¬ãŒã·ã§ã³ã³ã³ãããŒã«ã·ã§ãŒããŒã§ããªã¢åæã䜿çšã§ããŸãã çµã¿èŸŒã¿ã®barrierïŒïŒé¢æ°ãåŒã³åºããšããã¹ãŠã®ãããã·ã§ãŒããŒããã®é¢æ°ãåŒã³åºããŸã§å®è¡ããããã¯ãããŸãã ãã®é¢æ°ã®åŒã³åºãã«ã¯é倧ãªå¶éã課ããããŸããmain以å€ã®é¢æ°ããåŒã³åºãããšã¯ã§ããŸããããããŒå¶åŸ¡æ§é ïŒforãwhileãswitchãªã©ïŒã§åŒã³åºãããšã¯ã§ãããæ»ãåŸã«åŒã³åºãããšã¯ã§ããŸããã
æåŸã«ããã€ãã©ã€ã³ã®ãã®æ®µéã§æãèå³æ·±ãã®ã¯ãé ç¹ã®åºåãäž»ãªãã®ã§ã¯ãªãããšã§ãã gl_outã«èšé²ããã座æšããããªãŽã³ã¯åéãããŸããã ããã»ã¬ãŒã·ã§ã³ã³ã³ãããŒã«ã·ã§ãŒããŒã®äž»ãªè£œåã¯ã次ã®åºåé åãžã®æžã蟌ã¿ã§ãã
patch out float gl_TessLevelOuter[4]; patch out float gl_TessLevelInner[2];
ãããã®é åã¯ãããããæœè±¡ãããã®é ç¹ã®æ°ãå¶åŸ¡ããããããã®æ®µéã¯ããã»ã¬ãŒã·ã§ã³å¶åŸ¡ãšåŒã°ããŸãã æœè±¡ãããã¯ãããã»ã¬ãŒã·ã§ã³ããªããã£ãçæ段éã§çæããã2次å ã®å¹ŸäœåŠç圢ç¶ã®ãã€ã³ãã®ã»ããã§ãã æœè±¡ãããã«ã¯ãäžè§åœ¢ãæ£æ¹åœ¢ã茪éã®3ã€ã®åœ¢åŒããããŸãã åæã«ãåã¿ã€ãã®æœè±¡ãããã«ã€ããŠãã·ã§ãŒããŒã¯å¿ èŠãªã€ã³ããã¯ã¹gl_TessLevelOuterãšgl_TessLevelInnerã®ã¿ãå ¥åããå¿ èŠãããããããã®é åã®æ®ãã®ã€ã³ããã¯ã¹ã¯ç¡èŠãããŸãã çæããããããã«ã¯ã幟äœåŠçå³åœ¢ã®é ç¹ã ãã§ãªããå¢çç·äžããã³å³åœ¢å éšã®ç¹ã®åº§æšãå«ãŸããŸãã ããšãã°ãgl_TessLevelOuterãšgl_TessLevelInnerã®ããã€ãã®å€ãæã€æ£æ¹åœ¢ã¯ããã®çš®ã®äžè§åœ¢ãã圢æãããŸãã

æ£æ¹åœ¢ã®å·Šäžé ã®åº§æšã¯åžžã«[0; 0]ãå³äž-[1; 1]ãããã³ä»ã®ãã¹ãŠã®ãã€ã³ãã«ã¯ã0ã1ã®å€ãæã€å¯Ÿå¿ãã座æšããããŸãã
茪éã¯åºæ¬çã«æ£æ¹åœ¢ã§ãããäžè§åœ¢ã§ã¯ãªãé·æ¹åœ¢ã«åå²ãããŸãã çé«ç·äžã®ç¹ã®åº§æšã®å€ãã0ã1ã®ééã«å±ããŸãã
ããããäžè§åœ¢ã®å åŽã®åº§æšã¯æ ¹æ¬çã«ç°ãªããŸãã2次å ã®äžè§åœ¢ã§ã¯ã3æåã®éå¿åº§æšã䜿çšãããŸãã ããã«ããããã®å€ã0ãã1ã®ééã«ãããäžè§åœ¢ã¯æ£äžè§åœ¢ã§ãã
æœè±¡ãããã®ç¹å®ã®ã¿ã€ãã®ããŒãã£ã·ã§ã³ïŒå®éã«ã¯ãæ¬æ¥ã®æå³ã§ã¯ããã»ã¬ãŒã·ã§ã³ãšåŒã°ããŸãïŒã¯ãgl_TessLevelOuterãšgl_TessLevelInnerã«å€§ããäŸåããŠããŸãã ããã§è©³ãã説æããããšããInnerãOuterãšã©ã®ããã«ç°ãªããã«ã€ããŠãåæããŸããã ãããã¯ãã¹ãŠãOpenGLããã¥ã¢ã«ã®å¯Ÿå¿ããã»ã¯ã·ã§ã³ã§è©³çŽ°ã«èª¬æãããŠããŸãã
ããŠãæ€ç©ã«æ»ããŸãããã ã°ã©ãã£ãã¯ãã€ãã©ã€ã³ã®ãã®æ®µéã§ã¯ãæ¢åã®åäžãã€ã³ãã«å¯ŸããŠæå³ã®ããå€æãå®è¡ããããšã¯ãŸã ã§ããªããããå ¥åã·ã§ãŒããŒãå€æŽããã«ãã®ã·ã§ãŒããŒã®åºåã«æž¡ããŸãã
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
ãžãªã¡ããªãçæããã«ã¯ãé·æ¹åœ¢ã®æ Œåãã€ãŸããã¢ã€ãœã©ã€ã³ãã¿ã€ãã®æœè±¡çãªãããã䜿çšããŸãã 茪éã®çæã¯ãgl_TessLevelOuter [0] -y座æšã«æ²¿ã£ããã€ã³ãã®æ°ãããã³gl_TessLevelOuter [1]-xã«æ²¿ã£ããã€ã³ãã®æ°ã®2ã€ã®å€æ°ã®ã¿ã«ãã£ãŠå¶åŸ¡ãããŸãã ãã®ããã°ã©ã ã§ã¯ã yã«æ²¿ã£ããµã€ã¯ã«ãããã·ã¥ã®èãéãæããåèã«å¯ŸããŠxã«æ²¿ã£ããµã€ã¯ã«ãèã«æ²¿ã£ãŠèµ°ããŸãã ãããã£ãŠã察å¿ããåºåã«èšé²ããã¹ãã ã®æ°ïŒå ¥åãã€ã³ãã®4çªç®ã®åº§æšïŒïŒ
gl_TessLevelOuter[0] = gl_in[gl_InvocationID].gl_Position.w;
ã¹ãã ã«æ²¿ã£ããã€ã³ãã®æ°ã¯ãã¹ãã ãæ§æãããã»ã°ã¡ã³ãã®æ°ãã€ãŸããã®è©³çŽ°ã決å®ããŸãã ãªãœãŒã¹ãç¡é§ã«ããªãããã«ã詳现ã¬ãã«ã¯ã«ã¡ã©ãšããã·ã¥éã®è·é¢ã«äŸåããŸãã
uniform vec3 eyePosition; // . int lod() { // : float dist = distance(gl_in[gl_InvocationID].gl_Position.xyz, eyePosition); // : if(dist < 10.0f) { return 48; } if(dist < 20.0f) { return 24; } if(dist < 80.0f) { return 12; } if(dist < 800.0f) { return 6; } return 4; }
CPUåŽã§ã¯ãåglDraw *åŒã³åºãã®åã«åçš®ã®å€æ°ãå ¥åãããŸãã
grassShader.setUniformValue("eyePosition", camera.getPosition()); grassShader.setUniformValue("lookDirection", camera.getLookDirection());
ãããã®æåã¯ç©ºéå ã®ã«ã¡ã©ã®åº§æšã§ããã2çªç®ã¯èŠç·ã®æ¹åã§ãã ã«ã¡ã©ã®äœçœ®ããã¥ãŒã®æ¹åãããã³ããã·ã¥ã®åº§æšãç¥ããšããã®ããã·ã¥ãã«ã¡ã©ã®åŸãã«ãããã©ããã確èªã§ããŸãã

ããã·ã¥ãæ£é¢ã«ããå Žåãã«ã¡ã©ããåæ¹ãžã®æ¹åãšã«ã¡ã©ããããã·ã¥ãžã®æ¹åãšã®éã®è§åºŠã¯éããªããããã§ãªãå Žåã¯éè§ã«ãªããŸãã ãããã£ãŠãæåã®å Žåãå³ã«ç€ºãããŠãããã¯ãã«ã®ã¹ã«ã©ãŒç©ã¯ãŒããã倧ããã2çªç®ã®å Žåã¯å°ãããªããŸãã ã¹ã«ã©ãŒç©ãèšç®ããã¹ãããé¢æ°ããŒãã®ã¹ãããã䜿çšããŠãããã·ã¥ãåŸãã«ããå Žåã¯ãŒãã§ãããã³ãã«ããå Žåã¯1ã§ããå€æ°ãååŸããŸãã
float halfspaceCull = step(dot(eyePosition - gl_in[gl_InvocationID].gl_Position.xyz, lookDirection), 0);
æåŸã«ãå°æ¥ã®ããã·ã¥ã®èã®ãã€ã³ãæ°ãèšé²ã§ããŸãã
gl_TessLevelOuter[1] = lod() * halfspaceCull;
ããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒ
çšèªã«é¢ãã泚æïŒè±èªã®åæã§ã¯ããã®ã·ã§ãŒããŒã¯Tesselationè©äŸ¡ã·ã§ãŒããŒãšåŒã°ããŸãã ãã·ã¢ã®ã€ã³ã¿ãŒãããã§ã¯ããããã»ã¬ãŒã·ã§ã³è©äŸ¡ã·ã§ãŒããŒããŸãã¯ãããã»ã¬ãŒã·ã§ã³èšç®ã·ã§ãŒããŒãã®ãããªæåéãã®ç¿»èš³ãèŠã€ããããšãã§ããŸãã ç§ã®æèŠã§ã¯ããããã¯äžèªç¶ã«èŠãããã®ã·ã§ãŒããŒã®æ¬è³ªãåæ ããŠããŸããã ãããã£ãŠãããã§ã¯ãããã»ã¬ãŒã·ã§ã³å¶åŸ¡ã·ã§ãŒããŒããã£ãåã®æ®µéãšã¯ç°ãªããããã»ã¬ãŒã·ã§ã³è©äŸ¡ã·ã§ãŒããŒã¯åã«ããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒãšåŒã°ããŸãã
ããã»ã¬ãŒã·ã§ã³ã¯ãããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒãã·ã§ãŒããŒããã°ã©ã ã«è¿œå ãããŠããå Žåã«ã®ã¿æå¹ã«ãªããŸãã åæã«ãããã»ã¬ãŒã·ã§ã³ã³ã³ãããŒã«ã·ã§ãŒããŒã¯å¿ é ã§ã¯ãããŸããããã®ååšã¯ãå ¥åããããå€æŽããã«åºåã«é©çšããããšãšåçã§ãã gl_TessLevel *é åã®å€ã¯ããã©ã¡ãŒã¿GL_PATCH_DEFAULT_OUTER_LEVELãŸãã¯GL_PATCH_DEFAULT_INNER_LEVELãæå®ããŠglPatchParameterfvãåŒã³åºãããšã«ãããCPUåŽã§èšå®ã§ããŸãã ãã®å Žåãããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒã®ãã¹ãŠã®æœè±¡ãããã¯åãã«ãªããŸãã ããã°ã©ã ã«ããã»ã¬ãŒã·ã§ã³ã³ã³ãããŒã«ã·ã§ãŒããŒã®ã¿ãè¿œå ããŠãæå³ããªããã·ã§ãŒããŒã¬ã€ã¢ãŠããšã©ãŒãçºçããŸãã æœè±¡ãããã®åœ¢åŒã¯ããã®ãã©ã¡ãŒã¿ãŒãšã¯å¯Ÿç §çã«ãããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒã³ãŒãã§æ±ºå®ãããŸãã
layout(isolines, equal_spacing) in; // .
ããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒã¯ãæœè±¡ãããã®åãã€ã³ãã«å¯ŸããŠåŒã³åºãããŸãã ããšãã°ããããã64x64ã®èŒªéã泚æããå Žåãã·ã§ãŒããŒã¯4096ååŒã³åºãããŸãã ããã»ã¬ãŒã·ã§ã³ã³ã³ãããŒã«ã·ã§ãŒããŒã®åºåããã®ãã¹ãŠã®ããŒã¯ã¯ããã®å ¥åã«ãªããŸãã
in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[gl_MaxPatchVertices];
gl_PatchVerticesInãgl_PrimitiveIDãgl_TessLevelOuterãgl_TessLevelInnerã¯æ¢ã«ããªãã¿ã§ãã æåŸã®2ã€ã®å€æ°ã¯ãããã»ã¬ãŒã·ã§ã³ã³ã³ãããŒã«ã·ã§ãŒããŒãšåãã¿ã€ãã§ãããèªã¿åãå°çšã§ãã æåŸã«ãæãèå³æ·±ãå ¥åå€æ°ã¯
in vec3 gl_TessCoord;
ããã«ã¯ãæœè±¡ãããã®çŸåšã®ïŒãã®åŒã³åºãã®ïŒãã€ã³ãã®åº§æšãå«ãŸããŸãã vec3ãšããŠå®£èšãããŠããŸãããgl_TessCoord.zã¯äžè§åœ¢ã«å¯ŸããŠã®ã¿æå³ããããŸãã æ£æ¹åœ¢ãŸãã¯èŒªéã®ãã®åº§æšã®èªã¿åãã¯å®çŸ©ãããŠããŸããã
ã·ã§ãŒããŒã®åºåã«ããã€ãã®å€æ°ãé©çšã§ããŸãã äž»ãªãã®ã¯vec4 gl_Positionã§ããããã€ãã©ã€ã³ã®æ¬¡ã®ã¹ããŒãžã®ããã«ããªããã£ããåéãããé ç¹ã®åº§æšãèšé²ããå¿ èŠããããŸãã ç§ãã¡ã®å Žåãããã¯ã»ã°ã¡ã³ãã®ã·ãŒã±ã³ã¹ã§ãããªããªãã ããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒã¯ãå°æ¥ã®ããã·ã¥ã®ã¹ã±ã«ãã³ã®ã¿ãçæããŸãã
ãã®ãããæœè±¡ãããã®é ç¹ã¯å€æ°ïŒæ倧4096ïŒãããåãã»ã°ã¡ã³ãã«åå²ãããè¡ã«ç·šæãããŠããŸãã ãã®åœ¢ç¶ãå€æŽããã«ç·ãšããŠæç»ããå ŽåïŒ
gl_Position = vec4(gl_TessCoord.xy, 0.0f, 1.0f);
ããã¥ã¡ã³ãã®åçã«äŒŒããã®ã衚瀺ãããŸã ã

以äžã®ã¹ã¯ãªãŒã³ã·ã§ããã§ã¯ãå°ããªåŽé¢å³
ãããã®ç·ããèãäœãæ¹æ³ã¯ïŒ éå§ããã«ã¯ãããããåçŽã«é 眮ããŸãã
gl_Position = vec4(gl_TessCoord.yx, 0.0f, 1.0f);

ãããŠãåçŽè»žãäžå¿ã«ããããå圢ã«é 眮ããæ¹æ³ãåŠã³ãŸãã
vec3 position = vec3(2.0f, gl_TessCoord.x, 0.0f); float alpha = gl_TessCoord.y * 2.0f * M_PI; float cosAlpha = cos(alpha); float sinAlpha = sin(alpha); mat3 circDistribution = mat3( cosAlpha, 0.0f, -sinAlpha, 0.0f, 1.0f, 0.0f, sinAlpha, 0.0f, cosAlpha); position = circDistribution * position; gl_Position = vec4(position, 1.0f);

ãã ãããã®ãããªç·ã¯èã¿ãšããããããã§ã³ã¹ã®ããã«èŠããŸãã ããã·ã¥ãããèªç¶ã«ããããã«ã3次ããžãšæ²ç·ã®ããã«ç·ãæ²ããŸãããã

ãããŠãããã§åº§æšgl_TessCoord.xã¯éåžžã«äŸ¿å©ã§ããããã«ã€ããŠã¯ãåã¹ãã ã«æ²¿ã£ãŠ0ãã1ãŸã§å®è¡ãããšèããããšã«åæããŸããã æ²ç·ã®åœ¢ç¶ã¯ãåºæºç¹P 0 ... P 3ã«å®å šã«äŸåããŸãã èã®åºã¯åžžã«å°é¢ã«ããããã®äžéšã¯åžžã«ç©ºãåããŠããã®ã§ãP 0 =ïŒ0; 0ïŒãåããŸãã ãããŠãæ®ãã®èªç±ç¹ã®å°ãªããšãããããã®äœçœ®ãéžæããããã«ã cubic-bezier.comã¯å®ç§ã§ã ããã®å¯äžã®ç®çã¯ãå¿ èŠãªåœ¢ã®æ²ç·ãäœæããããšã§ãã ããã§ãgl_TessCoord.xãããžã§æ²ç·ã®åŒã«ä»£å ¥ãããšãé ç¹ãæ²ç·äžã«ãããã»ã°ã¡ã³ããæ²ç·ãè¿äŒŒããããªã©ã€ã³ãåŸãããŸãã
float t = gl_TessCoord.x; // . float t1 = t - 1.0f; // , . // : position.xy = -p0 * (t1 * t1 * t1) + p3 * (t * t * t) + p1 * t * (t1 * t1) * 3.0f - p2 * (t * t) * t1 * 3.0f; // , : position.x += 2.0f; // . , : position.z = 0.0f;

å°æ¥çã«ã¯ã湟æ²ããã¹ãã ã®åšå²ã«ããªãŽã³ãæ§ç¯ããå¿ èŠããããŸãããã®ãããç Žæããã¹ãã ã®åé ç¹ã§ãã¹ãã ã«åçŽãªå¹³é¢ãç¥ãå¿ èŠããããŸãã 埮å幟äœåŠã®éçšããããã©ã¡ããªãã¯æ²ç·ã®äž»æ³ç·ã®ãã¯ãã«ã¯ããã©ã¡ãŒã¿ãŒã«é¢ããæ²ç·ã®å°é¢æ°ã®ãã¯ãã«ç©ã®çµã¿åãããšããŠååŸã§ããããšãããã£ãŠããŸãã
[B 'ã[B'ãB '']]ïŒ1ïŒ
å¹³é¢ãäžæã«æå®ããã«ã¯ããã1ã€ã®ãã¯ãã«ãå¿ èŠã§ãã ç§ãã¡ã®å Žåãæ²ç·å šäœã¯åçŽé¢XYã«ãããŸããã€ãŸããã¡ã€ã³æ³ç·ã¯ãã®äžã«ãããŸãã ãããã£ãŠãæ²ç·ã®åŸæ³ç·ã¯ç¡æã§æäŸãããŸããããã¯åãªãå®æ°ãã¯ãã«ïŒ0; 0; 1ïŒã§ãã ããã§ãå± å¿å°ã®è¯ãXYå¹³é¢ãããã¹ãã ãåç¹ãäžå¿ã«å転ããããšãæãåºããŠãã ãããã€ãŸããæ³ç·å¹³é¢ãå転ããå¿ èŠããããŸãã ãããè¡ãã«ã¯ãäž¡æ¹ã®çæãã¯ãã«ã«ã¹ãã ã®ãã€ã³ããšåãå転è¡åãæããã ãã§ååã§ãã ãã¹ãŠããŸãšããïŒ
// : out vec3 normal; out vec3 binormal; // : normal = normalize( circDistribution * // , . vec3( // , (1): p0.y * (t1 * t1) * -3.0f + p1.y * (t1 * t1) * 3.0f - p2.y * (t * t) * 3.0f + p3.y * (t * t) * 3.0f - p2.y * t * t1 * 6.0f + p1.y * t * t1 * 6.0f, p0.x * (t1 * t1) * 3.0f - p1.x * (t1 * t1) * 3.0f + p2.x * (t * t) * 3.0f - p3.x * (t * t) * 3.0f + p2.x * t * t1 * 6.0f - p1.x * t * t1 * 6.0f, 0.0f )); // : binormal = (circDistribution * vec3(0.0f, 0.0f, 1.0f));
ãŸããæ確ã«ããããã«ãã¹ãã ã®è©³çŽ°ãæžãããŸãã æ³ç·ã¯èµ€ã§æç»ãããåŸæ³ç·ã¯éã§æç»ãããŸãã

ã¢ãã¡ãŒã·ã§ã³ã«ã€ããŠç°¡åã«èª¬æããŸãã ãŸããèã¯èªç¶ã«åããŸãã ããã¯ãä»ã®å ã®ãã€ã³ããäžå¿ãšããæ²ç·ã®ã¢ã³ã«ãŒãã€ã³ãã®å圢å転ã«ãã£ãŠè¡ãããŸãã ãã®å Žåãåæç¹ã®äœçœ®ãšå転ã®åæäœçžã¯ã©ã³ãã å€æ°ã«äŸåãïŒã©ã³ãã ãª1次å ãã¯ã¹ãã£ãèŠããŠããŸããïŒïŒãããã¯gl_TessCoord.yãšgl_PrimitiveIDã«äŸåããŸãã ãããã£ãŠãåããã·ã¥ã®åã¹ãã ã¯ç¬èªã®æ¹æ³ã§ç§»åããã«ãªã¹ã®é¯èŠãäœãåºããŸãã ãŸãã移åã¯å¶åŸ¡ç¹ã®ç§»åã«ãã£ãŠè¡ããããããæ³ç·ãšåŸæ³ç·ã¯å®å šã«æ£ãããŸãŸã§ãã å®éãéªšæ Œã¢ãã¡ãŒã·ã§ã³ãååŸããŸããããã®ã¢ãã¡ãŒã·ã§ã³ã§ã¯ãããŒã³ããã®å Žã§çæãããã¡ã¢ãªãå æããŸããã
èã¿ã®åœŒãèªèº«ã®åãã«å ããŠã圌ãã¯ãŸã ã颚ãã®åœ±é¿ãåããŸãã 颚ã¯ã2ã€ã®ãŠãŒã¶ãŒãã©ã¡ãŒã¿ãŒãšããŒãªã³ãã€ãºã«äŸåããéã ãããŠãŒã¶ãŒãæå®ããæ¹åã®ã¹ãã ã®é ç¹ã®å€äœã§ãã ãã®å Žåã颚ãèã®æ ¹ãå€äœãããã¹ãã§ã¯ãªããããå€äœã®éã«æè»æ§é¢æ°ãä¹ç®ãããŸãã
float flexibility(const in float x) { return x * x; }
ã¹ãã t1ã«æ²¿ã£ã座æšããååŸã ã«ã¹ã¿ã 颚ãã©ã¡ãŒã¿ãŒã¯ãçŽç²ã«æ¡ä»¶ä»ãã§ãé床ãããã³ãä¹±æ°æµããšåŒã°ããŸãããŠãŒã¶ãŒãã¢ã¯ã»ã¹ã§ããç¯å²ã§å€æŽããããšã¯ããããã®æ°æµãã©ã¡ãŒã¿ãŒãå€æŽããããšã«äŒŒãŠããããã§ãã ãã ãããã®ã颚ãã¯å®éã®ç©çåŠãšã¯é¢ä¿ãããŸããã ã€ã³ã¿ãŒãã§ã€ã¹ã®é床ã¹ã©ã€ããŒã¯ãæ³ç·ã調æŽããã«æ³ç·ãèšç®ããåŸãã¹ã±ã«ãã³ã«é¢šãé©çšããããããæå³çã«å°ããªå€ã«å¶éãããŠããŸãã ãã®ãããæ³ç·ã¯ãã®ãããªãã®ã§ã¯ãªããªããã¹ã±ã«ãã³ã®åŒ·ãæªã¿ïŒå€§ããªã颚éãïŒã«ãããããªãŽã³ã®èªå·±äº€å·®ãçŸããŸãã
ããã€ãºã®å€ãããã¯ã¹ãã£ãããå ŽåãPerlinãã€ãºã¯ãªãã§ããïŒ å®éãPerlinãã€ãºãšã¯å¯Ÿç §çã«ããã¯ã¹ãã£å€ã¯åº§æšã®é£ç¶é¢æ°ã§ã¯ãããŸããã ãããã£ãŠãåãã¬ãŒã ã®ãã€ãºã®å€ããã¯ã¹ãã£ã«å¿ããŠãªãã»ãããäœæãããšãæ»ãããªé¢šã®ä»£ããã«ãã¬ãŒã ã¬ãŒãã§æ··oticãšããçæ£ãçããŸãã Perlinã®ãã€ãºã®é«å質ãªå®è£ ã¯ã Stefan GustavsonããååŸãããŸããã
ããªãŽã³ãæ§ç¯ããã«ã¯ä»ã«äœãå¿ èŠã§ããïŒ ãŸããèã®åãã¯æ ¹ããé ç¹ã«åãã£ãŠæžå°ããã¯ãã§ãã ãããã£ãŠãã¹ãã ã«æ²¿ã£ã座æšã«å¿ããŠã察å¿ããåºåå€æ°ãäœæããããã«åãã転éããŸãã
out float stemThickness; float thickness(const in float x) { return (1.0f - x) / 0.9f; } //... stemThickness = thickness(gl_TessCoord.x);
ã¹ãã ã«æ²¿ã£ã座æšãšããã·ã¥å ã®ã¹ãã ã®æ°ããã³ã³ãã¢ã«æ²¿ã£ãŠããã«è»¢éãããŸãã
out float along; flat out float stemIdx; // ... along = gl_TessCoord.x; stemIdx = gl_TessCoord.y;
ãã¯ã¹ãã£ãé©çšãããšãã«å¿ èŠã«ãªããŸãã
幟äœåŠã·ã§ãŒããŒ
æåŸã«ããã¹ã®å¹ŸäœåŠçéšåã®çµããã«å°éããŸããã ãžãªã¡ããªã·ã§ãŒããŒã®å ¥åã§ãããªããã£ãå šäœãååŸããŸãã ããã»ã¬ãŒã·ã§ã³ã¹ããŒãžã®å ¥åã§ãé©åãªéã®ããŒã¿ãå«ãããšãã§ããä»»æã®ããããããå Žåãããªããã£ãã¯ãã€ã³ããã©ã€ã³ããŸãã¯äžè§åœ¢ã§ããããã»ã¬ãŒã·ã§ã³ã·ã§ãŒããŒããªãå Žåã¯ãglDraw *åŒã³åºãããã®ããªããã£ãïŒéåžžã¯äžè§åœ¢ïŒããžãªã¡ããªã·ã§ãŒããŒã®å ¥åã«è¡šç€ºãããŸããããã¯ãé ç¹ã·ã§ãŒããŒã«ãã£ãŠåçŽã«åŠçãããå¯èœæ§ããããŸãããã®å Žåãããã»ã¬ãŒã·ã§ã³ã¯ãã»ã°ã¡ã³ããšããŠåãå ¥ãã茪éãã€ãŸãé ç¹ã®ãã¢ãçæããŸãã
layout(lines) in;
ãããã®é ç¹ã¯ãçµã¿èŸŒã¿ã®å ¥åé åã«æžã蟌ãŸããŸãã
in gl_PerVertex { vec4 gl_Position; float gl_PointSize; float gl_ClipDistance[]; } gl_in[];
ãã®å Žåãã€ã³ããã¯ã¹ã¯0ãŸãã¯1ã®ã¿ã§äœæã§ããŸãããŠãŒã¶ãŒå ¥åå€æ°ããåãç¯å²ã®ã€ã³ããã¯ã¹ãæã€é åãšããŠå®çŸ©ãããŸãã
in vec3 normal[]; in vec3 binormal[]; in float stemThickness[]; in float along[]; flat in float stemIdx[];
ãžãªã¡ããªã·ã§ãŒããŒã®åºåã«ããã€ã³ããäžé£ã®ç·ãäžé£ã®äžè§åœ¢ãé©çšã§ããŸããæåŸã®ãªãã·ã§ã³ã䜿çšããŸãã
layout(triangle_strip) out;
ã·ã§ãŒããŒã¯åå ¥åããªããã£ãã«å¯ŸããŠåŒã³åºãããè€æ°ã®ããªããã£ããçæã§ããŸããããã¯ã2ã€ã®çµã¿èŸŒã¿é¢æ°ã䜿çšããŠè¡ãããŸããåã®ã¹ããŒãžãšåæ§ã«ãåºåå€æ°ã¯gl_PositionãšåŒã°ããŸããå ¥ååŸãã·ã§ãŒããŒã¯çµã¿èŸŒã¿é¢æ°EmitVertexïŒïŒãåŒã³åºããŠãé ç¹åœ¢æã®çµäºã«ã€ããŠãããªã«ãŒãã«éç¥ããå¿ èŠããããŸããããªããã£ãã®ãã¹ãŠã®é ç¹ã®åœ¢æãçµäºãããšãEndPrimitiveïŒïŒé¢æ°ãåŒã³åºãããŸãã
ã¹ãã ã®ããªãŽã³ã¯åçŽã«åœ¢æãããŸãïŒã»ã°ã¡ã³ãã®æåãšæåŸã§ã¹ãã ã®æ²ç·ã«åçŽãªå¹³é¢ãç¥ã£ãŠããã®ã§ããããã®å¹³é¢å ã§ã»ã°ã¡ã³ããšã®äº€ç¹ã®åšãã移åããããã€ãã®ã¹ãããã§é ç¹ã解æŸããŸãã詳现ã¯ããã®ã¹ããããã€ãŸãå¹¹ããã©ããããŸãã¯åéã®ããã«èŠãããã©ããã
ããšãã°ãããã¯ãæ確ã«ããããã«ãéè£éïŒãã©ããïŒåº§æšãšãã©ã°ã¡ã³ãæ³ç·ã§5ã»ã¯ã¿ãŒã®èã®èã¿ãã©ã®ããã«èŠãããã§ãïŒ

ãããŠãããã«èª¬æããã¢ãããŒããå®è£ ããã³ãŒãããããŸãïŒ
for(int i = 0; i < numSectors + 1; ++i) { // float around = i / float(numSectors); // , [0; 1] float alpha = (around) * 2.0f * M_PI; // () for(int j = 0; j < 2; ++j) { // // - : vec3 r = cos(alpha) * normal[j] + sin(alpha) * binormal[j]; // : vec3 vertexPosition = r * stemRadius * stemThickness[j] + gl_in[j].gl_Position.xyz; // . // . // , .. gl_Position // , . fragPosition = vertexPosition; // . fragNormal = r; // . fragAlong = along[j]; // . // fragAlong fragAround , // . fragAround = around; // , // . // . stemIdxFrag = stemIdx[j]; // , . // "" , // . gl_Position = viewProjectionMatrix * vec4 (vertexPosition, gl_in[j].gl_Position.w); EmitVertex(); } } EndPrimitive();
ãã©ã°ã¡ã³ãã·ã§ãŒããŒ
ãã©ã°ã¡ã³ãã·ã§ãŒããŒã¯ããªãæšæºã«èŠããã®ã§ãç°¡åã«èª¬æããŸãããã®äžã§ãéåžžã®Fongç §æã¯ããã§ã«éŠŽæã¿ã®ããStephen GustavsonããåãããVoronoiãã€ã¢ã°ã©ã ã«åºã¥ããã»ã«ã®åœ¢ã®æç¶ãåãã¯ã¹ãã£ã§èŠçŽãããŠããŸãããã¯ã»ã«ã®è²ã¯ããã¯ã¹ãã£åº§æšã ãã§ãªããæéïŒãã¬ãŒã çªå·ïŒããã³èã¿ã®èã®æ°ã«ãäŸåããŸãã
out vec4 outColor; float sfn = float(frameNumber) / totalFrames; float cap(const in float x) { return -abs(fma(x, 2.0f, -1.0f)) + 1.0f; } //... float cell = cellular2x2(vec2(fma(sfn, 100, rand(stemIdxFrag) + fragAlong * 3.0f), cap(fragAround)) * 10.0f).x * 0.3f; outColor = ambient + diffuse + specular + vec4(0.0f, cell, 0.0f, 0.0f)
ãããã£ãŠã现èã¯å¹¹ã«æ²¿ã£ãŠæ»ããã«ãã¯ãªãŒããããç°ãªãå¹¹ã§ç°ãªã£ãŠèŠããŸãã
ããã«ãããã°ã©ãã£ãã¯ã¹ãã€ãã©ã€ã³ã«æ²¿ã£ãããŒã¿ãã¹ãçµäºããŸããã€ãŸããåšåº«ã確ä¿ããæéã§ãã
ãªãã§ïŒ
ããã§ãããäŒçµ±çãªã¢ãããŒããšæ¯èŒããŠãç§ãã¡ã¯äœãç²åŸããŸãããïŒåçïŒã¡ã¢ãªãæè»æ§ã垯åå¹ ã®ç¯çŽãå¥ã®æ¹æ³ã§åæ§ã®æè»æ§ã®ã¢ãã¡ãŒã·ã§ã³ãäœæããããšãããšã次ã®ããã€ããè¡ãå¿ èŠããããŸãã
- ãžãªã¡ããªããããªã¡ã¢ãªã«ã¹ããªãŒãã³ã°ããåæã«CPUãããŒãããŸããããã¯æåç·ã®æ¹æ³ã§ããããããã®ãããªããŒã¿éã«å¯ŸããŠã ããã»ãšãã©å®è¡ããŸããã
- ããŒã³ãã¡ã¢ãªã«ä¿åãããžãªã¡ããªã·ã§ãŒããŒã䜿çšããŸãããã ããäžéšã®ã¡ã¿ããŒã¿ã«ã¯ãé ç¹ã®è¿œå å±æ§ãå¿ èŠã«ãªãå¯èœæ§ãæãé«ããããã«åçš®ã®å€æ°ãä»ããŠå€§éã®ããŒã¿ã転éããå¿ èŠããããŸãã
- ã¢ãã¡ãŒã·ã§ã³ã®ã©ã³ãã æ§ãç ç²ã«ããããã©ã³ãã å€æ°ãè¿œå ããŸããããã«ãããã©ã³ãã ããŒã¿ãå«ã倧éã®ãã¯ã¹ãã£ãçæãããããPerlinãã€ãºãããã«èšç®ãããŸãã
䟿å©ãªãªã³ã¯
ã»ãšãã©ã®ãªã³ã¯ã¯ãã§ã«ããã¹ãã«å«ãŸããŠããŸããããã§ã¯ããã¢ã®äœæ¥äžã«äœ¿çšããã䟿å©ãªãªã³ã¯ãæ®ããããšæããŸãã
- ãªã¢ã«ã¿ã€ã ã®ãããšã»ã¹ããŒã¯ã¹æ¹çšåŒãåç §ã§èšè¿°ãããé£ç¶åªäœã®åäœãèšç®ããæ¹æ³ã¯ãèšç®ã·ã§ãŒããŒã§å®è£ ããããšã«ããããã¹ãã§èæ ®ãããæ¬äŒŒé¢šã®ä»£ããã«äœ¿çšã§ããŸãããã®ãæ¬åœã®ã颚ã¯æžŠãå·»ããŠé害ç©ã®åšããæµããŸãã
- OpenGLã®å ¬åŒã·ã§ãŒããªãã¡ã¬ã³ã¹ããã¥ã¢ã«ãç¹å®ã®çµã¿èŸŒã¿é¢æ°ã®ååšãæãåºãããšãã§ããã®ã§ãã·ã§ãŒããŒãæžããšãã«åœ¹ç«ã¡ãŸãã
- ããã°ã©ããã«ãã€ãã©ã€ã³ã®æŠèŠã
ãæž èŽããããšãããããŸããïŒ
UPD1
çµæãããª
UPD2 Windowsã®ãã€ããªãžã®
ãªã³ã¯ã