{"id":335,"date":"2021-11-29T19:12:59","date_gmt":"2021-11-29T19:12:59","guid":{"rendered":"https:\/\/writingagame.com\/?p=335"},"modified":"2022-01-13T18:02:21","modified_gmt":"2022-01-13T18:02:21","slug":"chapter-4-printf-in-opengl-es","status":"publish","type":"post","link":"https:\/\/writingagame.com\/index.php\/2021\/11\/29\/chapter-4-printf-in-opengl-es\/","title":{"rendered":"Chapter 4. Printf in OpenGL ES"},"content":{"rendered":"\n<p>Now, having OpenGL ES projects for 2 different platforms, we can see what is common and what is different.<\/p>\n\n\n\n<p>Common is generic structure: Creating GL context, initializing data, main loop with frames rendering, exit. GL calls (Thank God!) look similar too. The difference is in program and GL initialization, in GL-related includes (gl\/egl on Android and glfw\/glad in Windows). Events and input handling are different as well.<\/p>\n\n\n\n<p>Well, let\u2019s encapsulate platform-specific stuff in 2 separate sets (one for PC and another one for Android).<\/p>\n\n\n\n<p>We will start here from printf-alike function, which is essential for development, and obviously will require 2 different implementations for Windows and for Android. We&#8217;ll start in<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Windows:<\/h2>\n\n\n\n<ol class=\"wp-block-list\"><li>Start Visual Studio. Open <em>C:\\CPP\\a999hello\\p_windows\\p_windows.sln<\/em><\/li><\/ol>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>2. Add a placeholder: right-click on \u201c<em style=\"font-size: revert;\">p_windows<\/em> \u201d project <em>-&gt; Add -&gt; New <strong>Filter<\/strong><\/em><\/p>\n\n\n\n<p>Name &#8211; <strong>xPlatform<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>3. Physically we will keep Windows-specific files in  <em>C:\\CPP\\p_windows<\/em>  folder. Need to inform Project about this new location:<\/p>\n\n\n\n<p>Right-click on \u201c<strong>p_windows<\/strong>\u201d project -&gt;&nbsp;<em>Properties<\/em>,<em> <strong>All configurations<\/strong>,&nbsp;<strong>Win32<\/strong>, Configuration properties -&gt; C++ -&gt; General<\/em> -&gt;&nbsp;<em>Additional Include Directories -&gt; Edit<\/em>, add New Line, browse to<\/p>\n\n\n\n<p>C:\\CP<em>P\\p_windows<\/em><\/p>\n\n\n\n<p><strong>Select Folder, Ok, Apply, Ok<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>4. Under <em>xPlatform<\/em> add a header file: Right-click on  <em>xPlatform<\/em>, <em>Add -&gt; New Item<\/em>,<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>pick \u201cHeader File (.h)\u201d<\/li><li>name \u2013 <em>platform.h<\/em><\/li><li>Default location is not what we want, change it to <em>C:\\CPP\\p_windows<\/em><\/li><\/ul>\n\n\n\n<p>Then \u2013 <strong>Add<\/strong>.<\/p>\n\n\n\n<p>As was announced above, we will write a function that can print something on the screen (in our case \u2013 in Console window), something like printf.<\/p>\n\n\n\n<p>We can\u2019t use printf directly because:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It will work only on PC. Android will require different implementation.<\/li><li>It doesn\u2019t work at all on OpenGL screen.<\/li><li>We need it in Debug configuration only, it must be disabled in Release configuration.<\/li><\/ul>\n\n\n\n<p>I&#8217;ll call it <em>mylog()<\/em>. I want it to accept parameters the same way as printf (format string first and then \u2013 whatever).<\/p>\n\n\n\n<p>Also, it should do nothing in Release configuration. So, the code is:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#pragma once\n#include &quot;stdio.h&quot;\n#include &lt;stdarg.h&gt;\n\ninline void mylog(const char* _Format, ...) {\n#ifdef _DEBUG\n    va_list _ArgList;\n    va_start(_ArgList, _Format);\n    vprintf(_Format, _ArgList);\n    va_end(_ArgList);\n#endif\n};\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Now we are ready to try it. <\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>5. Open <em>main.cpp<\/em>.<\/p>\n\n\n\n<p>On the top, in &#8216;includes&#8217; section add a new line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"platform.h\"<\/code><\/pre>\n\n\n\n<p>In <em>main(void)<\/em> function, in the very beginning, right after \u201c{\u201c add a new line<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mylog(\" Hello %s !\\n\", \"Windows\");<\/code><\/pre>\n\n\n\n<p>Pick <strong>Debug <\/strong>configuration.<\/p>\n\n\n\n<p>Build and run (green arrow). Look at Console window:<\/p>\n\n\n\n<p><strong>Hello Windows !<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>6. Now we can remove \u201c#include &lt;stdio.h&gt;\u201d from <em>main.cpp<\/em> and change <em>error_callback()<\/em> from using printf to <em>mylog <\/em>(it was an only printf occurrence in main.cpp):<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\nstatic void error_callback(int error, const char* description)\n{\n    mylog(&quot;Error: %s\\n&quot;, description);\n}\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Build and run &#8211; good.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>Now &#8211; on <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Android:<\/h2>\n\n\n\n<p>On Android it will be a bit different. First \u2013 there is no Console window. Second \u2013 no \u201cwindows\u201d at all (in Windows sense). However, it has \u201cLogCat\u201d &#8211; Android\u2019s own mechanism for printing debug\/development messages.<\/p>\n\n\n\n<p>7. Close and re-start Visual Studio, open <em>C:\\CPP\\a999hello\\p_android\\p_android.sln<\/em>.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>8. Again, need to add a filter (virtual folder): right-click on <em>p_android.NativeActivity<\/em> project -&gt; <em>Add -&gt; New <strong>Filter<\/strong><\/em>.<\/p>\n\n\n\n<p>Same name, <strong>xPlatform<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>9. Under <em>xPlatform <\/em>create a header file: Right-click on <em>xPlatform<\/em>, <em>Add -&gt; New Item<\/em>,<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>pick \u201cHeader File (.h)\u201d<\/li><li>name \u2013 <em>platform.h<\/em><\/li><li>Change location to <em>C:\\CPP\\p_android\\<\/em><\/li><\/ul>\n\n\n\n<p>Then \u2013 <strong>Add<\/strong>.<\/p>\n\n\n\n<p>The code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#pragma once\n#include &lt;android\/log.h&gt;\n#include &quot;stdio.h&quot;\n\ninline void mylog(const char* _Format, ...) {\n#ifdef _DEBUG\n    char outStr&#91;1024];\n    va_list _ArgList;\n    va_start(_ArgList, _Format);\n    vsprintf(outStr, _Format, _ArgList);\n    __android_log_print(ANDROID_LOG_INFO, &quot;mylog&quot;, outStr, NULL);\n    va_end(_ArgList);\n#endif\n};\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>This code relies on <strong>_DEBUG<\/strong> constant, but it is missed in Android&#8217;s debug configuration.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>10. Open <em>p_android.NativeApplication<\/em> project properties, pick <em><strong>Debug <\/strong>configuration, ARM64,<\/em> <\/p>\n\n\n\n<p>go to <em>Configuration Properties -&gt; C\/C++ -&gt; Preprocessor<\/em>, open <em>Preprocessor Definitions -&gt; Edit<\/em>. If <strong>_DEBUG<\/strong> is missed &#8211; add it, then OK, Apply, Ok.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>11. Now open <em>main.cpp<\/em>.<\/p>\n\n\n\n<p>In #include section add a new line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"platform.h\"<\/code><\/pre>\n\n\n\n<p>In <em>android_main (\u2026)<\/em>, in the very beginning, right after \u201c{\u201c add a new line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mylog(\" Hello %s ! \\n\", \"Android\");<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>12. Again, we need to inform <em>p_android.NativeActivity<\/em> project where to look for <em>platform.h<\/em> header.<\/p>\n\n\n\n<p>Right-click on  <em>p_android.NativeActivity<\/em>  project -&gt;<em> Properties, <strong>All Configurations<\/strong>, ARM64<\/em>. Open <em>Configuration Properties -&gt; C\/C++ -&gt; General -&gt; Additional Include Directories -&gt; Edit<\/em>, Add new line, navigate to<\/p>\n\n\n\n<p><em>C:\\CPP\\p_android<\/em><\/p>\n\n\n\n<p>Select Folder, Ok, Apply, Ok.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>13. Turn on and <strong>unlock <\/strong>your Android device, plug it in with USB cable, allow USB Debugging.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>14. Build and run (green arrow). On Android side nothing changed, same green flashing screen, but now we can open <strong>LogCat<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p>15. On VS screen open <em>top menu -&gt; Tools -&gt; Android Tools -&gt; Logcat<\/em>.<\/p>\n\n\n\n<p>In &lt;Search Logcat&gt; field print \u201cmylog\u201d, Enter. What do we have here?:<\/p>\n\n\n\n<p><strong>Hello Android !<\/strong><\/p>\n\n\n\n<p> <em>VS top menu -&gt; Debug -&gt; Stop Debugging.<\/em> <\/p>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p class=\"mb-2\">Now, having OpenGL ES projects for 2 different platforms, we can see what is common and what is different. Common is generic structure: Creating GL context, initializing data, main loop with frames rendering, exit. GL calls (Thank God!) look similar too. The difference is in program and GL initialization, in GL-related includes (gl\/egl on Android [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-335","post","type-post","status-publish","format-standard","hentry","category-cross-platform-3d"],"_links":{"self":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/335","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/comments?post=335"}],"version-history":[{"count":19,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/335\/revisions"}],"predecessor-version":[{"id":1279,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/335\/revisions\/1279"}],"wp:attachment":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media?parent=335"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/categories?post=335"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/tags?post=335"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}