LearnOpenGL

Translation in progress of learnopengl.com.
git clone https://git.mtkn.jp/LearnOpenGL
Log | Files | Refs

Debugging.html (42030B)


      1 <!DOCTYPE html>
      2 <html lang="ja"> 
      3 <head>
      4     <meta charset="utf-8"/>
      5     <title>LearnOpenGL</title>
      6     <link rel="shortcut icon" type="image/ico" href="/favicon.ico"  />
      7 	<link rel="stylesheet" href="../static/style.css" />
      8 	<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"> </script>
      9 	<script src="/static/functions.js"></script>
     10 </head>
     11 <body>
     12 	<nav>
     13 <ol>
     14 	<li id="Introduction">
     15 		<a href="https://learnopengl.com/Introduction">はじめに</a>
     16 	</li>
     17 	<li id="Getting-started">
     18 		<span class="closed">入門</span>
     19 		<ol>
     20 			<li id="Getting-started/OpenGL">
     21 				<a href="https://learnopengl.com/Getting-started/OpenGL">OpenGL </a>
     22 			</li>
     23 			<li id="Getting-started/Creating-a-window">
     24 				<a href="https://learnopengl.com/Getting-started/Creating-a-window">ウィンドウの作成</a>
     25 			</li>
     26 			<li id="Getting-started/Hello-Window">
     27 				<a href="https://learnopengl.com/Getting-started/Hello-Window">最初のウィンドウ</a>
     28 			</li>
     29 			<li id="Getting-started/Hello-Triangle">
     30 				<a href="https://learnopengl.com/Getting-started/Hello-Triangle">最初の三角形</a>
     31 			</li>
     32 			<li id="Getting-started/Shaders">
     33 				<a href="https://learnopengl.com/Getting-started/Shaders">シェーダー</a>
     34 			</li>
     35 			<li id="Getting-started/Textures">
     36 				<a href="https://learnopengl.com/Getting-started/Textures">テクスチャ</a>
     37 			</li>
     38 			<li id="Getting-started/Transformations">
     39 				<a href="https://learnopengl.com/Getting-started/Transformations">座標変換</a>
     40 			</li>
     41 			<li id="Getting-started/Coordinate-Systems">
     42 				<a href="https://learnopengl.com/Getting-started/Coordinate-Systems">座標系</a>
     43 			</li>
     44 			<li id="Getting-started/Camera">
     45 				<a href="https://learnopengl.com/Getting-started/Camera">カメラ</a>
     46 			</li>
     47 			<li id="Getting-started/Review">
     48 				<a href="https://learnopengl.com/Getting-started/Review">まとめ</a>
     49 			</li>
     50 		</ol>
     51 	</li>
     52 	<li id="Lighting">
     53 		<span class="closed">Lighting </span>
     54 		<ol>
     55 			<li id="Lighting/Colors">
     56 				<a href="https://learnopengl.com/Lighting/Colors">Colors </a>
     57 			</li>
     58 			<li id="Lighting/Basic-Lighting">
     59 				<a href="https://learnopengl.com/Lighting/Basic-Lighting">Basic Lighting </a>
     60 			</li>
     61 			<li id="Lighting/Materials">
     62 				<a href="https://learnopengl.com/Lighting/Materials">Materials </a>
     63 			</li>
     64 			<li id="Lighting/Lighting-maps">
     65 				<a href="https://learnopengl.com/Lighting/Lighting-maps">Lighting maps </a>
     66 			</li>
     67 			<li id="Lighting/Light-casters">
     68 				<a href="https://learnopengl.com/Lighting/Light-casters">Light casters </a>
     69 			</li>
     70 			<li id="Lighting/Multiple-lights">
     71 				<a href="https://learnopengl.com/Lighting/Multiple-lights">Multiple lights </a>
     72 			</li>
     73 			<li id="Lighting/Review">
     74 				<a href="https://learnopengl.com/Lighting/Review">Review </a>
     75 			</li>
     76 		</ol>
     77 	</li>
     78 	<li id="Model-Loading">
     79 		<span class="closed">Model Loading </span>
     80 		<ol>
     81 			<li id="Model-Loading/Assimp">
     82 				<a href="https://learnopengl.com/Model-Loading/Assimp">Assimp </a>
     83 			</li>
     84 			<li id="Model-Loading/Mesh">
     85 				<a href="https://learnopengl.com/Model-Loading/Mesh">Mesh </a>
     86 			</li>
     87 			<li id="Model-Loading/Model">
     88 				<a href="https://learnopengl.com/Model-Loading/Model">Model </a>
     89 			</li>
     90 		</ol>
     91 	</li>
     92 	<li id="Advanced-OpenGL">
     93 		<span class="closed">Advanced OpenGL </span>
     94 		<ol>
     95 			<li id="Advanced-OpenGL/Depth-testing">
     96 				<a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing">Depth testing </a>
     97 			</li>
     98 			<li id="Advanced-OpenGL/Stencil-testing">
     99 				<a href="https://learnopengl.com/Advanced-OpenGL/Stencil-testing">Stencil testing </a>
    100 			</li>
    101 			<li id="Advanced-OpenGL/Blending">
    102 				<a href="https://learnopengl.com/Advanced-OpenGL/Blending">Blending </a>
    103 			</li>
    104 			<li id="Advanced-OpenGL/Face-culling">
    105 				<a href="https://learnopengl.cm/Advanced-OpenGL/Face-culling">Face culling </a>
    106 			</li>
    107 			<li id="Advanced-OpenGL/Framebuffers">
    108 				<a href="https://learnopengl.com/Advanced-OpenGL/Framebuffers">Framebuffers </a>
    109 			</li>
    110 			<li id="Advanced-OpenGL/Cubemaps">
    111 				<a href="https://learnopengl.com/Advanced-OpenGL/Cubemaps">Cubemaps </a>
    112 			</li>
    113 			<li id="Advanced-OpenGL/Advanced-Data">
    114 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-Data">Advanced Data </a>
    115 			</li>
    116 			<li id="Advanced-OpenGL/Advanced-GLSL">
    117 				<a href="https://learnopengl.com/Advanced-OpenGL/Advanced-GLSL">Advanced GLSL </a>
    118 			</li>
    119 			<li id="Advanced-OpenGL/Geometry-Shader">
    120 				<a href="https://learnopengl.com/Advanced-OpenGL/Geometry-Shader">Geometry Shader </a>
    121 			</li>
    122 			<li id="Advanced-OpenGL/Instancing">
    123 				<a href="https://learnopengl.com/Advanced-OpenGL/Instancing">Instancing </a>
    124 			</li>
    125 			<li id="Advanced-OpenGL/Anti-Aliasing">
    126 				<a href="https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing">Anti Aliasing </a>
    127 			</li>
    128 		</ol>
    129 	</li>
    130 	<li id="Advanced-Lighting">
    131 		<span class="closed">Advanced Lighting </span>
    132 		<ol>
    133 			<li id="Advanced-Lighting/Advanced-Lighting">
    134 				<a href="https://learnopengl.com/Advanced-Lighting/Advanced-Lighting">Advanced Lighting </a>
    135 			</li>
    136 			<li id="Advanced-Lighting/Gamma-Correction">
    137 				<a href="https://learnopengl.com/Advanced-Lighting/Gamma-Correction">Gamma Correction </a>
    138 			</li>
    139 			<li id="Advanced-Lighting/Shadows">
    140 				<span class="closed">Shadows </span>
    141 				<ol>
    142 					<li id="Advanced-Lighting/Shadows/Shadow-Mapping">
    143 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping">Shadow Mapping </a>
    144 					</li>
    145 					<li id="Advanced-Lighting/Shadows/Point-Shadows">
    146 						<a href="https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows">Point Shadows </a>
    147 					</li>
    148 				</ol>
    149 			</li>
    150 			<li id="Advanced-Lighting/Normal-Mapping">
    151 				<a href="https://learnopengl.com/Advanced-Lighting/Normal-Mapping">Normal Mapping </a>
    152 			</li>
    153 			<li id="Advanced-Lighting/Parallax-Mapping">
    154 				<a href="https://learnopengl.com/Advanced-Lighting/Parallax-Mapping">Parallax Mapping </a>
    155 			</li>
    156 			<li id="Advanced-Lighting/HDR">
    157 				<a href="https://learnopengl.com/Advanced-Lighting/HDR">HDR </a>
    158 			</li>
    159 			<li id="Advanced-Lighting/Bloom">
    160 				<a href="https://learnopengl.com/Advanced-Lighting/Bloom">Bloom </a>
    161 			</li>
    162 			<li id="Advanced-Lighting/Deferred-Shading">
    163 				<a href="https://learnopengl.com/Advanced-Lighting/Deferred-Shading">Deferred Shading </a>
    164 			</li>
    165 			<li id="Advanced-Lighting/SSAO">
    166 				<a href="https://learnopengl.com/Advanced-Lighting/SSAO">SSAO </a>
    167 			</li>
    168 		</ol>
    169 	</li>
    170 	<li id="PBR">
    171 		<span class="closed">PBR </span>
    172 		<ol>
    173 			<li id="PBR/Theory">
    174 				<a href="https://learnopengl.com/PBR/Theory">Theory </a>
    175 			</li>
    176 			<li id="PBR/Lighting">
    177 				<a href="https://learnopengl.com/PBR/Lighting">Lighting </a>
    178 			</li>
    179 			<li id="PBR/IBL">
    180 				<span class="closed">IBL </span>
    181 				<ol>
    182 					<li id="PBR/IBL/Diffuse-irradiance">
    183 						<a href="https://learnopengl.com/PBR/IBL/Diffuse-irradiance">Diffuse irradiance </a>
    184 					</li>
    185 					<li id="PBR/IBL/Specular-IBL">
    186 						<a href="https://learnopengl.com/PBR/IBL/Specular-IBL">Specular IBL </a>
    187 					</li>
    188 				</ol>
    189 			</li>
    190 		</ol>
    191 	</li>
    192 	<li id="In-Practice">
    193 		<span class="closed">In Practice </span>
    194 		<ol>
    195 			<li id="In-Practice/Debugging">
    196 				<a href="https://learnopengl.com/In-Practice/Debugging">Debugging </a>
    197 			</li>
    198 			<li id="In-Practice/Text-Rendering">
    199 				<a href="https://learnopengl.com/In-Practice/Text-Rendering">Text Rendering </a>
    200 			</li>
    201 			<li id="In-Practice/2D-Game">
    202 				<span class="closed">2D Game </span>
    203 				<ol>
    204 					<li id="In-Practice/2D-Game/Breakout">
    205 						<a href="https://learnopengl.com/In-Practice/2D-Game/Breakout">Breakout </a>
    206 					</li>
    207 					<li id="In-Practice/2D-Game/Setting-up">
    208 						<a href="https://learnopengl.com/In-Practice/2D-Game/Setting-up">Setting up </a>
    209 					</li>
    210 					<li id="In-Practice/2D-Game/Rendering-Sprites">
    211 						<a href="https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites">Rendering Sprites </a>
    212 					</li>
    213 					<li id="In-Practice/2D-Game/Levels">
    214 						<a href="https://learnopengl.com/In-Practice/2D-Game/Levels">Levels </a>
    215 					</li>
    216 					<li id="In-Practice/2D-Game/Collisions">
    217 						<span class="closed">Collisions </span>
    218 						<ol>
    219 							<li id="In-Practice/2D-Game/Collisions/Ball">
    220 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Ball">Ball </a>
    221 							</li>
    222 							<li id="In-Practice/2D-Game/Collisions/Collision-detection">
    223 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-detection">Collision detection </a>
    224 							</li>
    225 							<li id="In-Practice/2D-Game/Collisions/Collision-resolution">
    226 								<a href="https://learnopengl.com/In-Practice/2D-Game/Collisions/Collision-resolution">Collision resolution </a>
    227 							</li>
    228 						</ol>
    229 					</li>
    230 					<li id="In-Practice/2D-Game/Particles">
    231 						<a href="https://learnopengl.com/In-Practice/2D-Game/Particles">Particles </a>
    232 					</li>
    233 					<li id="In-Practice/2D-Game/Postprocessing">
    234 						<a href="https://learnopengl.com/In-Practice/2D-Game/Postprocessing">Postprocessing </a>
    235 					</li>
    236 					<li id="In-Practice/2D-Game/Powerups">
    237 						<a href="https://learnopengl.com/In-Practice/2D-Game/Powerups">Powerups </a>
    238 					</li>
    239 					<li id="In-Practice/2D-Game/Audio">
    240 						<a href="https://learnopengl.com/In-Practice/2D-Game/Audio">Audio </a>
    241 					</li>
    242 					<li id="In-Practice/2D-Game/Render-text">
    243 						<a href="https://learnopengl.com/In-Practice/2D-Game/Render-text">Render text </a>
    244 					</li>
    245 					<li id="In-Practice/2D-Game/Final-thoughts">
    246 						<a href="https://learnopengl.com/In-Practice/2D-Game/Final-thoughts">Final thoughts </a>
    247 					</li>
    248 				</ol>
    249 			</li>
    250 		</ol>
    251 	</li>
    252 	<li id="Guest-Articles">
    253 		<span class="closed">Guest Articles </span>
    254 		<ol>
    255 			<li id="Guest-Articles/How-to-publish">
    256 				<a href="https://learnopengl.com/Guest-Articles/How-to-publish">How to publish </a>
    257 			</li>
    258 			<li id="Guest-Articles/2020">
    259 				<span class="closed">2020 </span>
    260 				<ol>
    261 					<li id="Guest-Articles/2020/OIT">
    262 						<span class="closed">OIT </span>
    263 						<ol>
    264 							<li id="Guest-Articles/2020/OIT/Introduction">
    265 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Introduction">Introduction </a>
    266 							</li>
    267 							<li id="Guest-Articles/2020/OIT/Weighted-Blended">
    268 								<a href="https://learnopengl.com/Guest-Articles/2020/OIT/Weighted-Blended">Weighted Blended </a>
    269 							</li>
    270 						</ol>
    271 					</li>
    272 					<li id="Guest-Articles/2020/Skeletal-Animation">
    273 						<a href="https://learnopengl.com/Guest-Articles/2020/Skeletal-Animation">Skeletal Animation </a>
    274 					</li>
    275 				</ol>
    276 			</li>
    277 			<li id="Guest-Articles/2021">
    278 				<span class="closed">2021 </span>
    279 				<ol>
    280 					<li id="Guest-Articles/2021/CSM">
    281 						<a href="https://learnopengl.com/Guest-Articles/2021/CSM">CSM </a>
    282 					</li>
    283 					<li id="Guest-Articles/2021/Scene">
    284 						<span class="closed">Scene </span>
    285 						<ol>
    286 							<li id="Guest-Articles/2021/Scene/Scene-Graph">
    287 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Scene-Graph">Scene Graph </a>
    288 							</li>
    289 							<li id="Guest-Articles/2021/Scene/Frustum-Culling">
    290 								<a href="https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling">Frustum Culling </a>
    291 							</li>
    292 						</ol>
    293 					</li>
    294 					<li id="Guest-Articles/2021/Tessellation">
    295 						<span class="closed">Tessellation </span>
    296 						<ol>
    297 							<li id="Guest-Articles/2021/Tessellation/Height-map">
    298 								<a href="https://learnopengl.com/Guest-Articles/2021/Tessellation/Height-map">Height map </a>
    299 							</li>
    300 						</ol>
    301 					</li>
    302 				</ol>
    303 			</li>
    304 		</ol>
    305 	</li>
    306 	<li id="Code-repository">
    307 		<a href="https://learnopengl.com/Code-repository">Code repository </a>
    308 	</li>
    309 	<li id="Translations">
    310 		<a href="https://learnopengl.com/Translations">Translations </a>
    311 	</li>
    312 	<li id="About">
    313 		<a href="https://learnopengl.com/About">About </a>
    314 	</li>
    315 </ol>
    316 	</nav>
    317 	<main>
    318     <h1 id="content-title">Debugging</h1>
    319 <h1 id="content-url" style='display:none;'>In-Practice/Debugging</h1>
    320 <p>
    321   Graphics programming can be a lot of fun, but it can also be a large source of frustration whenever something isn't rendering just right, or perhaps not even rendering at all! Seeing as most of what we do involves manipulating pixels, it can be difficult to figure out the cause of error whenever something doesn't work the way it's supposed to. Debugging these kinds of <em>visual</em> errors is different than what you're used to when debugging errors on the CPU. We have no console to output text to, no breakpoints to set on GLSL code, and no way of easily checking the state of GPU execution.
    322 </p>
    323 
    324 <p>
    325   In this chapter we'll look into several techniques and tricks of debugging your OpenGL program. Debugging in OpenGL is not too difficult to do and getting a grasp of its techniques definitely pays out in the long run.
    326 </p>
    327 
    328 <h2>glGetError()</h2>
    329 <p>
    330   The moment you incorrectly use OpenGL (like configuring a buffer without first binding any) it will take notice and generate one or more user error flags behind the scenes. We can query these error flags using a function named <fun>glGetError</fun> that checks the error flag(s) set and returns an error value if OpenGL got misused:
    331 </p>
    332 
    333 <pre><code>
    334 GLenum glGetError();  
    335 </code></pre>
    336 
    337 <p>
    338   
    339   The moment <fun>glGetError</fun> is called, it returns either an error flag or no error at all. The error codes that <fun>glGetError</fun> can return are listed below:
    340 </p>
    341 
    342 <table>
    343   <tr>
    344     <th>Flag</th>
    345     <th>Code</th>
    346     <th>Description</th>
    347   </tr>
    348   <tr>
    349     <td><var>GL_NO_ERROR</var></td>
    350     <td>0</td>
    351     <td>No user error reported since the last call to <fun>glGetError</fun>.</td>
    352   </tr>  
    353   <tr>
    354     <td><var>GL_INVALID_ENUM</var></td>
    355     <td>1280</td>
    356     <td>Set when an enumeration parameter is not legal.</td>
    357   </tr>  
    358   <tr>
    359     <td><var>GL_INVALID_VALUE</var></td>
    360     <td>1281</td>
    361     <td>Set when a value parameter is not legal.</td>
    362   </tr>  
    363   <tr>
    364     <td><var>GL_INVALID_OPERATION</var></td>
    365     <td>1282</td>
    366     <td>Set when the state for a command is not legal for its given parameters.</td>
    367   </tr>  
    368   <tr>
    369     <td><var>GL_STACK_OVERFLOW</var></td>
    370     <td>1283</td>
    371     <td>Set when a stack pushing operation causes a stack overflow.</td>
    372   </tr>  
    373   <tr>
    374     <td><var>GL_STACK_UNDERFLOW</var></td>
    375     <td>1284</td>
    376     <td>Set when a stack popping operation occurs while the stack is at its lowest point.</td>
    377   </tr>  
    378   <tr>
    379     <td><var>GL_OUT_OF_MEMORY</var></td>
    380     <td>1285</td>
    381     <td>Set when a memory allocation operation cannot allocate (enough) memory.</td>
    382   </tr>  
    383   <tr>
    384     <td><var>GL_INVALID_FRAMEBUFFER_OPERATION</var></td>
    385     <td>1286</td>
    386     <td>Set when reading or writing to a framebuffer that is not complete.</td>
    387   </tr>  
    388 </table>
    389 
    390 <p>
    391   Within OpenGL's function documentation you can always find the error codes a function generates the moment it is incorrectly used. For instance, if you take a look at the documentation of <a href="http://docs.gl/gl3/glBindTextur%65" target="_blank"><function id='48'>glBindTexture</function></a> function, you can find all the user error codes it could generate under the <em>Errors</em> section.
    392 </p>
    393 
    394 <p>
    395   The moment an error flag is set, no other error flags will be reported. Furthermore, the moment <fun>glGetError</fun> is called it clears all error flags (or only one if on a distributed system, see note below). This means that if you call <fun>glGetError</fun> once at the end of each frame and it returns an error, you can't conclude this was the only error, and the source of the error could've been anywhere in the frame.
    396 </p>
    397 
    398 <note>
    399   Note that when OpenGL runs distributedly like frequently found on X11 systems, other user error codes can still be generated as long as they have different error codes. Calling <fun>glGetError</fun> then only resets one of the error code flags instead of all of them. Because of this, it is recommended to call <fun>glGetError</fun> inside a loop.
    400 </note>
    401 
    402 <pre><code>
    403 <function id='48'>glBindTexture</function>(GL_TEXTURE_2D, tex);
    404 std::cout &lt;&lt; glGetError() &lt;&lt; std::endl; // returns 0 (no error)
    405   
    406 <function id='52'>glTexImage2D</function>(GL_TEXTURE_3D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    407 std::cout &lt;&lt; glGetError() &lt;&lt; std::endl; // returns 1280 (invalid enum)
    408   
    409 <function id='50'>glGenTextures</function>(-5, textures);
    410 std::cout &lt;&lt; glGetError() &lt;&lt; std::endl; // returns 1281 (invalid value)
    411   
    412 std::cout &lt;&lt; glGetError() &lt;&lt; std::endl; // returns 0 (no error)
    413 </code></pre>
    414 
    415 <p>
    416   The great thing about <fun>glGetError</fun> is that it makes it relatively easy to pinpoint where any error may be and to validate the proper use of OpenGL. Let's say you get a black screen and you have no idea what's causing it: is the framebuffer not properly set? Did I forget to bind a texture? By calling <fun>glGetError</fun> all over your codebase, you can quickly catch the first place an OpenGL error starts showing up. 
    417 </p>
    418 
    419 <p>
    420   By default <fun>glGetError</fun> only prints error numbers, which isn't easy to understand unless you've memorized the error codes. It often makes sense to write a small helper function to easily print out the error strings together with where the error check function was called: 
    421 </p>
    422 
    423 <pre><code>
    424 GLenum glCheckError_(const char *file, int line)
    425 {
    426     GLenum errorCode;
    427     while ((errorCode = glGetError()) != GL_NO_ERROR)
    428     {
    429         std::string error;
    430         switch (errorCode)
    431         {
    432             case GL_INVALID_ENUM:                  error = "INVALID_ENUM"; break;
    433             case GL_INVALID_VALUE:                 error = "INVALID_VALUE"; break;
    434             case GL_INVALID_OPERATION:             error = "INVALID_OPERATION"; break;
    435             case GL_STACK_OVERFLOW:                error = "STACK_OVERFLOW"; break;
    436             case GL_STACK_UNDERFLOW:               error = "STACK_UNDERFLOW"; break;
    437             case GL_OUT_OF_MEMORY:                 error = "OUT_OF_MEMORY"; break;
    438             case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
    439         }
    440         std::cout &lt;&lt; error &lt;&lt; " | " &lt;&lt; file &lt;&lt; " (" &lt;&lt; line &lt;&lt; ")" &lt;&lt; std::endl;
    441     }
    442     return errorCode;
    443 }
    444 #define glCheckError() glCheckError_(__FILE__, __LINE__) 
    445 </code></pre>
    446 
    447 <p>
    448   In case you're unaware of what the preprocessor directives <code>__FILE__</code> and <code>__LINE__</code> are: these variables get replaced during compile time with the respective file and line they were compiled in. If we decide to stick a large number of these <fun>glCheckError</fun> calls in our codebase it's helpful to more precisely know which <fun>glCheckError</fun> call returned the error.
    449 </p>
    450 
    451 <pre><code>
    452 <function id='32'>glBindBuffer</function>(GL_VERTEX_ARRAY, vbo);
    453 glCheckError(); 
    454 </code></pre>
    455 
    456 <p>
    457   This will give us the following output:
    458 </p>
    459 
    460 <img src="/img/in-practice/debugging_glgeterror.png" alt="Output of glGetError in OpenGL debugging."/>
    461 
    462 <p>
    463   <fun>glGetError</fun> doesn't help you too much as the information it returns is rather simple, but it does often help you catch typos or quickly pinpoint where in your code things went wrong; a simple but effective tool in your debugging toolkit.
    464 </p>
    465 
    466 
    467 <h2>Debug output</h2>
    468 <p>
    469   A less common, but more useful tool than <fun>glCheckError</fun> is an OpenGL extension called <def>debug output</def> that became part of core OpenGL since version 4.3. With the debug output extension, OpenGL itself will directly send an error or warning message to the user with a lot more details compared to <fun>glCheckError</fun>. Not only does it provide more information, it can also help you catch errors exactly where they occur by intelligently using a debugger.
    470 </p>
    471 
    472 <note>
    473   Debug output is core since OpenGL version 4.3, which means you'll find this functionality on any machine that runs OpenGL 4.3 or higher. If they're not available, its functionality can be queried from the <code>ARB_debug_output</code> or <code>AMD_debug_output</code> extension. Note that OS X does not seem to support debug output functionality (as gathered online).
    474 </note>
    475 
    476 <p>
    477   In order to start using debug output we have to request a debug output context from OpenGL at our initialization process. This process varies based on whatever windowing system you use; here we will discuss setting it up on GLFW, but you can find info on other systems in the additional resources at the end of the chapter.
    478 </p>
    479 
    480 <h3>Debug output in GLFW</h3>
    481 <p>
    482   Requesting a debug context in GLFW is surprisingly easy as all we have to do is pass a hint to GLFW that we'd like to have a debug output context. We have to do this before we call <fun><function id='20'>glfwCreateWindow</function></fun>:
    483 </p>
    484 
    485 <pre><code>
    486 <function id='18'>glfwWindowHint</function>(GLFW_OPENGL_DEBUG_CONTEXT, true);  
    487 </code></pre>
    488 
    489 <p>
    490   Once we've then initialized GLFW, we should have a debug context if we're using OpenGL version 4.3 or higher. If not, we have to take our chances and hope the system is still able to request a debug context. Otherwise we have to request debug output using its OpenGL extension(s). 
    491 </p>
    492 
    493 <note>
    494   Using OpenGL in debug context can be significantly slower compared to a non-debug context, so when working on optimizations or releasing your application you want to remove GLFW's debug request hint.
    495 </note>
    496   
    497 <p>
    498   To check if we successfully initialized a debug context we can query OpenGL:
    499 </p>
    500 
    501 <pre><code>
    502 int flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
    503 if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
    504 {
    505     // initialize debug output 
    506 }
    507 </code></pre>
    508 
    509 <p>
    510   The way debug output works is that we pass OpenGL an error logging function callback (similar to GLFW's input callbacks) and in the callback function we are free to process the OpenGL error data as we see fit; in our case we'll be displaying useful error data to the console. Below is the callback function prototype that OpenGL expects for debug output:
    511 </p>
    512 
    513 <pre><code>
    514 void APIENTRY glDebugOutput(GLenum source, GLenum type, unsigned int id, GLenum severity, 
    515                             GLsizei length, const char *message, const void *userParam);
    516 </code></pre>
    517   
    518 <p>
    519   Given the large set of data we have at our exposal, we can create a useful error printing tool like below:
    520 </p>
    521 
    522 <pre><code>
    523 void APIENTRY glDebugOutput(GLenum source, 
    524                             GLenum type, 
    525                             unsigned int id, 
    526                             GLenum severity, 
    527                             GLsizei length, 
    528                             const char *message, 
    529                             const void *userParam)
    530 {
    531     // ignore non-significant error/warning codes
    532     if(id == 131169 || id == 131185 || id == 131218 || id == 131204) return; 
    533 
    534     std::cout &lt;&lt; "---------------" &lt;&lt; std::endl;
    535     std::cout &lt;&lt; "Debug message (" &lt;&lt; id &lt;&lt; "): " &lt;&lt;  message &lt;&lt; std::endl;
    536 
    537     switch (source)
    538     {
    539         case GL_DEBUG_SOURCE_API:             std::cout &lt;&lt; "Source: API"; break;
    540         case GL_DEBUG_SOURCE_WINDOW_SYSTEM:   std::cout &lt;&lt; "Source: Window System"; break;
    541         case GL_DEBUG_SOURCE_SHADER_COMPILER: std::cout &lt;&lt; "Source: Shader Compiler"; break;
    542         case GL_DEBUG_SOURCE_THIRD_PARTY:     std::cout &lt;&lt; "Source: Third Party"; break;
    543         case GL_DEBUG_SOURCE_APPLICATION:     std::cout &lt;&lt; "Source: Application"; break;
    544         case GL_DEBUG_SOURCE_OTHER:           std::cout &lt;&lt; "Source: Other"; break;
    545     } std::cout &lt;&lt; std::endl;
    546 
    547     switch (type)
    548     {
    549         case GL_DEBUG_TYPE_ERROR:               std::cout &lt;&lt; "Type: Error"; break;
    550         case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: std::cout &lt;&lt; "Type: Deprecated Behaviour"; break;
    551         case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:  std::cout &lt;&lt; "Type: Undefined Behaviour"; break; 
    552         case GL_DEBUG_TYPE_PORTABILITY:         std::cout &lt;&lt; "Type: Portability"; break;
    553         case GL_DEBUG_TYPE_PERFORMANCE:         std::cout &lt;&lt; "Type: Performance"; break;
    554         case GL_DEBUG_TYPE_MARKER:              std::cout &lt;&lt; "Type: Marker"; break;
    555         case GL_DEBUG_TYPE_PUSH_GROUP:          std::cout &lt;&lt; "Type: Push Group"; break;
    556         case GL_DEBUG_TYPE_POP_GROUP:           std::cout &lt;&lt; "Type: Pop Group"; break;
    557         case GL_DEBUG_TYPE_OTHER:               std::cout &lt;&lt; "Type: Other"; break;
    558     } std::cout &lt;&lt; std::endl;
    559     
    560     switch (severity)
    561     {
    562         case GL_DEBUG_SEVERITY_HIGH:         std::cout &lt;&lt; "Severity: high"; break;
    563         case GL_DEBUG_SEVERITY_MEDIUM:       std::cout &lt;&lt; "Severity: medium"; break;
    564         case GL_DEBUG_SEVERITY_LOW:          std::cout &lt;&lt; "Severity: low"; break;
    565         case GL_DEBUG_SEVERITY_NOTIFICATION: std::cout &lt;&lt; "Severity: notification"; break;
    566     } std::cout &lt;&lt; std::endl;
    567     std::cout &lt;&lt; std::endl;
    568 }
    569 </code></pre>
    570 
    571 <p>
    572   Whenever debug output detects an OpenGL error, it will call this callback function and we'll be able to print out a large deal of information regarding the OpenGL error. Note that we ignore a few error codes that tend to not really display anything useful (like <code>131185</code> in NVidia drivers that tells us a buffer was successfully created).
    573 </p>
    574 
    575 <p>
    576   Now that we have the callback function it's time to initialize debug output:
    577 </p>
    578 
    579 <pre><code>
    580 if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
    581 {
    582     <function id='60'>glEnable</function>(GL_DEBUG_OUTPUT);
    583     <function id='60'>glEnable</function>(GL_DEBUG_OUTPUT_SYNCHRONOUS); 
    584     glDebugMessageCallback(glDebugOutput, nullptr);
    585     glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
    586 } 
    587 </code></pre>
    588 
    589 <p>
    590   Here we tell OpenGL to enable debug output. The <code><function id='60'>glEnable</function>(GL_DEBUG_SYNCRHONOUS)</code> call tells OpenGL to directly call the callback function the moment an error occurred. 
    591 </p>
    592 
    593 <h3>Filter debug output</h3>
    594 <p>
    595   With <fun>glDebugMessageControl</fun> you can potentially filter the type(s) of errors you'd like to receive a message from. In our case we decided to not filter on any of the sources, types, or severity rates. If we wanted to only show messages from the OpenGL API, that are errors, and have a high severity, we'd configure it as follows: 
    596 </p>
    597 
    598 <pre><code>
    599 glDebugMessageControl(GL_DEBUG_SOURCE_API, 
    600                       GL_DEBUG_TYPE_ERROR, 
    601                       GL_DEBUG_SEVERITY_HIGH,
    602                       0, nullptr, GL_TRUE); 
    603 </code></pre>
    604 
    605 <p>
    606   Given our configuration, and assuming you have a context that supports debug output, every incorrect OpenGL command will now print a large bundle of useful data:
    607 </p>
    608 
    609 <img src="/img/in-practice/debugging_debug_output.png" alt="Output of OpenGL debug output on a text console."/>
    610   
    611 <h3>Backtracking the debug error source</h3>
    612 <p>
    613   Another great trick with debug output is that you can relatively easy figure out the exact line or call an error occurred. By setting a breakpoint in <fun>DebugOutput</fun> at a specific error type (or at the top of the function if you don't care), the debugger will catch the error thrown and you can move up the call stack to whatever function caused the message dispatch:
    614 </p>
    615   
    616   <img src="/img/in-practice/debugging_debug_output_breakpoint.png" alt="Setting a breaking and using the callstack in OpenGL to catch the line of an error with debug output."/>    
    617     
    618 <p>
    619   It requires some manual intervention, but if you roughly know what you're looking for it's incredibly useful to quickly determine which call causes an error.
    620 </p>
    621   
    622 <h3>Custom error output</h3>
    623 <p>
    624   Aside from reading messages, we can also push messages to the debug output system with <fun>glDebugMessageInsert</fun>:
    625 </p>
    626 
    627 <pre><code>
    628 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,                       
    629                      GL_DEBUG_SEVERITY_MEDIUM, -1, "error message here"); 
    630 </code></pre>
    631 
    632 <p>
    633   This is especially useful if you're hooking into other application or OpenGL code that makes use of a debug output context. Other developers can quickly figure out any <em>reported</em> bug that occurs in your custom OpenGL code.
    634 </p>
    635     
    636 <p>
    637   In summary, debug output (if you can use it) is incredibly useful for quickly catching errors and is well worth the effort in setting up as it saves considerable development time. You can find a source code example <a href="/code_viewer_gh.php?code=src/7.in_practice/1.debugging/debugging.cpp" target="_blank">here</a> with both <fun>glGetError</fun> and debug output context configured; see if you can fix all the errors.
    638 </p>
    639 
    640 <h2>Debugging shader output</h2>
    641 <p>
    642   When it comes to GLSL, we unfortunately don't have access to a function like <fun>glGetError</fun> nor the ability to step through the shader code. When you end up with a black screen or the completely wrong visuals, it's often difficult to figure out if something's wrong with the shader code. Yes, we have the compilation error reports that report syntax errors, but catching the semantic errors is another beast.
    643 </p>
    644 
    645 <p>
    646   One frequently used trick to figure out what is wrong with a shader is to evaluate all the relevant variables in a shader program by sending them directly to the fragment shader's output channel. By outputting shader variables directly to the output color channels, we can convey interesting information by inspecting the visual results. For instance, let's say we want to check if a model has correct normal vectors. We can pass them (either transformed or untransformed) from the vertex shader to the fragment shader where we'd then output the normals as follows:
    647 </p>
    648 
    649 <pre><code>
    650 #version 330 core
    651 out vec4 FragColor;
    652 in vec3 Normal;
    653 [...]
    654   
    655 void main()
    656 {
    657     [...]
    658     FragColor.rgb = Normal;
    659     FragColor.a = 1.0f;
    660 }
    661 </code></pre>
    662 
    663 <p>
    664   By outputting a (non-color) variable to the output color channel like this we can quickly inspect if the variable is, as far as you can tell, displaying correct values. If, for instance, the visual result is completely black it is clear the normal vectors aren't correctly passed to the shaders; and when they are displayed it's relatively easy to check if they're (sort of) correct or not:
    665 </p>
    666 
    667 <img src="/img/in-practice/debugging_glsl_output.png" alt="The image of a 3D model with its normal vectors displayed as the fragment shader output in OpenGL for debugging"/>
    668   
    669 <p>
    670   From the visual results we can see the world-space normal vectors appear to be correct as the right sides of the backpack model is mostly colored red (which would mean the normals roughly point (correctly) towards the positive x axis). Similarly, the front side of the backpack is mostly colored towards the positive z axis (blue). 
    671 </p>
    672   
    673 <p>
    674   This approach can easily extend to any type of variable you'd like to test. Whenever you get stuck and suspect there's something wrong with your shaders, try displaying multiple variables and/or intermediate results to see at which part of the algorithm something's missing or seemingly incorrect.
    675 </p>
    676   
    677 <h2>OpenGL GLSL reference compiler</h2>
    678 <p>
    679   Each driver has its own quirks and tidbits; for instance, NVIDIA drivers are more flexible and tend to overlook some restrictions on the specification, while ATI/AMD drivers tend to better enforce the OpenGL specification (which is the better approach in my opinion). The result of this is that shaders on one machine may not work on the other due to driver differences. 
    680 </p>
    681   
    682 <p>
    683   With years of experience you'll eventually get to learn the minor differences between GPU vendors, but if you want to be sure your shader code runs on all kinds of machines you can directly check your shader code against the official specification using OpenGL's GLSL <a href="https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/" target="_blank">reference compiler</a>. You can download the so called <def>GLSL lang validator</def> binaries from <a href="https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/" target="_blank">here</a> or its complete source code from <a href="https://github.com/KhronosGroup/glslang" target="_blank">here</a>.
    684 </p>
    685   
    686 <p>
    687   Given the binary GLSL lang validator you can easily check your shader code by passing it as the binary's first argument. Keep in mind that the GLSL lang validator determines the type of shader by a list of fixed extensions:
    688 <p>
    689   
    690 <ul>
    691   <li><code>.vert</code>: vertex shader.</li>
    692   <li><code>.frag</code>: fragment shader.</li>
    693   <li><code>.geom</code>: geometry shader.</li>
    694   <li><code>.tesc</code>: tessellation control shader.</li>
    695   <li><code>.tese</code>: tessellation evaluation shader.</li>
    696   <li><code>.comp</code>: compute shader.</li>
    697 </ul>
    698   
    699 <p>
    700   Running the GLSL reference compiler is as simple as:
    701 </p>
    702   
    703 <pre><code>
    704 glsllangvalidator shaderFile.vert  
    705 </code></pre>
    706   
    707 <p>
    708   Note that if it detects no error, it returns no output. Testing the GLSL reference compiler on a broken vertex shader gives the following output:
    709 </p>
    710   
    711   <img src="/img/in-practice/debugging_glsl_reference_compiler.png" alt="Output of the GLSL reference compiler (GLSL lang validator) in OpenGL"/>
    712     
    713 <p>
    714   It won't show you the subtle differences between AMD, NVidia, or Intel GLSL compilers, nor will it help you completely bug proof your shaders, but it does at least help you to check your shaders against the direct GLSL specification. 
    715 </p>
    716 
    717 <h2>Framebuffer output</h2>
    718 <p>
    719   Another useful trick for your debugging toolkit is displaying a framebuffer's content(s) in some pre-defined region of your screen. You're likely to use  <a href="https://learnopengl.com/Advanced-OpenGL/Framebuffers" target="_blank">framebuffers</a> quite often and, as most of their magic happens behind the scenes, it's sometimes difficult to figure out what's going on. Displaying the content(s) of a framebuffer on your screen is a useful trick to quickly see if things look correct.
    720 </p>
    721 
    722 <note>
    723    Note that displaying the contents (attachments) of a framebuffer as explained here only works on texture attachments, not render buffer objects.
    724 </note>
    725   
    726 <p>
    727   Using a simple shader that only displays a texture, we can easily write a small helper function to quickly display any texture at the top-right of the screen:
    728 </p>
    729   
    730 <pre><code>
    731 // vertex shader
    732 #version 330 core
    733 layout (location = 0) in vec2 position;
    734 layout (location = 1) in vec2 texCoords;
    735 
    736 out vec2 TexCoords;
    737 
    738 void main()
    739 {
    740     gl_Position = vec4(position, 0.0f, 1.0f);
    741     TexCoords = texCoords;
    742 }
    743   
    744 // fragment shader
    745 #version 330 core
    746 out vec4 FragColor;
    747 in  vec2 TexCoords;
    748   
    749 uniform sampler2D fboAttachment;
    750   
    751 void main()
    752 {
    753     FragColor = texture(fboAttachment, TexCoords);
    754 } 
    755 </code></pre>
    756   
    757 <pre><code>  
    758 void DisplayFramebufferTexture(unsigned int textureID)
    759 {
    760     if (!notInitialized)
    761     {
    762         // initialize shader and vao w/ NDC vertex coordinates at top-right of the screen
    763         [...]
    764     }
    765   
    766     <function id='49'>glActiveTexture</function>(GL_TEXTURE0);  	
    767     <function id='28'>glUseProgram</function>(shaderDisplayFBOOutput);
    768         <function id='48'>glBindTexture</function>(GL_TEXTURE_2D, textureID);
    769         <function id='27'>glBindVertexArray</function>(vaoDebugTexturedRect);
    770             <function id='1'>glDrawArrays</function>(GL_TRIANGLES, 0, 6);
    771         <function id='27'>glBindVertexArray</function>(0);
    772     <function id='28'>glUseProgram</function>(0);
    773 }
    774   
    775 int main()
    776 {
    777     [...]
    778     while (!<function id='14'>glfwWindowShouldClose</function>(window))
    779     {
    780         [...]
    781         DisplayFramebufferTexture(fboAttachment0);
    782         
    783         <function id='24'>glfwSwapBuffers</function>(window);
    784     }
    785 }  
    786 </code></pre>
    787 
    788 <p>
    789   This will give you a nice little window at the corner of your screen for debugging framebuffer output. Useful, for example, for determining if the normal vectors of the geometry pass in a deferred renderer look correct:
    790 </p>
    791   
    792   <img src="/img/in-practice/debugging_fbo_output.png" alt="Framebuffer attachment output to a texture for debugging purposes in OpenGL"/>
    793 
    794 <p>
    795   You can of course extend such a utility function to support rendering more than one texture. This is a quick and dirty way to get continuous feedback from whatever is in your framebuffer(s).
    796 </p>
    797 
    798 <h2>External debugging software</h2>
    799 <p>
    800   When all else fails there is still the option to use a 3rd party tool to help us in our debugging efforts. Third party applications often inject themselves in the OpenGL drivers and are able to intercept all kinds of OpenGL calls to give you a large array of interesting data. These tools can help you in all kinds of ways like: profiling OpenGL function usage, finding bottlenecks, inspecting buffer memory, and displaying textures and framebuffer attachments. When you're working on (large) production code, these kinds of tools can become invaluable in your development process.
    801 </p>
    802     
    803 <p>
    804     I've listed some of the more popular debugging tools here; try out several of them to see which fits your needs the best.
    805 </p>
    806     
    807 <!--<h3>gDebugger</h3>
    808 <p>
    809   gDebugger is a cross-platform and easy to use debugging tool for OpenGL applications. gDebugger sits alongside your running OpenGL application and provides a detailed overview of the running OpenGL state. You can pause the application at any moment to inspect the current state, texture memory and/or buffer usage. You can download gDebugger <a href="http://www.gremedy.com/" target="_blank">here</a>.
    810 </p>
    811     
    812 <p>
    813   Running gDebugger is as easy as opening the application, creating a new project and giving it the location and working directory of your OpenGL executable.
    814 </p>
    815     
    816     <img src="/img/in-practice/debugging_external_gdebugger.png" alt="Image of gDebugger running on an OpenGL application.">
    817 -->      
    818     
    819 <!--<h3>APItrace</h3>
    820 <p>
    821  <a href="https://github.com/apitrace/apitrace" target="_blank">APItrace</a>
    822 </p>-->
    823     
    824 <h3>RenderDoc</h3>
    825 <p>
    826   RenderDoc is a great (completely <a href="https://github.com/baldurk/renderdoc" target="_blank">open source</a>) standalone debugging tool. To start a capture, you specify the executable you'd like to capture and a working directory. The application then runs as usual, and whenever you want to inspect a particular frame, you let RenderDoc capture one or more frames at the executable's current state. Within the captured frame(s) you can view the pipeline state, all OpenGL commands, buffer storage, and textures in use.
    827 </p>
    828       
    829 <img src="/img/in-practice/debugging_external_renderdoc.png" alt="Image of RenderDoc running on an OpenGL application."/>
    830     
    831 <h3>CodeXL</h3>
    832 <p>
    833   <a href="https://gpuopen.com/compute-product/codexl/" target="_blank">CodeXL</a> is GPU debugging tool released as both a standalone tool and a Visual Studio plugin. CodeXL gives a good set of information and is great for profiling graphics applications. CodeXL also works on NVidia or Intel cards, but without support for OpenCL debugging.
    834 </p>
    835   
    836   <img src="/img/in-practice/debugging_external_codexl.png" alt="Image of CodeXL running on an OpenGL application."/>
    837     
    838 <p>
    839   I personally don't have much experience with CodeXL since I found RenderDoc easier to use, but I've included it anyways as it looks to be a pretty solid tool and developed by one of the larger GPU manufacturers.
    840 </p>
    841     
    842 <h3>NVIDIA Nsight</h3>
    843 <p>
    844   NVIDIA's popular <a href="https://developer.nvidia.com/nvidia-nsight-visual-studio-edition" target="_blank">Nsight</a> GPU debugging tool is not a standalone tool, but a plugin to either the Visual Studio IDE or the Eclipse IDE (NVIDIA now has a <a href="https://developer.nvidia.com/nsight-graphics" target="_blank">standalone version</a> as well). The Nsight plugin is an incredibly useful tool for graphics developers as it gives a large host of run-time statistics regarding GPU usage and the frame-by-frame GPU state. 
    845     </p>
    846     
    847 <p>
    848   The moment you start your application from within Visual Studio (or Eclipse), using Nsight's debugging or profiling commands, Nsight will run within the application itself. The great thing about Nsight is that it renders an overlay GUI system from within your application that you can use to gather all kinds of interesting information about your application, both at run-time and during frame-by-frame analysis. 
    849 </p>
    850   
    851   <img src="/img/in-practice/debugging_external_nsight.png" alt="Image of RenderDoc running on an OpenGL application."/>
    852     
    853 <p>
    854   Nsight is an incredibly useful tool, but it does come with one major drawback in that it only works on NVIDIA cards. If you are working on NVIDIA cards (and use Visual Studio) it's definitely worth a shot.
    855 </p>
    856 
    857 <p>
    858   I'm sure there's plenty of other debugging tools I've missed (some that come to mind are Valve's <a href="https://github.com/ValveSoftware/vogl" target="_blank">VOGL</a> and <a href="https://apitrace.github.io/" target="_blank">APItrace</a>), but I feel this list should already get you plenty of tools to experiment with. 
    859 </p>
    860 
    861 <h2>Additional resources</h2>
    862 <ul>
    863   <li><a href="http://retokoradi.com/2014/04/21/opengl-why-is-your-code-producing-a-black-window/" target="_blank">Why is your code producing a black window</a>: list of general causes by Reto Koradi of why your screen may not be producing any output.</li>
    864   <li><a href="https://vallentin.dev/2015/02/23/debugging-opengl" target="_blank">Debug Output in OpenGL</a>: an extensive debug output write-up by Vallentin with detailed information on setting up a debug context on multiple windowing systems.</li>
    865 </ul>       
    866 
    867     </div>
    868     
    869     <div id="hover">
    870         HI
    871     </div>
    872    <!-- 728x90/320x50 sticky footer -->
    873 <div id="waldo-tag-6196"></div>
    874 
    875    <div id="disqus_thread"></div>
    876 
    877     
    878 
    879 
    880 </div> <!-- container div -->
    881 
    882 
    883 </div> <!-- super container div -->
    884 </body>
    885 </html>
    886 	</main>
    887 </body>
    888 </html>