LearnOpenGL

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

Stencil-testing.html (28827B)


      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     <div id="content">
    319     <h1 id="content-title">Stencil testing</h1>
    320 <h1 id="content-url" style='display:none;'>Advanced-OpenGL/Stencil-testing</h1>
    321 <p>
    322   Once the fragment shader has processed the fragment a so called <def>stencil test</def> is executed that, just like the depth test, has the option to discard fragments. After that the remaining fragments are passed to the depth test where OpenGL could possibly discard even more fragments. The stencil test is based on the content of yet another buffer called the <def>stencil buffer</def> that we're allowed to update during rendering to achieve interesting effects.
    323 </p>
    324 
    325 <p>
    326   A stencil buffer (usually) contains <code>8</code> bits per <def>stencil value</def> that amounts to a total of <code>256</code> different stencil values per pixel. We can set these stencil values to values of our liking and we can discard or keep fragments whenever a particular fragment has a certain stencil value.
    327 </p>
    328 
    329 <note>
    330   Each windowing library needs to set up a stencil buffer for you. GLFW does this automatically so we don't have to tell GLFW to create one, but other windowing libraries may not create a stencil buffer by default so be sure to check your library's documentation.
    331 </note>
    332 
    333 <p>
    334   A simple example of a stencil buffer is shown below (pixels not-to-scale):
    335 </p>
    336 
    337 <img src="/img/advanced/stencil_buffer.png" class="clean" alt="A simple demonstration of a stencil buffer"/>
    338 
    339 <p>
    340   The stencil buffer is first cleared with zeros and then an open rectangle of <code>1</code>s is stored in the stencil buffer. The fragments of the scene are then only rendered (the others are discarded) wherever the stencil value of that fragment contains a <code>1</code>. 
    341 </p>
    342   
    343 <p>
    344 	Stencil buffer operations allow us to set the stencil buffer at specific values wherever we're rendering fragments. By changing the content of the stencil buffer while we're rendering,  we're <em>writing</em> to the stencil buffer. In the same (or following) frame(s) we can <em>read</em> these values to discard or pass certain fragments. When using stencil buffers you can get as crazy as you like, but the general outline is usually as follows:
    345 </p>
    346 
    347 <ul>
    348   <li>Enable writing to the stencil buffer.</li>
    349   <li>Render objects, updating the content of the stencil buffer.</li>
    350   <li>Disable writing to the stencil buffer.</li>
    351   <li>Render (other) objects, this time discarding certain fragments based on the content of the stencil buffer.</li>
    352 </ul>
    353 
    354 <p>
    355   By using the stencil buffer we can thus discard certain fragments based on the fragments of other drawn objects in the scene.
    356 </p>
    357   
    358 <p>
    359   You can enable stencil testing by enabling <var>GL_STENCIL_TEST</var>. From that point on, all rendering calls will influence the stencil buffer in one way or another.
    360 </p>
    361   
    362 <pre><code>
    363 <function id='60'>glEnable</function>(GL_STENCIL_TEST);    
    364 </code></pre>
    365 
    366 <p>
    367   Note that you also need to clear the stencil buffer each iteration just like the color and depth buffer:
    368 </p>
    369 
    370 <pre><code>
    371 <function id='10'>glClear</function>(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 
    372 </code></pre>
    373   
    374 <p>
    375   Also, just like the depth testing's <fun><function id='65'>glDepthMask</function></fun> function, there is an equivalent function for the stencil buffer. The function <fun><function id='67'>glStencilMask</function></fun> allows us to set a bitmask that is <code>AND</code>ed with the stencil value about to be written to the buffer. By default this is set to a bitmask of all <code>1</code>s not affecting the output, but if we were to set this to <code>0x00</code> all the stencil values written to the buffer end up as <code>0</code>s. This is equivalent to depth testing's <fun><function id='65'>glDepthMask</function>(GL_FALSE)</fun>:
    376 </p>
    377   
    378 <pre><code>
    379 <function id='67'>glStencilMask</function>(0xFF); // each bit is written to the stencil buffer as is
    380 <function id='67'>glStencilMask</function>(0x00); // each bit ends up as 0 in the stencil buffer (disabling writes)
    381 </code></pre>
    382   
    383 <p>
    384   Most of the cases you'll only be using <code>0x00</code> or <code>0xFF</code> as the stencil mask, but it's good to know there are options to set custom bit-masks.
    385 </p>
    386   
    387 <h2>Stencil functions</h2>
    388 <p>
    389     Similar to depth testing, we have a certain amount of control over when a stencil test should pass or fail and how it should affect the stencil buffer. There are a total of two functions we can use to configure stencil testing: <fun><function id='68'>glStencilFunc</function></fun> and <fun><function id='69'>glStencilOp</function></fun>.
    390 </p>
    391   
    392 <p>
    393   The <fun><function id='68'>glStencilFunc</function>(GLenum func, GLint ref, GLuint mask)</fun> has three parameters:
    394 </p>
    395   
    396 <ul>
    397   <li><code>func</code>: sets the stencil test function that determines whether a fragment passes or is discarded. This test function is applied to the stored stencil value and the <fun><function id='68'>glStencilFunc</function></fun>'s <code>ref</code> value. Possible options are: <var>GL_NEVER</var>, <var>GL_LESS</var>, <var>GL_LEQUAL</var>, <var>GL_GREATER</var>, <var>GL_GEQUAL</var>, <var>GL_EQUAL</var>, <var>GL_NOTEQUAL</var> and <var>GL_ALWAYS</var>. The semantic meaning of these is similar to the depth buffer's functions.</li>
    398   <li><code>ref</code>: specifies the reference value for the stencil test. The stencil buffer's content is compared to this value.</li>
    399   <li><code>mask</code>: specifies a mask that is <code>AND</code>ed with both the reference value and the stored stencil value before the test compares them. Initially set to all <code>1</code>s.</li>
    400 </ul>
    401   
    402 <p>
    403    So in the case of the simple stencil example we've shown at the start, the function would be set to:
    404 </p>
    405 
    406 <pre class="cpp"><code>
    407 <function id='68'>glStencilFunc</function>(GL_EQUAL, 1, 0xFF)
    408 </code></pre>
    409 
    410 <p>
    411   This tells OpenGL that whenever the stencil value of a fragment is equal (<var>GL_EQUAL</var>) to the reference value <code>1</code>, the fragment passes the test and is drawn, otherwise discarded.  
    412 </p>
    413   
    414 <p>
    415   But <fun><function id='68'>glStencilFunc</function></fun> only describes whether OpenGL should pass or discard fragments based on the stencil buffer's content, not how we can actually update the buffer. That is where <fun><function id='69'>glStencilOp</function></fun> comes in.
    416 </p>
    417   
    418   <p>
    419     The <fun><function id='69'>glStencilOp</function>(GLenum sfail, GLenum dpfail, GLenum dppass)</fun> contains three options of which we can specify for each option what action to take:
    420   </p>
    421   
    422   <ul>
    423     <li><code>sfail</code>: action to take if the stencil test fails.</li>
    424     <li><code>dpfail</code>: action to take if the stencil test passes, but the depth test fails.</li>
    425     <li><code>dppass</code>: action to take if both the stencil and the depth test pass.</li>    
    426   </ul>
    427   
    428 <p>
    429   Then for each of the options you can take any of the following actions:
    430 </p>  
    431   
    432 <table>
    433   <tr>
    434   	<th>Action</th>
    435   	<th>Description</th>
    436   </tr>  
    437   <tr>
    438     <td><code>GL_KEEP</code></td>
    439  	<td>The currently stored stencil value is kept.</td>
    440   </tr>
    441   <tr>
    442     <td><code>GL_ZERO</code></td>
    443  	<td>The stencil value is set to <code>0</code>.</td>
    444   </tr>
    445   <tr>
    446     <td><code>GL_REPLACE</code></td>
    447  	<td>The stencil value is replaced with the reference value set with <fun><function id='68'>glStencilFunc</function></fun>.</td>
    448   </tr>
    449   <tr>
    450     <td><code>GL_INCR</code></td>
    451  	<td>The stencil value is increased by <code>1</code> if it is lower than the maximum value. </td>
    452   </tr><tr>
    453     <td><code>GL_INCR_WRAP</code></td>
    454  	<td>Same as <var>GL_INCR</var>, but wraps it back to <code>0</code> as soon as the maximum value is exceeded.</td>
    455   </tr> 
    456   <tr>
    457     <td><code>GL_DECR</code></td>
    458  	<td>The stencil value is decreased by <code>1</code> if it is higher than the minimum value.</td>
    459   </tr>
    460   <tr>
    461     <td><code>GL_DECR_WRAP</code></td>
    462  	<td>Same as <var>GL_DECR</var>, but wraps it to the maximum value if it ends up lower than <code>0</code>.</td>
    463   </tr>
    464   <tr>
    465     <td><code>GL_INVERT</code></td>
    466  	<td>Bitwise inverts the current stencil buffer value.</td>
    467   </tr>
    468 </table>
    469 
    470 <p>
    471   By default the <fun><function id='69'>glStencilOp</function></fun> function is set to <code>(GL_KEEP, GL_KEEP, GL_KEEP)</code> so whatever the outcome of any of the tests, the stencil buffer keeps its values. The default behavior does not update the stencil buffer, so if you want to write to the stencil buffer you need to specify at least one different action for any of the options.
    472 </p>
    473 
    474 <p>
    475   So using <fun><function id='68'>glStencilFunc</function></fun> and <fun><function id='69'>glStencilOp</function></fun> we can precisely specify when and how we want to update the stencil buffer and when to pass or discard fragments based on its content.
    476 </p>
    477   
    478 <h1>Object outlining</h1>
    479 <p>
    480    It would be unlikely if you completely understood how stencil testing works from the previous sections alone so we're going to demonstrate a particular useful feature that can be implemented with stencil testing alone called <def>object outlining</def>.
    481 </p>
    482 
    483 <img src="/img/advanced/stencil_object_outlining.png" class="clean" alt="An object outlined using stencil testing/buffer"/>
    484   
    485 <p>
    486   Object outlining does exactly what it says it does. For each object (or only one) we're creating a small colored border around the (combined) objects. This is a particular useful effect when you want to select units in a strategy game for example and need to show the user which of the units were selected. The routine for outlining your objects is as follows:
    487 </p>
    488 
    489 <ol>
    490   <li>Enable stencil writing.</li>
    491   <li>Set the stencil op to <var>GL_ALWAYS</var> before drawing the (to be outlined) objects, updating the stencil buffer with <code>1</code>s wherever the objects' fragments are rendered.</li>
    492   <li>Render the objects.</li>
    493   <li>Disable stencil writing and depth testing.</li>
    494   <li>Scale each of the objects by a small amount.</li>
    495   <li>Use a different fragment shader that outputs a single (border) color.</li>
    496   <li>Draw the objects again, but only if their fragments' stencil values are not equal to <code>1</code>.</li>
    497   <li>Enable depth testing again and restore stencil func to <var>GL_KEEP</var>.</li>
    498 </ol>
    499 
    500 <p>
    501   This process sets the content of the stencil buffer to <code>1</code>s for each of the object's fragments and when it's time to draw the borders, we draw scaled-up versions of the objects only where the stencil test passes. We're effectively discarding all the fragments of the scaled-up versions that are part of the original objects' fragments using the stencil buffer. 
    502 </p>
    503 
    504 <p>
    505   So we're first going to create a very basic fragment shader that outputs a border color. We simply set a hardcoded color value and call the shader <var>shaderSingleColor</var>:
    506 </p>
    507 
    508 <pre><code>
    509 void main()
    510 {
    511     FragColor = vec4(0.04, 0.28, 0.26, 1.0);
    512 }
    513 </code></pre>
    514 
    515 <p>
    516   Using the scene from the <a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing" target="_blank">previous</a> chapter we're going to add object outlining to the two containers, so we'll leave the floor out of it. We want to first draw the floor, then the two containers (while writing to the stencil buffer), and then draw the scaled-up containers (while discarding the fragments that write over the previously drawn container fragments). 
    517 </p>
    518 
    519 <p>
    520   We first need to enable stencil testing: 
    521 </p>
    522 
    523 <pre class="cpp"><code>
    524 <function id='60'>glEnable</function>(GL_STENCIL_TEST);
    525 </code></pre>
    526 
    527 <p>
    528   And then in each frame we want to specify the action to take whenever any of the stencil tests succeed or fail:
    529 </p>
    530 
    531 <pre class="cpp"><code>
    532 <function id='69'>glStencilOp</function>(GL_KEEP, GL_KEEP, GL_REPLACE);  
    533 </code></pre>
    534 
    535 <p>
    536   If any of the tests fail we do nothing; we simply keep the currently stored value that is in the stencil buffer. If both the stencil test and the depth test succeed however, we want to replace the stored stencil value with the reference value set via <fun><function id='68'>glStencilFunc</function></fun> which we later set to <code>1</code>.
    537 </p>
    538 
    539 <p>
    540   We clear the stencil buffer to <code>0</code>s at the start of the frame and for the containers we update the stencil buffer to <code>1</code> for each fragment drawn:
    541 </p>
    542 
    543 <pre><code>
    544 <function id='69'>glStencilOp</function>(GL_KEEP, GL_KEEP, GL_REPLACE);  
    545 <function id='68'>glStencilFunc</function>(GL_ALWAYS, 1, 0xFF); // all fragments should pass the stencil test
    546 <function id='67'>glStencilMask</function>(0xFF); // enable writing to the stencil buffer
    547 normalShader.use();
    548 DrawTwoContainers();
    549 </code></pre>
    550 
    551 <p>
    552   By using <var>GL_REPLACE</var> as the stencil op function we make sure that each of the containers' fragments update the stencil buffer with a stencil value of <code>1</code>. Because the fragments always pass the stencil test, the stencil buffer is updated with the reference value wherever we've drawn them.
    553 </p>
    554 
    555 <p>
    556   Now that the stencil buffer is updated with <code>1</code>s where the containers were drawn we're going to draw the upscaled containers, but this time with the appropriate test function and disabling writes to the stencil buffer:
    557 </p>
    558 
    559 <pre><code>
    560 <function id='68'>glStencilFunc</function>(GL_NOTEQUAL, 1, 0xFF);
    561 <function id='67'>glStencilMask</function>(0x00); // disable writing to the stencil buffer
    562 glDisable(GL_DEPTH_TEST);
    563 shaderSingleColor.use(); 
    564 DrawTwoScaledUpContainers();
    565 </code></pre>
    566 
    567 <p>
    568   We set the stencil function to <var>GL_NOTEQUAL</var> to make sure that we're only drawing parts of the containers that are not equal to <code>1</code>. This way we only draw the part of the containers that are outside the previously drawn containers. Note that we also disable depth testing so the scaled up containers (e.g. the borders) do not get overwritten by the floor. Make sure to enable the depth buffer again once you're done.
    569 </p>
    570 
    571 <p>
    572   The total object outlining routine for our scene looks something like this:
    573 </p>
    574 
    575 <pre><code>
    576 <function id='60'>glEnable</function>(GL_DEPTH_TEST);
    577 <function id='69'>glStencilOp</function>(GL_KEEP, GL_KEEP, GL_REPLACE);  
    578   
    579 <function id='10'>glClear</function>(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 
    580 
    581 <function id='67'>glStencilMask</function>(0x00); // make sure we don't update the stencil buffer while drawing the floor
    582 normalShader.use();
    583 DrawFloor()  
    584   
    585 <function id='68'>glStencilFunc</function>(GL_ALWAYS, 1, 0xFF); 
    586 <function id='67'>glStencilMask</function>(0xFF); 
    587 DrawTwoContainers();
    588   
    589 <function id='68'>glStencilFunc</function>(GL_NOTEQUAL, 1, 0xFF);
    590 <function id='67'>glStencilMask</function>(0x00); 
    591 glDisable(GL_DEPTH_TEST);
    592 shaderSingleColor.use(); 
    593 DrawTwoScaledUpContainers();
    594 <function id='67'>glStencilMask</function>(0xFF);
    595 <function id='68'>glStencilFunc</function>(GL_ALWAYS, 1, 0xFF);   
    596 <function id='60'>glEnable</function>(GL_DEPTH_TEST);  
    597 </code></pre>
    598 
    599 <p>
    600   As long as you understand the general idea behind stencil testing this shouldn't be too hard to understand. Otherwise try to carefully read the previous sections again and try to completely understand what each of the functions does now that you've seen an example of it can be used.
    601 </p>
    602 
    603 <p>
    604   The result of the outlining algorithm then looks like this:
    605 </p>
    606 
    607 
    608 <img src="/img/advanced/stencil_scene_outlined.png" class="clean" alt="3D scene with object outlining using a stencil buffer"/>
    609 
    610 <p>
    611   Check the source code <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/2.stencil_testing/stencil_testing.cpp" target="_blank">here</a> to see the complete code of the object outlining algorithm.
    612 </p>
    613 
    614 <note>
    615   You can see that the borders overlap between both containers which is usually the effect that we want (think of strategy games where we want to select 10 units; merging borders is generally preferred). If you want a complete border per object you'd have to clear the stencil buffer per object and get a little creative with the depth buffer.
    616 </note>
    617 
    618 <p>
    619   The object outlining algorithm you've seen is commonly used in games to visualize selected objects (think of strategy games) and an algorithm like this can easily be implemented within a model class. You could set a boolean flag within the model class to draw either with borders or without. If you want to be creative you could even give the borders a more natural look with the help of post-processing filters like Gaussian Blur.
    620 </p>
    621 
    622 <p>
    623   Stencil testing has many more purposes (beside outlining objects) like drawing textures inside a rear-view mirror so it neatly fits into the mirror shape, or rendering real-time shadows with a stencil buffer technique called <def>shadow volumes</def>. Stencil buffers give us with yet another nice tool in our already extensive OpenGL toolkit.
    624 </p>       
    625 
    626     </div>
    627     
    628 	</main>
    629 </body>
    630 </html>