LearnOpenGL

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

Blending.html (36464B)


      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">Blending</h1>
    320 <h1 id="content-url" style='display:none;'>Advanced-OpenGL/Blending</h1>
    321 <p>
    322   <def>Blending</def> in OpenGL is commonly known as the technique to implement <def>transparency</def> within objects. Transparency is all about objects (or parts of them) not having a solid color, but having a combination of colors from the object itself and any other object behind it with varying intensity. A colored glass window is a transparent object; the glass has a color of its own, but the resulting color contains the colors of all the objects behind the glass as well. This is also where the name blending comes from, since we <def>blend</def> several pixel colors (from different objects) to a single color. Transparency thus allows us to see through objects.
    323 </p>
    324 
    325 <img src="/img/advanced/blending_transparency.png" class="clean" alt="Image of full transparent window and partially transparent window"/>
    326 
    327 <p>
    328   Transparent objects can be completely transparent (letting all colors through) or partially transparent (letting colors through, but also some of its own colors). The amount of transparency of an object is defined by its color's <def>alpha</def> value. The alpha color value is the 4th component of a color vector that you've probably seen quite often now. Up until this chapter, we've always kept this 4th component at a value of <code>1.0</code> giving the object <code>0.0</code> transparency. An alpha value of <code>0.0</code> would result in the object having complete transparency. An alpha value of <code>0.5</code> tells us the object's color consist of 50% of its own color and 50% of the colors behind the object.
    329 </p>
    330 
    331 <p>
    332   The textures we've used so far all consisted of <code>3</code> color components: red, green and blue, but some textures also have an embedded alpha channel that contains an <def>alpha</def> value per texel. This alpha value tells us exactly which parts of the texture have transparency and by how much. For example, the following <a href="/img/advanced/blending_transparent_window.png" target="_blank">window texture</a> has an alpha value of <code>0.25</code> at its glass part and an alpha value of <code>0.0</code> at its corners. The glass part would normally be completely red, but since it has 75% transparency it largely shows the page's background through it, making it seem a lot less red:
    333 </p>
    334 
    335 <img src="/img/advanced/blending_transparent_window.png" class="clean" alt="Texture image of window with transparency"/>
    336 
    337 <p>
    338   We'll soon be adding this windowed texture to the scene from the depth testing chapter, but first we'll discuss an easier technique to implement transparency for pixels that are either fully transparent or fully opaque.
    339 </p>
    340 
    341 <h2>Discarding fragments</h2>
    342 <p>
    343   Some effects do not care about partial transparency, but either want to show something or nothing at all based on the color value of a texture. Think of grass; to create something like grass with little effort you generally paste a grass texture onto a 2D quad and place that quad into your scene. However, grass isn't exactly shaped like a 2D square so you only want to display some parts of the grass texture and ignore the others.
    344 </p>
    345 
    346 <p>
    347   The following <a href="/img/textures/grass.png" target="_blank">texture</a> is exactly such a texture where it either is full opaque (an alpha value of <code>1.0</code>) or it is fully transparent (an alpha value of <code>0.0</code>) and nothing in between. You can see that wherever there is no grass, the image shows the page's background color instead of its own.
    348 </p>
    349 
    350 <img src="/img/textures/grass.png" class="clean" style="width:384px; height:384px;" alt="Texture image of grass with transparency"/>
    351 
    352 <p>
    353   So when adding vegetation to a scene we don't want to see a square image of grass, but rather only show the actual grass and see through the rest of the image. We want to <def>discard</def> the fragments that show the transparent parts of the texture, not storing that fragment into the color buffer. 
    354 </p>
    355 
    356 <p>
    357   Before we get into that we first need to learn how to load a transparent texture. To load textures with alpha values there's not much we need to change. <code>stb_image</code> automatically loads an image's alpha channel if it's available, but we do need to tell OpenGL our texture now uses an alpha channel in the texture generation procedure: 
    358 </p>
    359 
    360 <pre class="cpp"><code>
    361 <function id='52'>glTexImage2D</function>(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);  
    362 </code></pre>
    363 
    364 <p>
    365   Also make sure that you retrieve all <code>4</code> color components of the texture in the fragment shader, not just the RGB components:
    366 </p>
    367 
    368 <pre><code>
    369 void main()
    370 {
    371     // FragColor = vec4(vec3(texture(texture1, TexCoords)), 1.0);
    372     FragColor = texture(texture1, TexCoords);
    373 }
    374 </code></pre>
    375 
    376 <p>
    377   Now that we know how to load transparent textures it's time to put it to the test by adding several of these leaves of grass throughout the basic scene introduced in the <a href="https://learnopengl.com/Advanced-OpenGL/Depth-testing" target="_blank">depth testing</a> chapter.
    378 </p>
    379 
    380 <p>
    381   We create a small <code>vector</code> array where we add several <code>glm::vec3</code> vectors to represent the location of the grass leaves:
    382 </p>
    383 
    384 <pre><code>
    385 vector&lt;glm::vec3&gt; vegetation;
    386 vegetation.push_back(glm::vec3(-1.5f,  0.0f, -0.48f));
    387 vegetation.push_back(glm::vec3( 1.5f,  0.0f,  0.51f));
    388 vegetation.push_back(glm::vec3( 0.0f,  0.0f,  0.7f));
    389 vegetation.push_back(glm::vec3(-0.3f,  0.0f, -2.3f));
    390 vegetation.push_back(glm::vec3( 0.5f,  0.0f, -0.6f));  
    391 </code></pre>
    392 
    393 <p>
    394   Each of the grass objects is rendered as a single quad with the grass texture attached to it. It's not a perfect 3D representation of grass, but it's a lot more efficient than loading and rendering a large number of complex models. With a few tricks like adding randomized rotations and scales you can get pretty convincing results with quads.
    395 </p>
    396 
    397 <p>
    398 Because the grass texture is going to be displayed on a quad object we'll need to create another VAO again, fill the VBO, and set the appropriate vertex attribute pointers. Then after we've rendered the floor and the two cubes we're going to render the grass leaves:
    399 </p>
    400 
    401 <pre><code>
    402 <function id='27'>glBindVertexArray</function>(vegetationVAO);
    403 <function id='48'>glBindTexture</function>(GL_TEXTURE_2D, grassTexture);  
    404 for(unsigned int i = 0; i &lt; vegetation.size(); i++) 
    405 {
    406     model = glm::mat4(1.0f);
    407     model = <function id='55'>glm::translate</function>(model, vegetation[i]);				
    408     shader.setMat4("model", model);
    409     <function id='1'>glDrawArrays</function>(GL_TRIANGLES, 0, 6);
    410 }  
    411 </code></pre>
    412 
    413 <p>
    414   Running the application will now look a bit like this:
    415 </p>
    416 
    417 <img src="/img/advanced/blending_no_discard.png" class="clean" alt="Not discarding transparent parts of texture results in weird artifacts in OpenGL"/>
    418 
    419 <p>
    420   This happens because OpenGL by default does not know what to do with alpha values, nor when to discard them. We have to manually do this ourselves. Luckily this is quite easy thanks to the use of shaders. GLSL gives us the  <code>discard</code> command that (once called) ensures the fragment will not be further processed and thus not end up into the color buffer. Thanks to this command we can check whether a fragment has an alpha value below a certain threshold and if so, discard the fragment as if it had never been processed:
    421 </p>
    422 
    423 <pre><code>
    424 #version 330 core
    425 out vec4 FragColor;
    426 
    427 in vec2 TexCoords;
    428 
    429 uniform sampler2D texture1;
    430 
    431 void main()
    432 {             
    433     vec4 texColor = texture(texture1, TexCoords);
    434     if(texColor.a &lt; 0.1)
    435         discard;
    436     FragColor = texColor;
    437 }
    438 </code></pre>
    439 
    440 
    441 <p>
    442   Here we check if the sampled texture color contains an alpha value lower than a threshold of <code>0.1</code> and if so, discard the fragment. This fragment shader ensures us that it only renders fragments that are not (almost) completely transparent. Now it'll look like it should:
    443 </p>
    444 
    445 
    446 <img src="/img/advanced/blending_discard.png" class="clean" alt="Image of grass leaves rendered with fragment discarding in OpenGL"/>
    447 
    448 <note>
    449   Note that when sampling textures at their borders, OpenGL interpolates the border values with the next repeated value of the texture (because we set its wrapping parameters to <var>GL_REPEAT</var> by default). This is usually okay, but since we're using transparent values, the top of the texture image gets its transparent value interpolated with the bottom border's solid color value. The result is then a slightly semi-transparent colored border you may see wrapped around your textured quad. To prevent this, set the texture wrapping method to <var>GL_CLAMP_TO_EDGE</var> whenever you use alpha textures that you don't want to repeat:
    450 
    451 <pre><code>
    452 <function id='15'>glTexParameter</function>i( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);	
    453 <function id='15'>glTexParameter</function>i( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    
    454 </code></pre>
    455 </note>
    456 
    457 <p>
    458   You can find the source code <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/3.1.blending_discard/blending_discard.cpp" target="_blank">here</a>.
    459 </p>
    460 
    461 
    462 <h2>Blending</h2>
    463 <p>
    464   While discarding fragments is great and all, it doesn't give us the flexibility to render semi-transparent images; we either render the fragment or completely discard it. To render images with different levels of transparency we have to enable <def>blending</def>. Like most of OpenGL's functionality we can enable blending by enabling <var>GL_BLEND</var>:
    465 </p>
    466 
    467 <pre><code>
    468 <function id='60'>glEnable</function>(GL_BLEND);  
    469 </code></pre>
    470 
    471 <p>
    472   Now that we've enabled blending we need to tell OpenGL <strong>how</strong> it should actually blend.
    473 </p>
    474 
    475 <p>
    476   Blending in OpenGL happens with the following equation:
    477 </p>
    478 
    479 \begin{equation}\bar{C}_{result} = \bar{\color{green}C}_{source} * \color{green}F_{source} + \bar{\color{red}C}_{destination} * \color{red}F_{destination}\end{equation}
    480 
    481 <ul>
    482   <li>\(\bar{\color{green}C}_{source}\): the source color vector. This is the color output of the fragment shader.</li>
    483   <li>\(\bar{\color{red}C}_{destination}\): the destination color vector. This is the color vector that is currently stored in the color buffer.</li>
    484   <li>\(\color{green}F_{source}\): the source factor value. Sets the impact of the alpha value on the source color.</li>
    485   <li>\(\color{red}F_{destination}\): the destination factor value. Sets the impact of the alpha value on the destination color.</li>  
    486 </ul>
    487 
    488 <p>
    489   After the fragment shader has run and all the tests have passed, this <def>blend equation</def> is let loose on the fragment's color output and with whatever is currently in the color buffer. The source and destination colors will automatically be set by OpenGL, but the source and destination factor can be set to a value of our choosing. Let's start with a simple example:
    490 </p>
    491 
    492 <img src="/img/advanced/blending_equation.png" class="clean" alt="Two squares where one has alpha value lower than 1"/>
    493 
    494 <p>
    495   We have two squares where we want to draw the semi-transparent green square on top of the red square. The red square will be the destination color (and thus should be first in the color buffer) and we are now going to draw the green square over the red square.
    496 </p>
    497 
    498 <p>
    499   The question then arises: what do we set the factor values to? Well, we at least want to multiply the green square with its alpha value so we want to set the \(F_{src}\) equal to the alpha value of the source color vector which is <code>0.6</code>. Then it makes sense to let the destination square have a contribution equal to the remainder of the alpha value. If the green square contributes 60% to the final color we want the red square to contribute 40% of the final color e.g. <code>1.0 - 0.6</code>. So we set \(F_{destination}\) equal to one minus the alpha value of the source color vector. The equation thus becomes:
    500 </p>
    501 
    502 \begin{equation}\bar{C}_{result} = \begin{pmatrix} \color{red}{0.0} \\ \color{green}{1.0} \\ \color{blue}{0.0} \\ \color{purple}{0.6} \end{pmatrix} * \color{green}{0.6} + \begin{pmatrix} \color{red}{1.0} \\ \color{green}{0.0} \\ \color{blue}{0.0} \\ \color{purple}{1.0} \end{pmatrix} * (\color{red}{1 - 0.6}) \end{equation}
    503 
    504 <p>
    505   The result is that the combined square fragments contain a color that is 60% green and 40% red:
    506 </p>
    507 
    508 <img src="/img/advanced/blending_equation_mixed.png" class="clean" alt="Two containers where one has alpha value lower than 1"/>
    509 
    510 <p>
    511   The resulting color is then stored in the color buffer, replacing the previous color. 
    512 </p>
    513 
    514 <p>
    515   So this is great and all, but how do we actually tell OpenGL to use factors like that? Well it just so happens that there is a function for this called <fun><function id='70'>glBlendFunc</function></fun>.
    516 </p>
    517 
    518 <p>
    519   The <fun><function id='70'>glBlendFunc</function>(GLenum sfactor, GLenum dfactor)</fun> function expects two parameters that set the option for the <def>source</def> and <def>destination factor</def>. OpenGL defined quite a few options for us to set of which we'll list the most common options below. Note that the constant color vector \(\bar{\color{blue}C}_{constant}\) can be separately set via the <fun><function id='73'>glBlendColor</function></fun> function. 
    520 </p>
    521 
    522 <table>
    523   <tr>
    524   	<th>Option</th>
    525   	<th>Value</th>
    526   </tr>  
    527   <tr>
    528     <td><code>GL_ZERO</code></td>
    529     <td>Factor is equal to \(0\).</td>
    530   </tr>
    531   <tr>
    532     <td><code>GL_ONE</code></td>
    533  	<td>Factor is equal to \(1\).</td>
    534   </tr>
    535   <tr>
    536     <td><code>GL_SRC_COLOR</code></td>
    537  	<td>Factor is equal to the source color vector \(\bar{\color{green}C}_{source}\).</td>
    538   </tr>
    539   <tr>
    540     <td><code>GL_ONE_MINUS_SRC_COLOR</code></td>
    541  	<td>Factor is equal to \(1\) minus the source color vector: \(1 - \bar{\color{green}C}_{source}\). </td>
    542   </tr><tr>
    543     <td><code>GL_DST_COLOR</code></td>
    544  	<td>Factor is equal to the destination color vector \(\bar{\color{red}C}_{destination}\)</td>
    545   </tr> 
    546   <tr>
    547     <td><code>GL_ONE_MINUS_DST_COLOR</code></td>
    548  	<td>Factor is equal to \(1\) minus the destination color vector: \(1 - \bar{\color{red}C}_{destination}\).</td>
    549   </tr>
    550   <tr>
    551     <td><code>GL_SRC_ALPHA</code></td>
    552  	<td>Factor is equal to the \(alpha\) component of the source color vector \(\bar{\color{green}C}_{source}\).  </td>
    553   </tr>
    554   <tr>
    555     <td><code>GL_ONE_MINUS_SRC_ALPHA</code></td>
    556  	<td>Factor is equal to \(1 - alpha\) of the source color vector \(\bar{\color{green}C}_{source}\).</td>
    557   </tr>
    558   <tr>
    559     <td><code>GL_DST_ALPHA</code></td>
    560  	<td>Factor is equal to the \(alpha\) component of the destination color vector \(\bar{\color{red}C}_{destination}\).  </td>
    561   </tr>
    562   <tr>
    563     <td><code>GL_ONE_MINUS_DST_ALPHA</code></td>
    564  	<td>Factor is equal to \(1 - alpha\) of the destination color vector \(\bar{\color{red}C}_{destination}\).</td>
    565   </tr>
    566   <tr>
    567     <td><code>GL_CONSTANT_COLOR</code></td>
    568  	<td>Factor is equal to the constant color vector \(\bar{\color{blue}C}_{constant}\).  </td>
    569   </tr>
    570   <tr>
    571     <td><code>GL_ONE_MINUS_CONSTANT_COLOR</code></td>
    572  	<td>Factor is equal to \(1\) - the constant color vector \(\bar{\color{blue}C}_{constant}\).</td>
    573   </tr>
    574   <tr>
    575     <td><code>GL_CONSTANT_ALPHA</code></td>
    576  	<td>Factor is equal to the \(alpha\) component of the constant color vector \(\bar{\color{blue}C}_{constant}\).  </td>
    577   </tr>
    578   <tr>
    579     <td><code>GL_ONE_MINUS_CONSTANT_ALPHA</code></td>
    580  	<td>Factor is equal to \(1 - alpha\) of the constant color vector \(\bar{\color{blue}C}_{constant}\).</td>
    581   </tr>
    582 </table>
    583 
    584 <p>
    585   To get the blending result of our little two square example, we want to take the \(alpha\) of the source color vector for the source factor and \(1 - alpha\) of the same color vector for the destination factor. This translates to <fun><function id='70'>glBlendFunc</function></fun> as follows:
    586 </p>
    587 
    588 <pre><code>
    589 <function id='70'>glBlendFunc</function>(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
    590 </code></pre>
    591 
    592 <p>
    593   It is also possible to set different options for the RGB and alpha channel individually using <fun><function id='71'><function id='70'>glBlendFunc</function>Separate</function></fun>:
    594 </p>
    595 
    596 <pre><code>
    597 <function id='71'><function id='70'>glBlendFunc</function>Separate</function>(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
    598 </code></pre>
    599 
    600 <p>
    601   This function sets the RGB components as we've set them previously, but only lets the resulting alpha component be influenced by the source's alpha value.
    602 </p>
    603 
    604 <p>
    605   OpenGL gives us even more flexibility by allowing us to change the operator between the source and destination part of the equation. Right now, the source and destination components are added together, but we could also subtract them if we want. <fun><function id='72'>glBlendEquation</function>(GLenum mode)</fun> allows us to set this operation and has 5 possible options:
    606 </p>
    607 
    608 <ul>
    609   <li><code>GL_FUNC_ADD</code>: the default, adds both colors to each other: \(\bar{C}_{result} = \color{green}{Src} + \color{red}{Dst}\).</li>
    610   <li><code>GL_FUNC_SUBTRACT</code>: subtracts both colors from each other: \(\bar{C}_{result} = \color{green}{Src} - \color{red}{Dst}\).</li>
    611   <li><code>GL_FUNC_REVERSE_SUBTRACT</code>: subtracts both colors, but reverses order: \(\bar{C}_{result} = \color{red}{Dst} - \color{green}{Src}\).</li>
    612   <li><code>GL_MIN</code>: takes the component-wise minimum of both colors: \(\bar{C}_{result} = min(\color{red}{Dst}, \color{green}{Src})\).</li>
    613   <li><code>GL_MAX</code>: takes the component-wise maximum of both colors: \(\bar{C}_{result} = max(\color{red}{Dst}, \color{green}{Src})\).</li>
    614 </ul>
    615 
    616 <p>
    617   Usually we can simply omit a call to <fun><function id='72'>glBlendEquation</function></fun> because <var>GL_FUNC_ADD</var> is the preferred blending equation for most operations, but if you're really trying your best to break the mainstream circuit any of the other equations could suit your needs.
    618 </p>
    619 
    620 <h2>Rendering semi-transparent textures</h2>
    621 <p>
    622   Now that we know how OpenGL works with regards to blending it's time to put our knowledge to the test by adding several semi-transparent windows. We'll be using the same scene as in the start of this chapter, but instead of rendering a grass texture we're now going to use the <a href="/img/advanced/blending_transparent_window.png" target="_blank">transparent window</a> texture from the start of this chapter.
    623 </p>
    624 
    625 <p>
    626   First, during initialization we enable blending and set the appropriate blending function:
    627 </p>
    628 
    629 <pre><code>
    630 <function id='60'>glEnable</function>(GL_BLEND);
    631 <function id='70'>glBlendFunc</function>(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
    632 </code></pre>
    633 
    634 <p>
    635   Since we enabled blending there is no need to discard fragments so we'll reset the fragment shader to its original version:
    636 </p>
    637 
    638 <pre><code>
    639 #version 330 core
    640 out vec4 FragColor;
    641 
    642 in vec2 TexCoords;
    643 
    644 uniform sampler2D texture1;
    645 
    646 void main()
    647 {             
    648     FragColor = texture(texture1, TexCoords);
    649 }  
    650 </code></pre>
    651 
    652 <p>
    653   This time (whenever OpenGL renders a fragment) it combines the current fragment's color with the fragment color currently in the color buffer based on the alpha value of <var>FragColor</var>. Since the glass part of the window texture is semi-transparent we should be able to see the rest of the scene by looking through this window.
    654 </p>
    655 
    656 
    657 <img src="/img/advanced/blending_incorrect_order.png" class="clean" alt="A blended scene in OpenGL where order is incorrect."/>
    658 
    659 <p>
    660   If you take a closer look however, you may notice something is off. The transparent parts of the front window are occluding the windows in the background. Why is this happening?
    661 </p>
    662 
    663 <p>
    664   The reason for this is that depth testing works a bit tricky combined with blending. When writing to the depth buffer, the depth test does not care if the fragment has transparency or not, so the transparent parts are written to the depth buffer as any other value. The result is that the background windows are tested on depth as any other opaque object would be, ignoring transparency. Even though the transparent part should show the windows behind it, the depth test discards them.
    665 </p>
    666 
    667 <p>
    668   So we cannot simply render the windows however we want and expect the depth buffer to solve all our issues for us; this is also where blending gets a little nasty. To make sure the windows show the windows behind them, we have to draw the windows in the background first. This means we have to manually sort the windows from furthest to nearest and draw them accordingly ourselves.
    669 </p>
    670 
    671 <note>
    672   Note that with fully transparent objects like the grass leaves we have the option to discard the transparent fragments instead of blending them, saving us a few of these headaches (no depth issues).
    673 </note>
    674 
    675 <h2>Don't break the order</h2>
    676 <p>
    677   To make blending work for multiple objects we have to draw the most distant object first and the closest object last. The normal non-blended objects can still be drawn as normal using the depth buffer so they don't have to be sorted. We do have to make sure they are drawn first before drawing the (sorted) transparent objects. When drawing a scene with non-transparent and transparent objects the general outline is usually as follows:
    678 </p>
    679 
    680 <ol>
    681   <li>Draw all opaque objects first.</li>
    682   <li>Sort all the transparent objects.</li>
    683   <li>Draw all the transparent objects in sorted order.</li>
    684 </ol>
    685 
    686 <p>
    687   One way of sorting the transparent objects is to retrieve the distance of an object from the viewer's perspective. This can be achieved by taking the distance between the camera's position vector and the object's position vector. We then store this distance together with the corresponding position vector in a <fun>map</fun> data structure from the STL library. A <fun>map</fun> automatically sorts its values based on its keys, so once we've added all positions with their distance as the key they're automatically sorted on their distance value:
    688 </p>
    689 
    690 <pre><code>
    691 std::map&lt;float, glm::vec3&gt; sorted;
    692 for (unsigned int i = 0; i &lt; windows.size(); i++)
    693 {
    694     float distance = glm::length(camera.Position - windows[i]);
    695     sorted[distance] = windows[i];
    696 }
    697 </code></pre>
    698 
    699 <p>
    700   The result is a sorted container object that stores each of the window positions based on their <var>distance</var> key value from lowest to highest distance.
    701 </p>
    702 
    703 <p>
    704   Then, this time when rendering, we take each of the map's values in reverse order (from farthest to nearest) and then draw the corresponding windows in correct order:
    705 </p>
    706 
    707 <pre><code>
    708 for(std::map&lt;float,glm::vec3&gt;::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); ++it) 
    709 {
    710     model = glm::mat4(1.0f);
    711     model = <function id='55'>glm::translate</function>(model, it-&gt;second);				
    712     shader.setMat4("model", model);
    713     <function id='1'>glDrawArrays</function>(GL_TRIANGLES, 0, 6);
    714 }  
    715 </code></pre>
    716 
    717 <p>
    718   We take a reverse iterator from the <fun>map</fun> to iterate through each of the items in reverse order and then translate each window quad to the corresponding window position. This relatively simple approach to sorting transparent objects fixes the previous problem and now the scene looks like this:
    719 </p>
    720 
    721 <img src="/img/advanced/blending_sorted.png" class="clean" alt="Image of an OpenGL scene with blending enabled, objects are sorted from far to near"/>
    722 
    723 <p>
    724   You can find the complete source code with sorting <a href="/code_viewer_gh.php?code=src/4.advanced_opengl/3.2.blending_sort/blending_sorted.cpp" target="_blank">here</a>.
    725 </p>
    726 
    727 <p>
    728   While this approach of sorting the objects by their distance works well for this specific scenario, it doesn't take rotations, scaling or any other transformation into account and weirdly shaped objects need a different metric than simply a position vector. 
    729 </p>
    730 
    731 <p>
    732   Sorting objects in your scene is a difficult feat that depends greatly on the type of scene you have, let alone the extra processing power it costs. Completely rendering a scene with solid and transparent objects isn't all that easy. There are more advanced techniques like <def>order independent transparency</def> but these are out of the scope of this chapter. For now you'll have to live with normally blending your objects, but if you're careful and know the limitations you can get pretty decent blending implementations.
    733 </p>
    734        
    735 
    736     </div>
    737     
    738 	</main>
    739 </body>
    740 </html>