ããŒã1
ãã®èšäºã¯ã·ãªãŒãºã®æåã®èšäºã§ãã 圌女ã¯Qt 5㧠OpenGLã䜿çšããæ¹æ³ã瀺ããŸãã ãã®èšäºã§ã¯ãQtã§ã®OpenGLã®ãµããŒãã®æŽå²ã«ã€ããŠå°ã説æããŸãã 次ã«ã Qt 5.1ã§å°å ¥ãããæ°æ©èœã®æåã®éšåã«ã€ããŠèª¬æããŸãã 以éã®èšäºã§ã¯ãããå€ãã®æ©èœãšãQtã䜿çšããŠOpenGLãæäœããæ¹æ³ã®ç°¡åãªäŸãããã€ã説æããŸãã
ïŒéåžžã«ïŒQtãšOpenGLã®ç°¡åãªæŽå²
Qtã«ã¯ãOpenGLã䜿çšããæç»ãµããŒãã®é·ãæŽå²ããããŸãã ã»ãšãã©ã®Qtéçºè ã¯ã QGLWidgetãšãããããOpenGLããŒã¹ã®ãšã³ãžã³ã«ã€ããŠã®èããæã£ãŠããŸãã ããã«ãããçã®OpenGLãæäœãããã QPainter APIãæäŸããæ©èœã䜿çšãããã§ããŸãã ããã«å ããŠãQtã¯ããŸããŸãªOpenGLãªããžã§ã¯ãã®åšãã«ããã€ãã®äŸ¿å©ãªã©ãããŒãæäŸããŸãïŒ QGLShaderProgram ã QGLFramebufferObject ã QGLBufferãªã©ã
Qt 5ãèšèšããéããããã®QGL *ã¯ã©ã¹ã¯ãå®äºããšããŒã¯ãããææ°ã®QOpenGL *ã¯ã©ã¹ã¯QtGuiã¢ãžã¥ãŒã«ã®äžéšã«ãªããŸããïŒ ç¿»èš³è ã®ã¡ã¢ -以åã¯QtOpenGLã§ããïŒã ãããã®å€æŽã®çç±ã¯ãQt Quick 2ã®æ°ããèŠèŠåãOpenGLã«åºã¥ããŠãããçŸåšQtã®ã°ã©ãã£ã«ã«è£œåã®äž»èŠãªéšåã§ããããã§ãã ããã«ãæ°ããQOpenGL *ã¯ã©ã¹ã¯ãå€ãQGL *ã¯ã©ã¹ãçŽæ¥çœ®ãæãããã®ãšããŠäœ¿çšã§ããŸãã QtGuiã©ã€ãã©ãªã®QOpenGL *ã¯ã©ã¹ã䜿çšããããšããå§ãããŸãã
Qt 5.0ã¯ïŒåºæ¬çã«ïŒQt 4.8ãæäŸããOpenGLæ©èœã®åããµãã»ãããæäŸããŸãã ããã¯ãç¹ã«Qt Quick 2ã§å¿ èŠãªæ©èœã®ããã«å¿ èŠã§ããã Qt 4.8ã®æ©èœã«å ããŠãQt 5.0ã¯ãä»»æã®ãã©ãããã©ãŒã ã§ã«ã¹ã¿ã OpenGLãŠã£ã³ããŠãšã³ã³ããã¹ããç°¡åã«äœæããããã®ããŒã«ãæäŸããŸãã OpenGL Coreãããã¡ã€ã«ããµããŒãã§ããã³ã³ããã¹ããäœæããããã«ãããŸããŸãªãã©ãããã©ãŒã ã®æ©èœãæ°ã«ããå¿ èŠã¯ãããŸããã QOpenGLContextã䜿çšããã ãã§ãçœé«ªãã身ãå®ãããšãã§ããŸãïŒ
Qt 5.1ã§ã®åéºã¯ãOpenGLãšQtãã·ã³ãã«ã§ãšã¬ã¬ã³ãããããŠããŸãããã°æ¥œãããã®ã«ããããã®OpenGLæ©èœã®ãã¢ããå§ãŸããŸãïŒ ãã®ç®çã®ããã«ã KDABã¯QtãšOpenGLã®å¢çã®æ¡å€§ã«å€é¡ã®æè³ãè¡ã£ãŠããŸããã
æ©èœãã©ãã§ãæ©èœïŒ
ççŽã«èšã£ãŠãäžéšã®ãã©ãããã©ãŒã ã§OpenGLã䜿çšããã®ã¯é£ããå ŽåããããŸãã ãããã®å°é£ã®äž»ãªçç±ã®1ã€ã¯ããšã³ããªãã€ã³ãã®ã¢ãã¬ã¹ãããã«ãæã§ã¯ãªãå®è¡æã«åçã«å²ãåœãŠãå¿ èŠãããããšã§ãïŒãªã³ã«ãŒããããå®è¡ã§ããå ŽåïŒã ããšãã°ãMicrosoft Windowsã§ã¯ãããŒãžã§ã³1.1以éã®OpenGLã§å°å ¥ãããé¢æ°ã®ã¢ãã¬ã¹ãå®è¡æã«å²ãåœãŠãå¿ èŠããããŸãã ã€ãŸããææ°ã®OpenGLã§äœ¿çšãããã»ãŒãã¹ãŠã®é¢æ°ã«å¯ŸããŠå®è¡ããå¿ èŠããããŸãã
ãããã®åé¡ã解決ããããã«ãQtã«ã¯QOpenGLContext :: GetProcAddressïŒïŒããã³QOpenGLFunctionsãšãã䟿å©ãªãŠãŒãã£ãªãã£ãããã€ãçšæãããŠããŸãã åè ã¯ãšã³ããªãã€ã³ããæåã§å²ãåœãŠãããã«äœ¿çšã§ããŸãããåŸè ã¯ãã®ã¡ãœãããOpenGL 2ããã³OpenGL ES 2é¢æ°ã®å ±éãµãã»ããã衚瀺ããã¯ã©ã¹ã§ãã ãããã®ãã«ããŒã¯å¯èœãªéãåªããŠããŸãã åé¡ã¯ãæäŸãããŠããã¡ãœããïŒOpenGL 2ããã³OpenGL ES 2ã®ãµãã»ããïŒã§QOpenGLFunctionsãå¶éãããŠããããšã§ãã ãšã³ããªãã€ã³ãã®æåå²ãåœãŠã¯éåžžã«é¢åãªäœæ¥ã§ããããšã©ãŒãçºçããŸãã ãŸãã¯ããããã®åé¡ã解決ããGlewãGLeeãªã©ã®ãµãŒãããŒãã£ã©ã€ãã©ãªã®é¢æ°ã䜿çšã§ããŸãã 確ãã«ããããã®ãœãªã¥ãŒã·ã§ã³ã¯ãå¿ èŠãªæ©èœãšQtã§ã®äŸ¿å©ãªäœæ¥ïŒããšãã°ãããããŒã®é åºãèæ ®ããïŒãååŸããããã®åé¡ãåŒãèµ·ãããŸãã
QOpenGLContext :: versionFunctionsïŒïŒã䜿çšããŠãã ããïŒ ããã¯æ§ãããªå°ããªæ©èœã§ããOpenGLé¢æ°ã®ã¢ãã¬ã¹ïŒãšã³ããªãã€ã³ãïŒã®ããŠãŒããã¢ãã¬ã€ã:)ãã®é¢æ°ã¯ãå¿ èŠãªããŒãžã§ã³ãšOpenGLãããã¡ã€ã«ã§ããªããžã§ã¯ãïŒåé¢æ°ã®ã¡ãœããïŒãžã®ãã€ã³ã¿ãŒãååŸããããã«äœ¿çšã§ããŸãã ç°¡åãªäŸãèŠãŠã¿ãŸãããã ã¬ã³ããªã³ã°ããQWindowã®ãµãã¯ã©ã¹ããããšããŸãããã OpenGL 4.3ã³ã¢ãããã¡ã€ã«ãäœæããæäŸããããã¹ãŠã®æ©èœã䜿çšããŸãã ãšãŠãç°¡åã§ãïŒ
Window::Window(QScreen * screen) : QWindow(screen) { // Qt OpenGL setSurfaceType(OpenGLSurface); // - QSurfaceFormat format; format.setDepthBufferSize(24); format.setMajorVersion(4); format.setMinorVersion(3); format.setSamples(4); format.setProfile(QSurfaceFormat::CoreProfile); setFormat(format); create(); // OpenGL m_context = new QOpenGLContext; m_context->setFormat(format); m_context->create(); // m_context->makeCurrent(this); // // m_funcs : QOpenGLFunctions_4_3_Core * m_funcs m_funcs = m_context->versionFunctions(); if (!m_funcs) { qWarning("Could not obtain OpenGL versions object"); exit(1); } m_funcs->initializeOpenGLFunctions(); }
ããããã¯ã QOpenGLFunctions_4_3_Coreãªããžã§ã¯ãã®ã¡ã³ããŒé¢æ°ã䜿çšã§ããŸãã äŸïŒ
// Vertex Attrib Divisor // instanced rendering // ( OpenGL 3.3) m_funcs->glVertexAttribDivisor(pointLocation, 1); // compute shader // ( OpenGL 4.3) m_funcs->glDispatchCompute(512 / 16, 512 / 16, 1);
ãã®ã³ãŒãã¯äœã«ã€ããŠã§ããïŒ
ã芧ã®ããã«ãOpenGLã®ãã¹ãŠã®æ©èœããµããŒãããŠãããã©ââãããã©ãŒã ã§äœ¿çšããã®ã¯ç°¡åã§ãã ããã«ã QOpenGLContext ã QOpenGLFunctions_4_3_Coreãããã³åæ§ã®ã¯ã©ã¹ã¯ãæå¹ãªé¢æ°ãã€ã³ã¿ãŒãå«ãããã¯ãšã³ããé åžããããšã«ãããé¢æ°ã®äœ¿çšãæå°éã«æããŸãã ãŸãããã®ã¢ãããŒãã¯ããã©ãããã©ãŒã åºæã®é¢æ°ã¢ãã¬ã¹ãèªåçã«åŠçããŸãïŒããšãã°ãè€æ°ã®ã¹ã¬ãããšã³ã³ããã¹ããŸãã¯è€æ°ã®GPUã䜿çšããå ŽåïŒã ãããã®ã¯ã©ã¹ã®ã³ãŒãã¯è£å©ãŠãŒãã£ãªãã£ã䜿çšããŠèªåçã«çæããããããOpenGLã®æ°ããããŒãžã§ã³ããªãªãŒã¹ããããšãã«æŽæ°ããã®ã¯éåžžã«ç°¡åã§ãã
OpenGLæ¡åŒµ
OpenGLã«ã¯äººæ°ã®ããæ¡åŒµãšã³ãžã³ãããããã³ããŒã¯æ°ããæ©èœãŸãã¯å®éšçãªæ©èœãšAPIãå°å ¥ããŠãããããæçšã§ããèããããŠãããã©ããã確èªã§ããŸãã æ®å¿µãªãããæ¡åŒµæ©èœãæ°ããé¢æ°ãå°å ¥ããå Žåã¯ãã¢ãã¬ã¹ãšä»ã®OpenGLé¢æ°ïŒäžèšã®ããã«ïŒãæå®ããå¿ èŠããããŸãã
OpenGLæ¡åŒµæ©èœã䜿çšããã«ã¯ã2ã€ã®æ®µéãçµãå¿ èŠããããŸãã Qtã¯äž¡æ¹ã®ã¹ãããã§åœ¹ç«ã¡ãŸãïŒ
ã¹ããŒãž1ïŒ
çŸåšã®å®è£ ãå¿ èŠãªæ¡åŒµæ©èœããµããŒãããŠããããšã確èªããŸãã æ¡åŒµæ©èœãæ°ããAPIãå°å ¥ããå Žåããšã³ããªãã€ã³ããæå®ããŸãã æ¡åŒµæ©èœããµããŒããããŠããããšã確èªããã«ã¯ã QOpenGLContext :: hasExtensionïŒïŒã¡ãœããã䜿çšããå¿ èŠããããŸãã ããã«ããµããŒããããŠããæ¡åŒµæ©èœã®å®å šãªãªã¹ããååŸããã«ã¯ã OpenGLContext :: extensionsïŒïŒã䜿çšã§ããŸãã // QList extensions = m_context->extensions().toList(); std::sort(extensions); qDebug() << "Supported extensions (" << extensions.count() <<")"; foreach (const QByteArray &extension, extensions) { qDebug() << " " << extension; }
ã¹ããŒãž2ïŒ
2çªç®ã®æ®µéã§ã¯ãå€ãå人ã§ããQOpenGLContext :: GetProcAddressïŒïŒã¡ãœããã䜿çšããå¿ èŠããããŸãã Qt 5.1ã§ã¯ã QtOpenGLExtensionsã¢ãžã¥ãŒã«ããããæ åœããŸãã ãã®ã¢ãžã¥ãŒã«ã¯éçã©ã€ãã©ãªã§ããã Khronosã¬ãžã¹ããªã® OpenGLæ¡åŒµïŒæ°ããAPIãå°å ¥ïŒããšã«ã¯ã©ã¹ãå«ãŸããŠããŸã ã OpenGLæ¡åŒµæ©èœã䜿çšããã«ã¯ã次ã®ãããªã³ãŒãã䜿çšããŸãã // if (!m_context->hasExtension(QByteArrayLiteral("GL_ARB_instanced_arrays")) { qFatal("GL_ARB_instanced_arrays is not supported"); } // QOpenGLExtension_ARB_instanced_arrays * m_instanceFuncs = new QOpenGLExtension_ARB_instanced_arrays(); m_instanceFuncs->initializeOpenGLFunctions(); // m_instanceFuncs->glVertexAttribDivisorARB(pointLocation, 1);
ã³ã¢OpenGLæ©èœãšåæ§ã«ãæ¡åŒµæ©èœã®ã³ãŒããçæããããããå°æ¥ã®æŽæ°ã容æã§ãã
ããŒã2
é ç¹é åãªããžã§ã¯ã
Qtã«ã¯ã é ç¹ããšã®å±æ§ããŒã¿ãèŠçŽ ã€ã³ããã¯ã¹ãããã¡ãŒãªã©ãããŸããŸãªã¿ã€ãã®OpenGLãããã¡ãŒãªããžã§ã¯ãã®ç®¡çã«åœ¹ç«ã€QOpenGLBuffer ïŒä»¥åã¯QGLBuffer ïŒããããŸã ã OpenGLã«ã¯ã é ç¹ãããã¡ãŒãªããžã§ã¯ãïŒVBOïŒã»ãããæ¯æŽãããªããžã§ã¯ãé ç¹é åïŒVAOïŒãšåŒã°ããã¿ã€ãã®ç¹å¥ãªã³ã³ãããŒããããŸãã
KDABã¯ã QOpenGLVertexArrayObjectã¯ã©ã¹ã§è€æ°ã®VAOãã«ãã»ã«åããQt 5.1ã®ã³ãŒããè¿œå ããŸããã ãã®ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ããã€ã³ããããšãåŸã§èšå®ããé ç¹ä»æ§ã®ç¶æ ããèšæ¶ãããããOpenGLã«æ瀺ããŸãã VAOèªäœãåæ¥ç¶ããã ãã§ãåŸã§å¿ èŠãªç¶æ ä»æ§ãéåžžã«è¿ éã«åŸ©å ã§ããŸãã ããã«ãããã¬ã³ããªã³ã°é¢æ°ã§ã¬ã³ããªã³ã°ãããããªããžã§ã¯ããã®é ç¹ç¶æ ãéåžžã«ãã°ããåãæ¿ããããšãã§ããŸãã
翻蚳è
ã®ã¡ã¢
ç§ã®æèŠã§ã¯ãããã€ã³ããã®ä»£ããã«ããããããéçºè
ãã«ãšã£ãŠãã銎æã¿ã®ããããã·ã¢èªãåè©ããã€ã³ããã䜿çšããæ¹ãé©åã§ãã
void Scene::initialize() { // QOpenGLContext // m_shaderProgram QOpenGLShaderProgram // VAO m_vao1 = new QOpenGLVertexArrayObject( this ); m_vao1->create(); m_vao1->bind(); // VBO IBO ( QOpenGLBuffer , // , ..). "" // VAO m_positionBuffer.create(); m_positionBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw); m_positionBuffer.bind(); m_positionBuffer.allocate(positionData, vertexCount * 3 * sizeof(float)); m_shaderProgram.enableAttributeArray("vertexPosition"); m_shaderProgram.setAttributeBuffer ("vertexPosition", GL_FLOAT, 0, 3); m_colorBuffer.create(); m_colorBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); m_colorBuffer.bind(); m_colorBuffer.allocate(colorData, vertexCount * 3 * sizeof(float)); m_shaderProgram.enableAttributeArray("vertexColor"); m_shaderProgram.setAttributeBuffer ("vertexColor", GL_FLOAT, 0, 3); // , , // , ... ... // VAO m_vao2 = new QOpenGLVertexArrayObject(this); m_vao2->create(); m_vao2->bind(); // VBO IBO ... // " " (. ) m_skyBoxVAO = new QOpenGLVertexArrayObject(this); ... } void Scene::render() { // m_funcs->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // m_phongShaderProgram->bind(); ... // m_vao1->bind(); m_funcs->glDrawElements(...); // m_vao2->bind(); m_funcs->glDrawElements(...); // / .. // m_skyboxShaderProgram->bind(); ... m_skyboxVAO->bind(); m_funcs->glDrawElements(...); ... }
翻蚳è
ã®ã¡ã¢
ãããããšç¹°ãè¿ããã¯ãæ瀺ãç¹°ãè¿ãããã®ç®èãªã¡ã¿ãã¡ãŒã§ãã ããã¯ãã»ãšãã©ã®ãã©ã³ãã®ã·ã£ã³ããŒã®ããã±ãŒãžã«ç€ºãããŠãããã¬ãŒãºãwashãããããç¹°ãè¿ããã«ç±æ¥ããŠããŸãã
VAOã¯OpenGL 3ããå°å ¥ãããŸããããCore Profileãåãã3.1ããå€ãOpenGLããŒãžã§ã³ã«ã¯å¿ é ã§ãã ããã«ãVAOã¯ãããããGL_ARB_vertex_array_objectãŸãã¯GL_OES_vertex_array_objectæ¡åŒµãšããŠOpenGL 2ããã³OpenGL ES 2ã§å©çšã§ããŸãã QOpenGLVertexArrayObjectã¯ã©ã¹ã¯ãå¿ èŠã«å¿ããŠäž»ãªæ©èœã䜿çšããïŒå¯èœãªå ŽåïŒããæ¡åŒµæ©èœïŒããå ŽåïŒãåç §ããŸãã
VAOã䜿çšãããšãèŠèŠåã³ãŒããå€§å¹ ã«ç°¡çŽ åãããçç£æ§ãåäžããŸãã OpenGLãã©ã€ããŒã¯ãããå€ãã®ãããã¡ãŒæäœãå®è¡ããå Žåãããæ€èšŒãã§ãã¯ãå°ãªãããŸãã
ããŒã3,4,5è¿æ¥å ¬é... PSïŒå€§ããªãªã¯ãšã¹ãããã¹ãŠã®æäœçããã³ææ³çãªèª€ããããã³ç¿»èš³ã®äžæ£ç¢ºãã¯ãLANçµç±ã§å ±åããå¿ èŠããããŸãã ããããå©çšå¯èœã«ãªã£ããããã¹ãŠãæ¯é ããŸãã