{"id":1117,"date":"2014-05-22T18:33:30","date_gmt":"2014-05-22T11:33:30","guid":{"rendered":"http:\/\/blog.bebensiganteng.com\/?p=1117"},"modified":"2016-03-14T08:19:49","modified_gmt":"2016-03-14T08:19:49","slug":"basic-boilerplate-opengl-es-cocos2d-x","status":"publish","type":"post","link":"https:\/\/rahmat-hidayat.com\/?p=1117","title":{"rendered":"OpenGL ES 2.0 in Cocos2d-x"},"content":{"rendered":"<p>Long story short, establishing OpenGL ES 2.0 is slightly different than <a href=\"http:\/\/labs.bebensiganteng.com\/html5\/framebufferobjects\/\" title=\"http:\/\/labs.bebensiganteng.com\/html5\/framebufferobjects\/\" target=\"_blank\">WebGL<\/a>, but the basic principle is similar.<\/p>\n<p><a href=\"http:\/\/www.cocos2d-x.org\/\" title=\"http:\/\/www.cocos2d-x.org\/\" target=\"_blank\">Cocos2d-x<\/a> provides you with a few ..uh, inconvenient wrappers.. that can help you started with custom shaders but if you don&#8217;t have the knowledge in everything that is OpenGL it can get a bit hectic, plus it&#8217;s hard to find a good reference.<\/p>\n<p>OpenGL is a gigantic topic so I&#8217;ll explain just the basic parts (plus I&#8217;m not an expert as well) so hopefully the below will helps you a bit.<\/p>\n<p>Add Vertex Shader (triangle.vsh)<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nattribute vec4 a_position;\r\n\r\nvoid main(void) {\r\n    gl_Position = a_position;\r\n}\r\n<\/pre>\n<p>and Fragment Shader (triangle.fsh)<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid main(void) {\r\n    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\r\n}\r\n<\/pre>\n<p>Add them to the compile resource list, like so<br \/>\n<img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/i.imgur.com\/Kdfeb25.gif\" width=\"425\" height=\"296\" alt=\"How to\" class=\"alignnone\" \/><\/p>\n<p>Do some OpenGL ES<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid HelloWorld::init() {\r\n\r\n    \/\/ Creates a program object\r\n    CCGLProgram *program = new CCGLProgram();\r\n\r\n    \/\/ A (check below)\r\n    bool loaded = program-&gt;initWithVertexShaderFilename(&quot;triangle.vsh&quot;,&quot;triangle.fsh&quot;);\r\n\r\n    \/\/ Check if everything is ok\r\n    if (!loaded) {\r\n        CCLOG(&quot;oh, god no&quot;);\r\n    }\r\n\r\n\r\n    \/\/ B (check below)\r\n    program-&gt;addAttribute(kCCAttributeNamePosition, 0);\r\n\r\n    \r\n    \/\/ link the programs\r\n    program-&gt;link();\r\n    \r\n    \/\/ C (check below)\r\n    program-&gt;updateUniforms();\r\n\r\n    \/\/ D (check below)\r\n    CCLOG(&quot;Program Log %s&quot;, program-&gt;programLog());\r\n\r\n    \/\/ Set the program to the current node\r\n    this-&gt;setShaderProgram(program);\r\n\r\n    \/\/ Release it from the memory pool\r\n    program-&gt;release();\r\n\r\n    \/\/ Set the clear color, not required actually.\r\n    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);\r\n\r\n}\r\n\r\nvoid HelloWorld::draw() {\r\n    \r\n    \/\/ Clear the color Buffer\r\n    glClear(GL_COLOR_BUFFER_BIT);\r\n    \r\n    \/\/ E (check below)\r\n    CC_NODE_DRAW_SETUP();\r\n    \r\n    \/\/ Draw the triangle\r\n    GLfloat vVertices[9] = {\r\n        0.0f, 0.5f, 0.0f,\r\n        -0.5f, -0.5f, 0.0f,\r\n        0.5f, -0.5f, 0.0f\r\n    };\r\n    \r\n    \/\/ F (check below)\r\n    ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );\r\n    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, vVertices);\r\n    glDrawArrays(GL_TRIANGLES, 0, 3);\r\n    \r\n    \/\/ Not required, only for stats\r\n    CC_INCREMENT_GL_DRAWS(1);\r\n    \r\n}\r\n<\/pre>\n<p>These are the necessary elements that an OpenGL needs, so let&#8217;s have a look;<\/p>\n<h5>A<\/h5>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nbool loaded = program-&gt;initWithVertexShaderFilename(&quot;triangle.vsh&quot;,&quot;triangle.fsh&quot;);\r\n<\/pre>\n<p><i>initWithVertexShaderFilename<\/i> as the name suggested, will loads all external files, compile, as well as attaching all the shaders into the program. <\/p>\n<h5>B<\/h5>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nprogram-&gt;addAttribute(kCCAttributeNamePosition, 0);\r\n<\/pre>\n<p><i>addAttribute<\/i> simply adds the <i>attribute vec4 a_position;<\/i> to 0, I&#8217;m not sure why Cocos2d-x have to make a function for it, because the actual call is just this;<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nglBindAttribLocation(programObject, index, attributeName);\r\n<\/pre>\n<h5>C<\/h5>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nprogram-&gt;updateUniforms();\r\n<\/pre>\n<p>During the compilation (Step A) Cocos2d-x will bind their own uniforms into your shaders.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n&quot;uniform mat4 CC_PMatrix;n&quot;\r\n&quot;uniform mat4 CC_MVMatrix;n&quot;\r\n&quot;uniform mat4 CC_MVPMatrix;n&quot;\r\n&quot;uniform vec4 CC_Time;n&quot;\r\n&quot;uniform vec4 CC_SinTime;n&quot;\r\n&quot;uniform vec4 CC_CosTime;n&quot;\r\n&quot;uniform vec4 CC_Random01;n&quot;\r\n&quot;\/\/CC INCLUDES ENDnn&quot;,\r\nsource,\r\n<\/pre>\n<p>Notice the end is <i>source<\/i>, which is our custom shaders.<\/p>\n<h5>D<\/h5>\n<p>Checking every step is absolutely necessary in OpenGL, since most of the times an error will not be reported, it will rather silently present you with a blank screen for you to stare into.<\/p>\n<h5>E<\/h5>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nCC_NODE_DRAW_SETUP();\r\n<\/pre>\n<p>Gets the program, and sets the built-in uniforms value in step C.<\/p>\n<h5>F<\/h5>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );\r\nglVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, vVertices);\r\nglDrawArrays(GL_TRIANGLES, 0, 3);\r\n<\/pre>\n<p>What <i>glVertexAttribPointer<\/i> does it retrieves the vertices from the buffer objects, so we need to tell it how to process those data, in order to understand it have a look at this <a href=\"http:\/\/blog.tojicode.com\/2011\/05\/interleaved-array-basics.html\" title=\"http:\/\/blog.tojicode.com\/2011\/05\/interleaved-array-basics.html\" target=\"_blank\">interleaved array basics<\/a> explanation. <\/p>\n<p><i>glDrawArrays(GL_TRIANGLES, 0, 3);<\/i> draws the primitives, there are 3 types of primitives which are Triangle, Lines, and Points, each one has its own types, again explaining those things in detail can have your mind tangled after a while, but in a nutshell GL_TRIANGLES simply means drawing 1 triangle by 3 given vertex (n\/3).<\/p>\n<p><i>ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );<\/i> basically just enables the Vertex attribute array, although why does it need to be defined explicitly is a bit puzzling.<\/p>\n<p>And here&#8217;s the result<br \/>\n<img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/i.imgur.com\/fFMpjLE.jpg\" width=\"425\" height=\"267\" alt=\"Result\" class=\"alignnone\" \/><\/p>\n<p>Not too exciting :p but you can plug in your own shaders now.<\/p>\n<h5>Resources<\/h5>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=6-9XFm7XAT8\" title=\"https:\/\/www.youtube.com\/watch?v=6-9XFm7XAT8\" target=\"_blank\">SIGGRAPH University : &#8220;An Introduction to OpenGL Programming&#8221;<\/a><br \/>\n<a href=\"http:\/\/www.amazon.com\/OpenGL-ES-2-0-Programming-Guide\/dp\/0321502795\" title=\"http:\/\/www.amazon.com\/OpenGL-ES-2-0-Programming-Guide\/dp\/0321502795\" target=\"_blank\">OpenGL ES 2.0 programming guide<\/a><br \/>\n<a href=\"http:\/\/blog.db-in.com\/all-about-opengl-es-2-x-part-1\/\" title=\"All about OpenGL ES 2.x\" target=\"_blank\">http:\/\/blog.db-in.com\/all-about-opengl-es-2-x-part-1\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Long story short, establishing OpenGL ES 2.0 is slightly different than WebGL, but the basic principle is similar. Cocos2d-x provides you with a few ..uh, inconvenient wrappers.. that can help you started with custom shaders but if you don&#8217;t have the knowledge in everything that is OpenGL it can get a bit hectic, plus it&#8217;s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[16,18,27,45,57],"tags":[80,85,101,124],"_links":{"self":[{"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=\/wp\/v2\/posts\/1117"}],"collection":[{"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1117"}],"version-history":[{"count":1,"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=\/wp\/v2\/posts\/1117\/revisions"}],"predecessor-version":[{"id":1634,"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=\/wp\/v2\/posts\/1117\/revisions\/1634"}],"wp:attachment":[{"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1117"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1117"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rahmat-hidayat.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1117"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}