ãã®ç¿»èš³ã¯FERusMãšå ±åã§äœæãããŸããã
ç«ã®äžã§èå³ãæã£ãŠãã ããã
å
容
ããŒã1.ã¯ããã«
ããŒã2.åºæ¬çãªç §æ
ããŒã3. 3Dã¢ãã«ãããŠã³ããŒããã
ããŒã4.é«åºŠãªOpenGLæ©èœ
ããŒã5.é«åºŠãªç §æ
- Opengl
- ãŠã£ã³ããŠäœæ
- ããã«ã¡ã¯ãŠã£ã³ããŠ
- ããã«ã¡ã¯ãã©ã€ã¢ã³ã°ã«
- ã·ã§ãŒããŒ
- ãã¯ã¹ãã£ãŒ
- å€æ
- 座æšç³»
- ã«ã¡ã©
ããŒã2.åºæ¬çãªç §æ
ããŒã3. 3Dã¢ãã«ãããŠã³ããŒããã
ããŒã4.é«åºŠãªOpenGLæ©èœ
- 深床ãã¹ã
- ã¹ãã³ã·ã«ãã¹ã
- è²æ··å
- é¡ã®ã¯ãªããã³ã°
- ãã¬ãŒã ãããã¡
- ãã¥ãŒããã¯ã«ãŒã
- é«åºŠãªããŒã¿åŠç
- é«åºŠãªGLSL
- 幟äœåŠã·ã§ãŒããŒ
- ã€ã³ã¹ã¿ã³ã¹å
- ã¹ã ãŒãžã³ã°
ããŒã5.é«åºŠãªç §æ
- é«åºŠãªç §æã Blinn-Fongã¢ãã«ã
- ã¬ã³ãè£æ£
- ã·ã£ããŠã«ãŒã
- å šæ¹åã·ã£ããŠããã
ããŒã1.3ã ããã«ã¡ã¯ãŠã£ã³ããŠ
GLFWãã€ã³ã¹ããŒã«ããããç°¡åãªããã°ã©ã ãäœæããæãæ¥ãŸããããã®ãããªè³æã§ããããããã«ããããHello WorldãšããŸãããã æåã«.cppãã¡ã€ã«ãäœæããããã€ãã®ããããŒãæ¥ç¶ããå¿ èŠããããŸãããŸãã GLEWã©ã€ãã©ãªã®éçããŒãžã§ã³ã䜿çšããããšã瀺ãå€æ°GLEW_STATICãèšå®ããå¿ èŠããããŸãã
// GLEW GLFW. // GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h>
GLFWã®åã«GLEWãæ¥ç¶ãããŠããããšã確èªããŠãã ããã GLEWããããŒãã¡ã€ã«ã«ã¯ã GL / gl.hãªã©ã®å¿ èŠãªOpenGLããããŒãã¡ã€ã«ããã¹ãŠå«ãŸããŠããŸãã
翻蚳è ããã®ã¡ã¢
TrueBersãææããããã«ãããã¯ããããå€ãæŸèæã§ãããGLFWã®ææ°ããŒãžã§ã³èªäœãå¿ èŠãªã©ã€ãã©ãªãæ¥ç¶ããŸããã GLFW_INCLUDE_NONEãã©ã°ãèšå®ãããŠããããããã©ã«ãã§ã¯å®£èšãããŠããŸããã
次ã«ãã¡ã€ã³é¢æ°ãèšè¿°ããŸããããã§ãGLFWãŠã£ã³ããŠãäœæãããŸãã 次ã®ããã«ãªããŸãã
int main() { // GLFW glfwInit(); // GLFW // OpenGL. // glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); return 0; }
ãã®é¢æ°ã§ã¯ãæåã«glfwInité¢æ°ãåŒã³åºããŠGLFWãåæåãã 次ã«glfwWindowHinté¢æ°ã䜿çšããŠGLFWãæ§æããŸãã glfwWindowHintã«ã¯éåžžã«åçŽãªçœ²åããããæåã®åŒæ°ã«ã¯å€æŽãããã©ã¡ãŒã¿ãŒã®èå¥åãæž¡ãå¿ èŠãããã2çªç®ã®ãã©ã¡ãŒã¿ãŒã¯å¯Ÿå¿ãããã©ã¡ãŒã¿ãŒã«èšå®ãããå€ã§ãã ãã©ã¡ãŒã¿ãŒèå¥åãšãã®å€ã®äžéšã¯ã GLFW_ãã¬ãã£ãã¯ã¹ä»ãã®äžè¬çãªåæã«ãããŸãã GLFWã³ã³ããã¹ãã®èšå®ã®è©³çŽ°ã«ã€ããŠã¯ã å ¬åŒGLFWããã¥ã¡ã³ããåç §ããŠãã ããã ãã®äŸãå®è¡ãããšãã«ãæªå®çŸ©ã®åäœã«éåžžã«é¡äŒŒãããšã©ãŒã衚瀺ãããå ŽåãGLFWã©ã€ãã©ãªã誀ã£ãŠæ¥ç¶ããããšãæå³ããŸãã
OpenGLããŒãžã§ã³3.3ã¯èšäºã§äœ¿çšããããããglfwWindowHintã¡ãœãããåŒæ°ã§åŒã³åºããçµæãšããŠããã®ç¹å®ã®ããŒãžã§ã³ã䜿çšããŠããããšãGLFWã«äŒããå¿ èŠããããŸãã
GLFW_CONTEXT_VERSION_MAJOR, 3 GLFW_CONTEXT_VERSION_MINOR, 3
ãããã£ãŠãGLFWã¯OpenGLã³ã³ããã¹ããäœæãããšãã«ãã¹ãŠã®å¿ èŠãªã¢ã¯ã·ã§ã³ãå®è¡ããŸãã ããã«ããããŠãŒã¶ãŒãå¿ èŠãªããŒãžã§ã³ã®OpenGLãæã£ãŠããªãå ŽåïŒãã®å ŽåãããŒãžã§ã³3.3ãèæ ®ãããŸãïŒãGLFWãèµ·åããªããªããŸãã ããŒãžã§ã³ã®ã€ã³ã¹ããŒã«ã«å ããŠã GLFW_OPENGL_CORE_PROFILEãããã¡ã€ã«ã䜿çšããããšãæ確ã«ç€ºããŸããã ããã«ãããã¬ã¬ã·ãŒOpenGLæ©èœã䜿çšãããšãã«ãšã©ãŒãçºçããŸãã Mac OS Xã䜿çšããŠããå ŽåãGLEWåæåã³ãŒãã«æ¬¡ã®glfwWindowHinté¢æ°åŒã³åºãïŒGLFW_OPENGL_FORWARD_COMPATãGL_TRUEïŒãè¿œå ããå¿ èŠããããŸãã
ããŒããŠã§ã¢ã«OpenGLãµããŒãããŒãžã§ã³3.3以éãããã察å¿ããOpenGLããŒãžã§ã³ãOSã«ã€ã³ã¹ããŒã«ãããŠããããšã確èªããŠãã ããã Linuxã³ã³ãã¥ãŒã¿ãŒã®OpenGLã®ããŒãžã§ã³ã確èªããã«ã¯ãã³ã³ãœãŒã«ã§glxinfoã䜿çšããŸãã Windowsã®å Žåã OpenGL Extension Viewerã䜿çšã§ããŸãã OpenGLã®ããŒãžã§ã³ãå¿ èŠãããäœãå ŽåãããŒããŠã§ã¢ãããããµããŒãããŠããããšã確èªãããã©ã€ããŒãæŽæ°ããŠãã ããã
次ã«ããŠã£ã³ããŠãªããžã§ã¯ããäœæããå¿ èŠããããŸãã ãã®ãªããžã§ã¯ãã«ã¯ããŠã£ã³ããŠã«é¢ãããã¹ãŠã®å¿ èŠãªæ å ±ãå«ãŸããŠãããGLFWé¢æ°ã«ãã£ãŠäœ¿çšãããŸãã
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr); if (window == nullptr) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window);
glfwCreateWindowé¢æ°ã®ã·ã°ããã£ã«ã¯ãããŠã£ã³ããŠã®é«ãããããŠã£ã³ããŠã®å¹ ããããŠã£ã³ããŠåãã®åŒæ°ãå¿ èŠã§ãïŒæ®ãã®åŒæ°ã¯äžèŠã§ãïŒã åŸã§å¿ èŠã«ãªãGLFWwindowåã®ãªããžã§ã¯ããžã®ãã€ã³ã¿ãŒãè¿ããŸãã 次ã«ããã®ã¹ããªãŒã ã®ã¡ã€ã³ã³ã³ããã¹ãã«ãªããŠã£ã³ããŠã³ã³ããã¹ããäœæããŸãã
ã°ãªã¥ãŒ
ååã®ã¬ãã¹ã³ã§ã¯ãGLEWã¯OpenGLé¢æ°ãžã®ãã€ã³ã¿ãŒã管çãããããOpenGLé¢æ°ãåŒã³åºãåã«GLEWãåæåããå¿ èŠããããšè¿°ã¹ãŸããã
glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; }
GLEWãåæåããåã«ã glewExperimentalå€æ°ãGL_TRUEã«èšå®ããããšã«æ³šæããŠãã ããã glewExperimentalãGL_TRUEã«èšå®ãããšãGLEWã¯ææ°ã®ææ³ã䜿çšããŠOpenGLæ©èœãå¶åŸ¡ã§ããŸãã ãŸãããã®å€æ°ãããã©ã«ãå€ã®ãŸãŸã«ãããšãã³ã¢ãããã¡ã€ã«ã¢ãŒãã®äœ¿çšæã«åé¡ãçºçããå ŽåããããŸãã
ãã¥ãŒããŒã
äœããæãå§ããåã«ãäœãä»ã®ããšãããå¿ èŠããããŸãã OpenGLã«ããŒã¿ã®è¡šç€ºæ¹æ³ãšãŠã£ã³ããŠã«çžå¯Ÿçãªåº§æšãèªèãããããã«ãã¬ã³ããªã³ã°ããããŠã£ã³ããŠã®ãµã€ãºãOpenGLã«äŒããå¿ èŠããããŸãã ãããã®å€ã¯glViewporté¢æ°ãä»ããŠèšå®ã§ããŸãã
int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height);
glViewporté¢æ°ã®æåã®2ã€ã®åŒæ°ã¯ããŠã£ã³ããŠã®å·Šäžé ã®äœçœ®ã§ãã 3çªç®ãš4çªç®ã¯ã¬ã³ããªã³ã°ããããŠã£ã³ããŠã®å¹ ãšé«ãïŒpxïŒã§ãGLFWããçŽæ¥ååŸããŸãã å¹ ãšé«ãããããã800ãš600ã«æåã§èšå®ãã代ããã«ãGLFWã®å€ã䜿çšããŸãããã®ã¢ã«ãŽãªãºã ã¯ãDPIã®å€§ããç»é¢ïŒApple Retinaãªã©ïŒã§ãæ©èœããããã§ãã
ãã¥ãŒããŒãã«äœãå€ãèšå®ããããšãã§ããŸãã ãã®å Žåãã¬ã³ããªã³ã°ãããæ å ±ã¯ãã¹ãŠå°ãããªããããšãã°ãã¢ããªã±ãŒã·ã§ã³ã®å¥ã®éšåããã¥ãŒããŒãã®å€åŽã«ã¬ã³ããªã³ã°ã§ããŸãã
èå°è£ã§ã¯ãOpenGLã¯glViewportãä»ããŠéä¿¡ãããããŒã¿ã䜿çšããŠã2D座æšãç»é¢åº§æšã«å€æããŸãã ããšãã°ãçµæãšããŠã®äœçœ®ïŒ-0.5ã0.5ïŒã¯ïŒ200ã450ïŒã«å€æãããŸãã åŠçãããOpenGL座æšã¯ãããã-1ã1ã®ç¯å²ã«ããããšã«æ³šæããŠãã ãããç¯å²ïŒ-1ã1ïŒããïŒ0,800ïŒããã³ïŒ0,600ïŒã«å¹æçã«å€æã§ããŸãã
ãšã³ãžã³ãæºåããŸã
1ã€ã®ç»åãã¬ã³ããªã³ã°ããçŽåŸã«ã¢ããªã±ãŒã·ã§ã³ãã¯ã©ãã·ã¥ããã®ã¯æãŸãããããŸããã ããã°ã©ã ãéãããããŸã§ãç»åã®ã¬ã³ããªã³ã°ãšãŠãŒã¶ãŒå ¥åã®åŠçãç¶ããããšèããŠããŸãã ãããè¡ãã«ã¯ãGLFWã«åæ¢ãããŸã§åŠçãããã²ãŒã ã«ãŒããšåŒã°ããã«ãŒããäœæããå¿ èŠããããŸãã
while(!glfwWindowShouldClose(window)) { glfwPollEvents(); glfwSwapBuffers(window); }
glfwWindowShouldCloseé¢æ°ã¯ãã«ãŒãã®åå埩ã®éå§æã«ãGLFWãéããåœä»€ãåãåã£ããã©ããã確èªããŸããGLFWãéããå Žåãé¢æ°ã¯trueãè¿ããã²ãŒã ã«ãŒãã¯åäœãåæ¢ããŸãããã®åŸãã¢ããªã±ãŒã·ã§ã³ãéããŸãã
glfwPollEventsé¢æ°ã¯ãã€ãã³ãïŒããŒããŒãå ¥åãããŠã¹ã®åããªã©ïŒãããªã¬ãŒããããã©ããã確èªããã€ã³ã¹ããŒã«ãããé¢æ°ïŒã³ãŒã«ããã¯é¢æ°ãä»ããŠèšå®ã§ããŸãïŒãåŒã³åºããŸãã éåžžãã«ãŒãã®å埩ã®éå§æã«ã€ãã³ãåŠçé¢æ°ãåŒã³åºããŸãã
glfwSwapBuffersé¢æ°ã¯ãçŸåšã®å埩äžã«ã¬ã³ããªã³ã°ã«äœ¿çšãããçµæãç»é¢ã«è¡šç€ºããã«ã©ãŒãããã¡ãŒïŒGLFWãŠã£ã³ããŠã®åãã¯ã»ã«ã®ã«ã©ãŒå€ãå«ã倧ããªãããã¡ãŒïŒã眮ãæããŸãã
ããã«ãããã¡ãªã³ã°
ã¢ããªã±ãŒã·ã§ã³ãåäžã®ãããã¡ã«æç»ãããšãçµæã®ç»åãã¡ãã€ãããšããããŸãã ãã®åäœã®çç±ã¯ãã¬ã³ããªã³ã°ãç¬æã§ã¯ãªãããã¯ã»ã«ããšã«äžããå·Šãå³ããäžã«è¡ãããããã§ãã ç»åã¯ããã«ã¯è¡šç€ºãããŸããããåŸã ã«è¡šç€ºããããããå€ãã®ã¢ãŒãã£ãã¡ã¯ããçºçããå ŽåããããŸãã ãããã®åé¡ãåé¿ããããã«ããŠã£ã³ããŠã¢ããªã±ãŒã·ã§ã³ã¯ããã«ãããã¡ãªã³ã°ã䜿çšããŸãã ããã³ããããã¡ãŒã«ã¯ããŠãŒã¶ãŒã«è¡šç€ºãããçµæã®ã€ã¡ãŒãžãå«ãŸããåæã«ã ãªã¢ãããã¡ãŒã«ã¬ã³ããªã³ã°ãè¡ãããŸãã æç»ãçµäºãããšããã«ããããã®ãããã¡ã亀æãããäžåºŠã«ãŠãŒã¶ãŒã«ç»åã衚瀺ãããŸãã
ä»ã®äœã
ã²ãŒã ãµã€ã¯ã«ãçµäºãããšããã«ãå²ãåœãŠããããªãœãŒã¹ãã¯ãªã¢ããå¿ èŠããããŸãã ããã¯ãã¡ã€ã³é¢æ°ã®æåŸã«ããglfwTerminateé¢æ°ã«ãã£ãŠè¡ãããŸãã
glfwTerminate(); return 0;
ãã®ã³ãŒãã¯ãã¹ãŠã®ãªãœãŒã¹ãã¯ãªã¢ããã¢ããªã±ãŒã·ã§ã³ãçµäºããŸãã 次ã«ãã¢ããªã±ãŒã·ã§ã³ããã«ãããŠã¿ãŸããããã§åé¡ããªããã°ã次ã®ããã«è¡šç€ºãããŸãã
éå±ãªé»ãç»åã衚瀺ãããŠããå Žåã¯ããã¹ãŠãæ£ããè¡ããŸããïŒ ä»ã®äœããæãããã¬ãã¹ã³ã®ãã¹ãŠã®äŸãæ¥ç¶ããã®ã«åé¡ãããå Žåã¯ããã®ãœãŒã¹ã³ãŒããè©ŠããŠãã ããã
ã¢ããªã±ãŒã·ã§ã³ã®ãã«ãã«åé¡ãããå Žåã¯ãæåã«IDEã®ãªã³ã«ãŒãæ£ããæ§æãããŠããããšã確èªããŠãã ããïŒæåŸã®ã¬ãã¹ã³ã§èª¬æãããšããïŒã ãŸããã³ãŒãã«ãšã©ãŒããªãããšã確èªããŠãã ããã äžèšã®ãœãŒã¹ã³ãŒããšç°¡åã«æ¯èŒã§ããŸãã ããã§ãåé¡ã解決ããªãå Žåã¯ãå ã®èšäºã®ã³ã¡ã³ããã芧ãã ãããåé¡ã®è§£æ±ºçãèŠã€ãããããããŸããã
å ¥ã
å ¥åãããçšåºŠå¶åŸ¡ããããã«ãGLFWã®ã³ãŒã«ããã¯é¢æ°ã䜿çšã§ããŸãã ã³ãŒã«ããã¯é¢æ°ã¯ãé©åãªã¿ã€ãã³ã°ã§åŒã³åºãããããã«GLFWã«æž¡ãããšãã§ããé¢æ°ãžã®ãã€ã³ã¿ãŒã§ãã ãããã®é¢æ°ã®1ã€ã¯ããŠãŒã¶ãŒãããŒããŒãã䜿çšãããã³ã«åŒã³åºãããKeyCallbackã§ãã ãã®é¢æ°ã®ãããã¿ã€ãã¯æ¬¡ã®ãšããã§ãã
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
ãã®é¢æ°ã¯ãæåã®åŒæ°ãšããŠGLFWwindowãžã®ãã€ã³ã¿ãŒãåãããã®åŸã«æŒãããããŒãèšè¿°ããçªå·ãããŒã«å¯ŸããŠå®è¡ãããã¢ã¯ã·ã§ã³ãããã³ä¿®é£ŸåïŒshiftãcontrolãaltãŸãã¯superïŒãèšè¿°ããçªå·ãç¶ããŸãã ããŒãæŒããããšãGLFWã¯ãã®é¢æ°ãåŒã³åºããå¿ èŠãªåŒæ°ãæž¡ããŸãã
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { // ESC, WindowShouldClose true, // if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); }
ïŒæ°ããïŒ key_callbacké¢æ°ã§ã¯ãæŒãããããŒãESCããŒã§ãããã©ããã確èªããæŒãããïŒãªãªãŒã¹ãããŠããªãïŒå ŽåãglfwSetWindowShouldCloseã䜿çšããŠWindowShouldCloseããããã£ãtrueã«èšå®ããŠGLFWãéããŸãã ã²ãŒã ã«ãŒãã®æ¬¡ã®ã¹ããŒã¿ã¹ãã§ãã¯ã«ãããµã€ã¯ã«ãäžæãããã¢ããªã±ãŒã·ã§ã³ãçµäºããŸãã
ãã®é¢æ°ãGLFWã«æž¡ãã ãã§ãã ããã¯æ¬¡ã®ããã«è¡ãããŸãã
glfwSetKeyCallback(window, key_callback);
ãªãŒããŒã©ã€ãã§ããå€ãã®ã³ãŒã«ããã¯é¢æ°ããããŸãã ããšãã°ããŠã£ã³ããŠã®ãµã€ãºå€æŽããšã©ãŒåŠçãªã©ã®é¢æ°ããªãŒããŒã©ã€ãã§ããŸãã ãŠã£ã³ããŠã®äœæåŸãã²ãŒã ãµã€ã¯ã«ã®åã«ã³ãŒã«ããã¯é¢æ°ãç»é²ããŸãã
æç»
ãµã€ã¯ã«ã®åå埩ã§ã¬ã³ããªã³ã°ãçºçããããã«ããããããã¹ãŠã®ã¬ã³ããªã³ã°ã³ãã³ããã²ãŒã ã«ãŒãã«é 眮ããŸãã 次ã®ããã«ãªããŸãã
// while(!glfwWindowShouldClose(window)) { // . glfwPollEvents(); // ... // glfwSwapBuffers(window); }
ãã¹ãŠãæ£åžžã«æ©èœããããšã確èªããããã«ãç»é¢ãã¯ãªã¢ããè²ã§å¡ãã€ã¶ããŸãã ã¬ã³ããªã³ã°ã®åå埩ã®éå§æã«ãç»é¢ãã¯ãªã¢ããå¿ èŠããããŸããããããªããšã以åã®ã¬ã³ããªã³ã°ã®çµæã衚瀺ãããŸãïŒãã®å¹æãå®éã«éæããå¿ èŠãããå ŽåããããŸãããããã§ãªãå ŽåããããŸãïŒã glClearã䜿çšããŠãããã¡ãç°¡åã«ãã©ãã·ã¥ã§ããŸãããã®äžã«ãç¹å®ã®ãããã¡ããã©ãã·ã¥ããå¿ èŠãããããšã瀺ãç¹å¥ãªããããæž¡ããŸãã çŸåšèšå®ã§ãããããã¯ã GL_COLOR_BUFFER_BIT ã GL_DEPTH_BUFFER_BIT ãããã³GL_STENCIL_BUFFER_BITã§ãã 次ã«ãã«ã©ãŒãããã¡ã®ã¿ãã¯ãªã¢ããå¿ èŠããããŸãã
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT);
glClearColorãéããŠç»é¢ããããã«ãããè²ãèšå®ããŠããããšã«æ³šæããŠãã ãã ã glClearãåŒã³åºããšããã«ããããã¡å šäœãæå®ãããè²ã§å¡ãã€ã¶ãããŸãã ãã®çµæãç·éã«ãªããŸãã
ã芧ã®ãšããã glClearColorã¯ç¶æ èšå®é¢æ°ã§ããã glClearã¯ç¶æ ã䜿çšããŠç»é¢ã®å¡ãã€ã¶ãè²ã決å®ããç¶æ 䜿çšé¢æ°ã§ãã
ã¬ãã¹ã³ã®å®å šãªãœãŒã¹ã³ãŒãã¯ãã¡ãã«ãããŸã ã
ããã§ãã¬ã³ããªã³ã°é¢æ°ã®åŒã³åºãã§ã²ãŒã ã«ãŒããåããããšãã§ããŸãããã次ã®ã¬ãã¹ã³ã®ããã«ãããä¿åããŸãã